From a220523b3f80a2377113396f56f029233bd49b74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 23:02:00 +0000 Subject: [PATCH 01/64] Update loom_version to v1.17.11 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 77e4da71..dbe4129f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ org.gradle.configuration-cache=false minecraft_version=1.21.10 yarn_mappings=1.21.10+build.3 loader_version=0.19.2 -loom_version=1.17.3 +loom_version=1.17.11 # Mod Properties mod_version=0.0.0 From 6e3b335d261e497997bf97ba7e345f9f5a855b43 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Mon, 15 Jun 2026 18:50:00 +0200 Subject: [PATCH 02/64] Update dependencies to Minecraft 26.1.2, Fabric Loader 0.19.3, and Fabric API 0.151.0 --- gradle.properties | 7 +++---- gradlew | 2 +- gradlew.bat | 31 +++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/gradle.properties b/gradle.properties index dbe4129f..a57de59b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,9 +7,8 @@ org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.10 -yarn_mappings=1.21.10+build.3 -loader_version=0.19.2 +minecraft_version=26.1.2 +loader_version=0.19.3 loom_version=1.17.11 # Mod Properties @@ -17,4 +16,4 @@ mod_version=0.0.0 maven_group=de.rettichlp # Dependencies -fabric_api_version=0.138.4+1.21.10 +fabric_api_version=0.151.0+26.1.2 diff --git a/gradlew b/gradlew index b9bb139f..739907df 100644 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/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/. diff --git a/gradlew.bat b/gradlew.bat index 24c62d56..c4bdd3ab 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -23,8 +23,8 @@ @rem @rem ########################################################################## -@rem Set local scope for the variables, and ensure extensions are enabled -setlocal EnableExtensions +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ 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 -"%COMSPEC%" /c exit 1 +goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ 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 -"%COMSPEC%" /c exit 1 +goto fail :execute @rem Setup the command line @@ -73,10 +73,21 @@ echo location of your Java installation. 1>&2 @rem Execute Gradle -@rem endlocal doesn't take effect until after the line is parsed and variables are expanded -@rem which allows us to clear the local environment before executing the java command -endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* -:exitWithErrorLevel -@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts -"%COMSPEC%" /c exit %ERRORLEVEL% +:end +@rem End local scope for the variables with windows NT shell +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! +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 From ce8dc16b87b169f6a25d69241cb1d5da081f219a Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 18:59:03 +0200 Subject: [PATCH 03/64] Migrate build scripts to Kotlin DSL --- build.gradle => build.gradle.kts | 48 +++++++++++++++----------------- settings.gradle | 13 --------- settings.gradle.kts | 17 +++++++++++ 3 files changed, 39 insertions(+), 39 deletions(-) rename build.gradle => build.gradle.kts (59%) delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/build.gradle b/build.gradle.kts similarity index 59% rename from build.gradle rename to build.gradle.kts index 5cf8a214..ea342e78 100644 --- a/build.gradle +++ b/build.gradle.kts @@ -1,10 +1,10 @@ plugins { - id 'net.fabricmc.fabric-loom-remap' version "${loom_version}" - id 'maven-publish' + id("net.fabricmc.fabric-loom") + `maven-publish` } -version = project.mod_version -group = project.maven_group +version = providers.gradleProperty("mod_version").get() +group = providers.gradleProperty("maven_group").get() repositories { // Add repositories to retrieve artifacts from in here. @@ -16,37 +16,33 @@ repositories { dependencies { // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + minecraft("com.mojang:minecraft:${providers.gradleProperty("minecraft_version").get()}") + + implementation("net.fabricmc:fabric-loader:${providers.gradleProperty("loader_version").get()}") // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" + implementation("net.fabricmc.fabric-api:fabric-api:${providers.gradleProperty("fabric_api_version").get()}") // https://mvnrepository.com/artifact/org.projectlombok/lombok compileOnly("org.projectlombok:lombok:1.18.46") annotationProcessor("org.projectlombok:lombok:1.18.46") - testCompileOnly("org.projectlombok:lombok:1.18.46") - testAnnotationProcessor("org.projectlombok:lombok:1.18.46") - // https://github.com/atteo/classindex - include("org.atteo.classindex:classindex:3.13") implementation("org.atteo.classindex:classindex:3.13") - annotationProcessor('org.atteo.classindex:classindex:3.13') + annotationProcessor("org.atteo.classindex:classindex:3.13") } -processResources { - def version = project.version - inputs.property "version", version +tasks.processResources { + val version = version + inputs.property("version", version) filesMatching("fabric.mod.json") { - expand "version": version + expand("version" to version) } } -tasks.withType(JavaCompile).configureEach { - it.options.release = 21 +tasks.withType().configureEach { + options.release = 25 } java { @@ -55,13 +51,13 @@ java { // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } -jar { - def projectName = project.name - inputs.property "projectName", projectName +tasks.jar { + val projectName = project.name + inputs.property("projectName", projectName) from("LICENSE") { rename { "${it}_$projectName" } @@ -71,8 +67,8 @@ jar { // configure the maven publication publishing { publications { - create("mavenJava", MavenPublication) { - from components.java + register("mavenJava") { + from(components["java"]) } } diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 04826913..00000000 --- a/settings.gradle +++ /dev/null @@ -1,13 +0,0 @@ -pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() - gradlePluginPortal() - } -} - -// Should match your modid -rootProject.name = 'ucutils' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 00000000..7386f5ad --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + maven { + name = "Fabric" + url = uri("https://maven.fabricmc.net/") + } + mavenCentral() + gradlePluginPortal() + } + + plugins { + id("net.fabricmc.fabric-loom") version providers.gradleProperty("loom_version") + } +} + +// Should match your modid +rootProject.name = "ucutils" From f71ffc23b754c0b8b60a7dd086253923a98aca9e Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 19:01:28 +0200 Subject: [PATCH 04/64] Align with Minecraft 26.1.2 API changes --- .../java/de/rettichlp/ucutils/UCUtils.java | 12 +-- .../rettichlp/ucutils/command/ModCommand.java | 42 ++++----- .../ucutils/command/ScreenshotCommand.java | 36 ++++---- .../ucutils/command/ShutdownCommand.java | 6 +- .../de/rettichlp/ucutils/common/Storage.java | 20 ++-- .../ucutils/common/api/ApiException.java | 2 +- .../common/configuration/options/Options.java | 45 ++++----- .../configuration/options/SoundOptions.java | 15 +-- .../ucutils/common/models/Color.java | 21 +++-- .../ucutils/common/models/Countdown.java | 18 ++-- .../ucutils/common/models/Faction.java | 42 ++++----- .../ucutils/common/models/ScreenshotType.java | 28 +++--- .../ucutils/common/models/ShutdownReason.java | 6 +- .../ucutils/common/models/Sound.java | 25 ++--- .../ucutils/common/registry/Registry.java | 10 +- .../common/services/MessageService.java | 39 ++++---- .../common/services/NameTagService.java | 68 +++++++------- .../common/services/NotificationService.java | 14 +-- .../common/services/RenderService.java | 41 ++++----- .../ucutils/common/services/SyncService.java | 26 +++--- .../ucutils/common/services/UtilService.java | 4 +- .../ucutils/listener/IHudRenderListener.java | 6 +- .../listener/IMessageReceiveListener.java | 4 +- .../ucutils/listener/impl/CarListener.java | 4 +- .../listener/impl/EconomyListener.java | 26 +++--- .../impl/faction/BadFactionListener.java | 31 ++++--- .../faction/EmergencyServiceListener.java | 4 +- .../impl/faction/FactionListener.java | 91 ++++++++++--------- .../listener/impl/job/AnglerListener.java | 61 +++++++------ 29 files changed, 377 insertions(+), 370 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index 6f9b0832..93a29700 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -15,8 +15,8 @@ import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.player.LocalPlayer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,8 +45,8 @@ public class UCUtils implements ModInitializer { public static final Storage storage = new Storage(); public static final Configuration configuration = new Configuration().loadFromFile(); - public static ClientPlayerEntity player; - public static ClientPlayNetworkHandler networkHandler; + public static LocalPlayer player; + public static ClientPacketListener networkHandler; private static final String NEOPROTECT_ENTRYPOINT = "c970141b-0cca-4ad2-894b-21ac9c171cbe.shield.neoprotect.ovh"; @@ -85,7 +85,7 @@ public void onInitialize() { ClientLifecycleEvents.CLIENT_STOPPING.register(client -> configuration.saveToFile()); } - private boolean isUnicaCity(ClientPlayNetworkHandler networkHandler) { + private boolean isUnicaCity(ClientPacketListener networkHandler) { if (getBoolean("fabric.development") || !configuration.getOptions().checkUnicacityServer()) { return true; } @@ -95,7 +95,7 @@ private boolean isUnicaCity(ClientPlayNetworkHandler networkHandler) { return false; } - String addressString = networkHandler.getConnection().getAddress().toString(); + String addressString = networkHandler.getConnection().getRemoteAddress().toString(); // for LabyMod players, there is no dot at the end of the domain if (!addressString.matches(NEOPROTECT_ENTRYPOINT + "\\.?/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}:\\d+")) { LOGGER.warn("Not connected to UnicaCity: {}", addressString); diff --git a/src/main/java/de/rettichlp/ucutils/command/ModCommand.java b/src/main/java/de/rettichlp/ucutils/command/ModCommand.java index a2ecd620..0ee60a08 100644 --- a/src/main/java/de/rettichlp/ucutils/command/ModCommand.java +++ b/src/main/java/de/rettichlp/ucutils/command/ModCommand.java @@ -6,7 +6,8 @@ import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.Person; -import net.minecraft.text.ClickEvent; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -19,12 +20,11 @@ import static de.rettichlp.ucutils.UCUtils.syncService; import static de.rettichlp.ucutils.UCUtils.utilService; import static java.net.URI.create; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.WHITE; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.WHITE; +import static net.minecraft.network.chat.Component.empty; @UCUtilsCommand(label = "ucutils") public class ModCommand extends CommandBase { @@ -50,35 +50,35 @@ public LiteralArgumentBuilder execute(@NotNull Litera String authors = getAuthors(); String contributors = getContributors(); - player.sendMessage(empty(), false); + player.sendSystemMessage(empty()); messageService.sendModMessage("UCUtils Version " + version, false); messageService.sendModMessage(empty() - .append(of("Autoren").copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(of(authors).copy().formatted(WHITE)), false); + .append(Component.literal("Autoren").withStyle(GRAY)) + .append(Component.literal(":").withStyle(DARK_GRAY)).append(" ") + .append(Component.literal(authors).withStyle(WHITE)), false); messageService.sendModMessage(empty() - .append(of("Discord").copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(of("https://discord.gg/mZGAAwhPHu").copy().styled(style -> style + .append(Component.literal("Discord").withStyle(GRAY)) + .append(Component.literal(":").withStyle(DARK_GRAY)).append(" ") + .append(Component.literal("https://discord.gg/mZGAAwhPHu").withStyle(style -> style .withColor(WHITE) .withClickEvent(new ClickEvent.OpenUrl(create("https://discord.gg/mZGAAwhPHu"))))), false); messageService.sendModMessage(empty() - .append(of("GitHub").copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(of("https://github.com/UnicacityAddon/ucutils").copy().styled(style -> style + .append(Component.literal("GitHub").withStyle(GRAY)) + .append(Component.literal(":").withStyle(DARK_GRAY)).append(" ") + .append(Component.literal("https://github.com/UnicacityAddon/ucutils").withStyle(style -> style .withColor(WHITE) .withClickEvent(new ClickEvent.OpenUrl(create("https://github.com/UnicacityAddon/ucutils"))))), false); messageService.sendModMessage(empty() - .append(of("Contributors").copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(of(contributors).copy().formatted(WHITE)), false); + .append(Component.literal("Contributors").withStyle(GRAY)) + .append(Component.literal(":").withStyle(DARK_GRAY)).append(" ") + .append(Component.literal(contributors).withStyle(WHITE)), false); - player.sendMessage(empty(), false); + player.sendSystemMessage(empty()); storage.print(); diff --git a/src/main/java/de/rettichlp/ucutils/command/ScreenshotCommand.java b/src/main/java/de/rettichlp/ucutils/command/ScreenshotCommand.java index c67eabfa..f4d3cc39 100644 --- a/src/main/java/de/rettichlp/ucutils/command/ScreenshotCommand.java +++ b/src/main/java/de/rettichlp/ucutils/command/ScreenshotCommand.java @@ -5,8 +5,9 @@ import de.rettichlp.ucutils.common.registry.CommandBase; import de.rettichlp.ucutils.common.registry.UCUtilsCommand; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -20,14 +21,13 @@ import static java.lang.String.valueOf; import static java.nio.file.Files.list; import static java.util.Arrays.stream; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; -import static net.minecraft.command.CommandSource.suggestMatching; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.AQUA; -import static net.minecraft.util.Formatting.DARK_AQUA; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GRAY; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument; +import static net.minecraft.ChatFormatting.AQUA; +import static net.minecraft.ChatFormatting.DARK_AQUA; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.commands.SharedSuggestionProvider.suggest; +import static net.minecraft.network.chat.Component.empty; @UCUtilsCommand(label = "screenshot") public class ScreenshotCommand extends CommandBase { @@ -36,13 +36,13 @@ public class ScreenshotCommand extends CommandBase { public LiteralArgumentBuilder execute(@NotNull LiteralArgumentBuilder node) { return node .then(argument("screenshotType", greedyString()) - .suggests((context, builder) -> suggestMatching(stream(ScreenshotType.values()).map(ScreenshotType::getDisplayName).toList(), builder)) + .suggests((context, builder) -> suggest(stream(ScreenshotType.values()).map(ScreenshotType::getDisplayName).toList(), builder)) .executes(context -> { // placeholder method: implemented as mixin in ChatScreenMixin return 1; })) .executes(context -> { - player.sendMessage(empty(), false); + player.sendSystemMessage(empty()); messageService.sendModMessage("Screenshots:", false); for (ScreenshotType screenshotType : ScreenshotType.values()) { @@ -56,17 +56,17 @@ public LiteralArgumentBuilder execute(@NotNull Litera } messageService.sendModMessage(empty() - .append(of(screenshotType.getDisplayName()).copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(of(valueOf(fileCount))) - .append(of(" ↗").copy().styled(style -> style + .append(Component.literal(screenshotType.getDisplayName()).withStyle(GRAY)) + .append(Component.literal(":").withStyle(DARK_GRAY)).append(" ") + .append(Component.literal(valueOf(fileCount))) + .append(Component.literal(" ↗").withStyle(style -> style .withColor(AQUA) .withBold(true) - .withHoverEvent(new HoverEvent.ShowText(of("Ordner öffnen").copy().formatted(DARK_AQUA))) + .withHoverEvent(new HoverEvent.ShowText(Component.literal("Ordner öffnen").withStyle(DARK_AQUA))) .withClickEvent(new ClickEvent.OpenFile(screenshotDirectory.getAbsolutePath())))), false); } - player.sendMessage(empty(), false); + player.sendSystemMessage(empty()); return 1; }); } diff --git a/src/main/java/de/rettichlp/ucutils/command/ShutdownCommand.java b/src/main/java/de/rettichlp/ucutils/command/ShutdownCommand.java index f872e244..dff4e61a 100644 --- a/src/main/java/de/rettichlp/ucutils/command/ShutdownCommand.java +++ b/src/main/java/de/rettichlp/ucutils/command/ShutdownCommand.java @@ -8,7 +8,7 @@ import static de.rettichlp.ucutils.common.models.ShutdownReason.CEMETERY; import static de.rettichlp.ucutils.common.models.ShutdownReason.JAIL; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal; @UCUtilsCommand(label = "shutdown") public class ShutdownCommand extends CommandBase { @@ -17,12 +17,12 @@ public class ShutdownCommand extends CommandBase { public LiteralArgumentBuilder execute(@NotNull LiteralArgumentBuilder node) { return node .then(literal("friedhof") - .executes(context -> { + .executes(_ -> { CEMETERY.activate(); return 1; })) .then(literal("gefängnis") - .executes(context -> { + .executes(_ -> { JAIL.activate(); return 1; })); diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index 1851bc70..6d36d8c9 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -11,10 +11,10 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -import net.minecraft.component.type.MapIdComponent; -import net.minecraft.entity.vehicle.MinecartEntity; -import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.vehicle.minecart.Minecart; +import net.minecraft.world.level.saveddata.maps.MapId; import org.jetbrains.annotations.Nullable; import java.time.LocalDateTime; @@ -29,7 +29,7 @@ import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.common.Storage.ToggledChat.NONE; import static de.rettichlp.ucutils.common.models.Faction.NULL; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class Storage { @@ -61,12 +61,12 @@ public class Storage { @Getter @Setter @Nullable - private Vec3d blackMarketPosition; + private Vec3i blackMarketPosition; @Getter @Setter @Nullable - private MapIdComponent captchaMap; + private MapId captchaMap; @Getter @Setter @@ -84,7 +84,7 @@ public class Storage { @Getter @Setter @Nullable - private Vec3d dealerPosition; + private Vec3i dealerPosition; @Getter @Setter @@ -96,7 +96,7 @@ public class Storage { @Getter @Setter - private MinecartEntity minecartEntityToHighlight; + private Minecart minecartEntityToHighlight; @Getter @Setter @@ -188,6 +188,6 @@ public enum ToggledChat { W_CHAT("w", translatable("ucutils.notification.toggled_chat.w")); private final String command; - private final Text toggleMessage; + private final Component toggleMessage; } } diff --git a/src/main/java/de/rettichlp/ucutils/common/api/ApiException.java b/src/main/java/de/rettichlp/ucutils/common/api/ApiException.java index 03f1abc8..120130b3 100644 --- a/src/main/java/de/rettichlp/ucutils/common/api/ApiException.java +++ b/src/main/java/de/rettichlp/ucutils/common/api/ApiException.java @@ -7,7 +7,7 @@ import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.notificationService; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; @Getter public class ApiException extends RuntimeException { diff --git a/src/main/java/de/rettichlp/ucutils/common/configuration/options/Options.java b/src/main/java/de/rettichlp/ucutils/common/configuration/options/Options.java index ee6ebefb..8a91f626 100644 --- a/src/main/java/de/rettichlp/ucutils/common/configuration/options/Options.java +++ b/src/main/java/de/rettichlp/ucutils/common/configuration/options/Options.java @@ -6,20 +6,21 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import static de.rettichlp.ucutils.common.configuration.options.Options.AtmInformationType.NONE; import static de.rettichlp.ucutils.common.configuration.options.Options.ReinforcementType.UNICACITYADDON; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.AQUA; -import static net.minecraft.util.Formatting.BLUE; -import static net.minecraft.util.Formatting.DARK_AQUA; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.AQUA; +import static net.minecraft.ChatFormatting.BLUE; +import static net.minecraft.ChatFormatting.DARK_AQUA; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.client.gui.components.Tooltip.create; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; @Getter @Setter @@ -45,22 +46,22 @@ public class Options { public enum ReinforcementType implements CyclingButtonEntry { UCUTILS(empty() - .append(of("UC").copy().formatted(DARK_AQUA)) - .append(of("Utils").copy().formatted(AQUA))), + .append(literal("UC").withStyle(DARK_AQUA)) + .append(literal("Utils").withStyle(AQUA))), UNICACITYADDON(empty() - .append(of("U").copy().formatted(BLUE)) - .append(of("nica")) - .append(of("C").copy().formatted(RED)) - .append(of("ity")) - .append(of("A").copy().formatted(BLUE)) - .append(of("ddon"))); + .append(literal("U").withStyle(BLUE)) + .append(literal("nica")) + .append(literal("C").withStyle(RED)) + .append(literal("ity")) + .append(literal("A").withStyle(BLUE)) + .append(literal("ddon"))); - private final Text displayName; + private final Component displayName; @Contract(value = " -> new", pure = true) @Override public @NotNull Tooltip getTooltip() { - return Tooltip.of(this.displayName); + return create(this.displayName); } } @@ -74,13 +75,13 @@ public enum AtmInformationType implements CyclingButtonEntry { G_BANK(translatable("ucutils.options.atm_information.value.g_bank.name"), translatable("ucutils.options.atm_information.value.g_bank.tooltip")), BOTH(translatable("ucutils.options.atm_information.value.both.name"), translatable("ucutils.options.atm_information.value.both.tooltip")); - private final Text displayName; - private final Text tooltip; + private final Component displayName; + private final Component tooltip; @Contract(value = " -> new", pure = true) @Override public @NotNull Tooltip getTooltip() { - return Tooltip.of(this.tooltip); + return create(this.tooltip); } } } diff --git a/src/main/java/de/rettichlp/ucutils/common/configuration/options/SoundOptions.java b/src/main/java/de/rettichlp/ucutils/common/configuration/options/SoundOptions.java index e30edb72..0a467f17 100644 --- a/src/main/java/de/rettichlp/ucutils/common/configuration/options/SoundOptions.java +++ b/src/main/java/de/rettichlp/ucutils/common/configuration/options/SoundOptions.java @@ -5,8 +5,8 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -15,7 +15,8 @@ import static de.rettichlp.ucutils.common.models.Faction.FBI; import static de.rettichlp.ucutils.common.models.Faction.POLIZEI; import static de.rettichlp.ucutils.common.models.Faction.RETTUNGSDIENST; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.client.gui.components.Tooltip.create; +import static net.minecraft.network.chat.Component.translatable; @Getter @Setter @@ -39,14 +40,14 @@ public enum StateSelect implements CyclingButtonEntry { @Contract(" -> new") @Override - public @NotNull Text getDisplayName() { + public @NotNull Component getDisplayName() { return translatable("ucutils.select_state." + name().toLowerCase() + ".name"); } @Contract(" -> new") @Override public @NotNull Tooltip getTooltip() { - return Tooltip.of(translatable("ucutils.select_state." + name().toLowerCase() + ".tooltip")); + return create(translatable("ucutils.select_state." + name().toLowerCase() + ".tooltip")); } public boolean verify(Faction faction) { @@ -62,14 +63,14 @@ public enum MedicSelect implements CyclingButtonEntry { @Contract(" -> new") @Override - public @NotNull Text getDisplayName() { + public @NotNull Component getDisplayName() { return translatable("ucutils.select_medic." + name().toLowerCase() + ".name"); } @Contract(" -> new") @Override public @NotNull Tooltip getTooltip() { - return Tooltip.of(translatable("ucutils.select_medic." + name().toLowerCase() + ".tooltip")); + return create(translatable("ucutils.select_medic." + name().toLowerCase() + ".tooltip")); } public boolean verify(Faction faction) { diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Color.java b/src/main/java/de/rettichlp/ucutils/common/models/Color.java index 6d78a4d6..b3ef5d79 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Color.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Color.java @@ -3,13 +3,14 @@ import de.rettichlp.ucutils.common.gui.screens.components.CyclingButtonEntry; import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.text.MutableText; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.byName; +import static net.minecraft.ChatFormatting.getByName; +import static net.minecraft.client.gui.components.Tooltip.create; +import static net.minecraft.network.chat.Component.translatable; @Getter @AllArgsConstructor @@ -33,16 +34,16 @@ public enum Color implements CyclingButtonEntry { WHITE; @Override - public MutableText getDisplayName() { - return translatable("ucutils.color." + this.name().toLowerCase()).formatted(getFormatting()); + public Component getDisplayName() { + return translatable("ucutils.color." + this.name().toLowerCase()).withStyle(getFormatting()); } @Override public @NotNull Tooltip getTooltip() { - return Tooltip.of(translatable("ucutils.color." + this.name().toLowerCase()).formatted(getFormatting())); + return create(translatable("ucutils.color." + this.name().toLowerCase()).withStyle(getFormatting())); } - public Formatting getFormatting() { - return byName(name()); + public ChatFormatting getFormatting() { + return getByName(name()); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java index c20c0ab5..cb046b1f 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java @@ -3,7 +3,7 @@ import de.rettichlp.ucutils.common.gui.widgets.CountdownWidget; import lombok.Getter; import lombok.RequiredArgsConstructor; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.time.Duration; import java.time.LocalDateTime; @@ -12,10 +12,10 @@ import static de.rettichlp.ucutils.UCUtils.utilService; import static java.time.Duration.between; import static java.time.LocalDateTime.now; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.WHITE; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.WHITE; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @Getter @RequiredArgsConstructor @@ -43,10 +43,10 @@ public Duration getRemainingDuration() { public CountdownWidget toWidget() { String millisToFriendlyString = messageService.millisToFriendlyString(getRemainingDuration().toMillis()); - Text text = empty() - .append(of(this.title).copy().formatted(WHITE)) - .append(of(":").copy().formatted(GRAY)).append(" ") - .append(of(millisToFriendlyString)); + Component text = empty() + .append(literal(this.title).withStyle(WHITE)) + .append(literal(":").withStyle(GRAY)).append(" ") + .append(literal(millisToFriendlyString)); return new CountdownWidget(text, this.startTime, this.duration.toMillis()); } diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Faction.java b/src/main/java/de/rettichlp/ucutils/common/models/Faction.java index 9cdd445d..ae5310c9 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Faction.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Faction.java @@ -2,27 +2,27 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.util.Optional; import static java.util.Arrays.stream; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BLUE; -import static net.minecraft.util.Formatting.DARK_AQUA; -import static net.minecraft.util.Formatting.DARK_BLUE; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.DARK_PURPLE; -import static net.minecraft.util.Formatting.DARK_RED; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; -import static net.minecraft.util.Formatting.LIGHT_PURPLE; -import static net.minecraft.util.Formatting.RED; -import static net.minecraft.util.Formatting.YELLOW; +import static net.minecraft.ChatFormatting.BLUE; +import static net.minecraft.ChatFormatting.DARK_AQUA; +import static net.minecraft.ChatFormatting.DARK_BLUE; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_PURPLE; +import static net.minecraft.ChatFormatting.DARK_RED; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.LIGHT_PURPLE; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @Getter @AllArgsConstructor @@ -46,15 +46,15 @@ public enum Faction { private final String displayName; private final String apiKey; private final boolean isBadFaction; - private final Formatting color; + private final ChatFormatting color; private final String icon; - public Text getNameTagSuffix() { + public Component getNameTagSuffix() { return this != NULL ? empty() - .append(literal("⌜").copy().formatted(DARK_GRAY)) - .append(literal(this.icon).copy().formatted(this.color)) - .append(literal("⌟").copy().formatted(DARK_GRAY)) + .append(literal("⌜").withStyle(DARK_GRAY)) + .append(literal(this.icon).withStyle(this.color)) + .append(literal("⌟").withStyle(DARK_GRAY)) : empty(); } diff --git a/src/main/java/de/rettichlp/ucutils/common/models/ScreenshotType.java b/src/main/java/de/rettichlp/ucutils/common/models/ScreenshotType.java index d38fb08e..cb783677 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/ScreenshotType.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/ScreenshotType.java @@ -2,15 +2,15 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.util.function.Consumer; -import static net.minecraft.client.util.ScreenshotRecorder.takeScreenshot; -import static net.minecraft.util.Util.getFormattedCurrentTime; +import static net.minecraft.client.Screenshot.takeScreenshot; +import static net.minecraft.util.Util.getFilenameFormattedDateTime; @Getter @AllArgsConstructor @@ -29,15 +29,15 @@ public enum ScreenshotType { ROLEPLAY("Roleplay"), TICKET("Ticket"); - private static final File RUN_DIRECTORY = MinecraftClient.getInstance().runDirectory; + private static final File RUN_DIRECTORY = Minecraft.getInstance().gameDirectory; private final String displayName; public void take(Consumer onSuccess) { - MinecraftClient.getInstance().execute(() -> takeScreenshot(MinecraftClient.getInstance().getFramebuffer(), nativeImage -> { + Minecraft.getInstance().execute(() -> takeScreenshot(Minecraft.getInstance().getMainRenderTarget(), nativeImage -> { try { File screenshotFile = getScreenshotFile(); - nativeImage.writeTo(screenshotFile); + nativeImage.writeToFile(screenshotFile); onSuccess.accept(screenshotFile); } catch (IOException e) { throw new RuntimeException(e); @@ -53,16 +53,12 @@ public void take(Consumer onSuccess) { private @NotNull File getScreenshotFile() { File screenshotDirectory = getScreenshotDirectory(); - String formattedCurrentTime = getFormattedCurrentTime(); - int i = 1; - - while (true) { - File file = new File(screenshotDirectory, this.displayName.toLowerCase() + "_" + formattedCurrentTime + (i == 1 ? "" : "_" + i) + ".png"); - if (!file.exists()) { - return file; - } - - ++i; + String name = this.displayName.toLowerCase() + "_" + getFilenameFormattedDateTime(); + int count = 1; + File file; + while ((file = new File(screenshotDirectory, name + (count == 1 ? "" : "_" + count) + ".png")).exists()) { + ++count; } + return file; } } diff --git a/src/main/java/de/rettichlp/ucutils/common/models/ShutdownReason.java b/src/main/java/de/rettichlp/ucutils/common/models/ShutdownReason.java index fee1f339..f1f6f4ff 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/ShutdownReason.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/ShutdownReason.java @@ -3,7 +3,7 @@ import de.rettichlp.ucutils.common.gui.screens.ShutdownScreen; import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; import java.util.Timer; import java.util.TimerTask; @@ -28,8 +28,8 @@ public void activate() { new Timer().schedule(new TimerTask() { @Override public void run() { - MinecraftClient client = MinecraftClient.getInstance(); - client.execute(() -> client.setScreen(new ShutdownScreen(ShutdownReason.this))); + Minecraft minecraft = Minecraft.getInstance(); + minecraft.execute(() -> minecraft.setScreen(new ShutdownScreen(ShutdownReason.this))); } }, 100); } diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Sound.java b/src/main/java/de/rettichlp/ucutils/common/models/Sound.java index 20c66ca6..c8bcf00f 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Sound.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Sound.java @@ -2,14 +2,17 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.resources.Identifier; +import net.minecraft.sounds.SoundEvent; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import static net.minecraft.client.sound.PositionedSoundInstance.master; +import static de.rettichlp.ucutils.UCUtils.MOD_ID; +import static net.minecraft.client.resources.sounds.SimpleSoundInstance.forUI; +import static net.minecraft.resources.Identifier.fromNamespaceAndPath; +import static net.minecraft.sounds.SoundEvent.createVariableRangeEvent; @Getter @AllArgsConstructor @@ -28,21 +31,21 @@ public enum Sound { @Contract(" -> new") public @NotNull Identifier getIdentifier() { - return Identifier.of("ucutils", this.path); + return fromNamespaceAndPath(MOD_ID, this.path); } @Contract(" -> new") public @NotNull SoundEvent getSoundEvent() { - return SoundEvent.of(getIdentifier()); + return createVariableRangeEvent(getIdentifier()); } public void play() { - PositionedSoundInstance positionedSoundInstance = master(getSoundEvent(), 1.0F, 1.0F); - MinecraftClient.getInstance().getSoundManager().play(positionedSoundInstance); + SimpleSoundInstance simpleSoundInstance = forUI(getSoundEvent(), 1.0F, 1.0F); + Minecraft.getInstance().getSoundManager().play(simpleSoundInstance); } public void play(float pitch, float volume) { - PositionedSoundInstance positionedSoundInstance = master(getSoundEvent(), pitch, volume); - MinecraftClient.getInstance().getSoundManager().play(positionedSoundInstance); + SimpleSoundInstance simpleSoundInstance = forUI(getSoundEvent(), pitch, volume); + Minecraft.getInstance().getSoundManager().play(simpleSoundInstance); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java b/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java index 0f7ddb74..d9b8a8ec 100644 --- a/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java +++ b/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java @@ -4,7 +4,6 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import de.rettichlp.ucutils.common.models.Sound; import de.rettichlp.ucutils.listener.ICommandSendListener; -import de.rettichlp.ucutils.listener.IHudRenderListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; import de.rettichlp.ucutils.listener.IMessageSendListener; import de.rettichlp.ucutils.listener.INaviSpotReachedListener; @@ -14,20 +13,19 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents; -import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import org.jetbrains.annotations.NotNull; import java.util.Objects; import java.util.Set; +import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.storage; import static java.util.Collections.emptySet; import static java.util.stream.Collectors.toSet; import static java.util.stream.StreamSupport.stream; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; -import static net.minecraft.registry.Registries.SOUND_EVENT; -import static net.minecraft.registry.Registry.register; +import static net.minecraft.core.Registry.register; +import static net.minecraft.core.registries.BuiltInRegistries.SOUND_EVENT; import static org.atteo.classindex.ClassIndex.getAnnotated; public class Registry { @@ -116,7 +114,7 @@ public void registerListeners() { ClientTickEvents.END_CLIENT_TICK.register((server) -> getListenersImplementing(ITickListener.class).forEach(ITickListener::onTick)); - HudRenderCallback.EVENT.register((drawContext, tickCounter) -> getListenersImplementing(IHudRenderListener.class).forEach(iHudRenderListener -> iHudRenderListener.onHudRender(drawContext, tickCounter))); + // FIXME HudRenderCallback.EVENT.register((drawContext, tickCounter) -> getListenersImplementing(IHudRenderListener.class).forEach(iHudRenderListener -> iHudRenderListener.onHudRender(drawContext, tickCounter))); // prevent multiple registrations of listeners this.initialized = true; diff --git a/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java b/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java index 40f72219..f8823463 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java @@ -1,6 +1,6 @@ package de.rettichlp.ucutils.common.services; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.time.LocalDate; @@ -12,32 +12,37 @@ import static java.lang.Math.abs; import static java.lang.String.format; import static java.time.format.DateTimeFormatter.ofPattern; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.DARK_PURPLE; -import static net.minecraft.util.Formatting.LIGHT_PURPLE; -import static net.minecraft.util.Formatting.WHITE; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_PURPLE; +import static net.minecraft.ChatFormatting.LIGHT_PURPLE; +import static net.minecraft.ChatFormatting.WHITE; +import static net.minecraft.network.chat.Component.literal; public class MessageService { public static final DateTimeFormatter DATE_TIME_FORMAT = ofPattern("dd.MM.yyyy HH:mm:ss"); public static final DateTimeFormatter TIME_FORMAT = ofPattern("HH:mm:ss"); - protected static final Text modMessagePrefix = Text.empty() - .append(of("✦").copy().formatted(DARK_PURPLE)) - .append(of(" ")) - .append(of("UCU").copy().formatted(LIGHT_PURPLE)) - .append(of(" ")) - .append(of("|").copy().formatted(DARK_GRAY)) - .append(of(" ")); + protected static final Component modMessagePrefix = Component.empty() + .append(literal("✦").withStyle(DARK_PURPLE)) + .append(literal(" ")) + .append(literal("UCU").withStyle(LIGHT_PURPLE)) + .append(literal(" ")) + .append(literal("|").withStyle(DARK_GRAY)) + .append(literal(" ")); public void sendModMessage(String message, boolean inActionbar) { - messageService.sendModMessage(of(message).copy().formatted(WHITE), inActionbar); + messageService.sendModMessage(literal(message).withStyle(WHITE), inActionbar); } - public void sendModMessage(Text message, boolean inActionbar) { - Text messageText = modMessagePrefix.copy().append(message); - player.sendMessage(messageText, inActionbar); + public void sendModMessage(Component message, boolean inActionbar) { + Component messageText = modMessagePrefix.copy().append(message); + + if (inActionbar) { + player.sendOverlayMessage(messageText); + } else { + player.sendSystemMessage(messageText); + } } public String dateTimeToFriendlyString(@NotNull ChronoLocalDateTime dateTime) { diff --git a/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java b/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java index 462fe6c7..5880e357 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java @@ -1,9 +1,9 @@ package de.rettichlp.ucutils.common.services; -import net.minecraft.scoreboard.Team; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.scores.Team; import org.jetbrains.annotations.NotNull; import java.time.Duration; @@ -13,49 +13,49 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static java.time.Duration.between; import static java.time.LocalDateTime.now; -import static net.minecraft.scoreboard.AbstractTeam.CollisionRule.NEVER; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BLUE; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.DARK_GREEN; -import static net.minecraft.util.Formatting.DARK_RED; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; -import static net.minecraft.util.Formatting.RED; -import static net.minecraft.util.Formatting.YELLOW; +import static net.minecraft.ChatFormatting.BLUE; +import static net.minecraft.ChatFormatting.BOLD; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_GREEN; +import static net.minecraft.ChatFormatting.DARK_RED; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.world.scores.Team.CollisionRule.NEVER; public class NameTagService { - public static final MutableText AFK_TAG = literal("ᴀꜰᴋ").formatted(GOLD, BOLD); + public static final Component AFK_TAG = literal("ᴀꜰᴋ").withStyle(GOLD, BOLD); - private static final MutableText A_DUTY_PREFIX = empty() - .append(literal("[").formatted(DARK_GRAY)) - .append(literal("UC").formatted(BLUE)) - .append(literal("]").formatted(DARK_GRAY)); + private static final Component A_DUTY_PREFIX = empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("UC").withStyle(BLUE)) + .append(literal("]").withStyle(DARK_GRAY)); public boolean isAfk(String targetName) { - return networkHandler.getPlayerList().stream() + return networkHandler.getOnlinePlayers().stream() .filter(entry -> entry.getProfile().name().equals(targetName)) .anyMatch(entry -> { - Team team = entry.getScoreboardTeam(); + Team team = entry.getTeam(); return team != null && !isADuty(targetName) && team.getCollisionRule() == NEVER; }); } public boolean isADuty(String targetName) { - return networkHandler.getPlayerList().stream() + return networkHandler.getOnlinePlayers().stream() .filter(entry -> entry.getProfile().name().equals(targetName)) .anyMatch(entry -> { - Text displayName = entry.getDisplayName(); + Component displayName = entry.getTabListDisplayName(); return displayName != null && displayName.contains(A_DUTY_PREFIX); }); } - public @NotNull Formatting getWantedPointColor(int wantedPointAmount) { - Formatting color; + public @NotNull ChatFormatting getWantedPointColor(int wantedPointAmount) { + ChatFormatting color; if (wantedPointAmount >= 60) { color = DARK_RED; @@ -73,15 +73,15 @@ public boolean isADuty(String targetName) { return color; } - public MutableText getMedicInformation(String playerName) { - MutableText text = empty(); + public Component getMedicInformation(String playerName) { + MutableComponent text = empty(); LocalDateTime bandageCooldownExpiration = storage.getMedicBandageCooldowns().getOrDefault(playerName, now()); Duration bandageExpirationDuration = between(now(), bandageCooldownExpiration); if (bandageExpirationDuration.isPositive()) { text - .append(literal("Bandage").formatted(GRAY)) - .append(literal(": ").formatted(DARK_GRAY)) + .append(literal("Bandage").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) .append(literal(bandageExpirationDuration.toSeconds() + "s")); } @@ -93,8 +93,8 @@ public MutableText getMedicInformation(String playerName) { } text - .append(literal("Schmerzpille").formatted(GRAY)) - .append(literal(": ").formatted(DARK_GRAY)) + .append(literal("Schmerzpille").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) .append(literal(pillExpirationDuration.toSeconds() + "s")); } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java b/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java index 9ac44d1b..941c93d6 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java @@ -2,7 +2,7 @@ import de.rettichlp.ucutils.common.gui.widgets.NotificationWidget; import lombok.Data; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.awt.Color; import java.time.LocalDateTime; @@ -31,23 +31,23 @@ public class NotificationService { private final Collection notifications = new ArrayList<>(); - public void sendSuccessNotification(Text text) { + public void sendSuccessNotification(Component text) { sendNotification(text, GREEN, 5000); } - public void sendInfoNotification(Text text) { + public void sendInfoNotification(Component text) { sendNotification(text, CYAN, 5000); } - public void sendWarningNotification(Text text) { + public void sendWarningNotification(Component text) { sendNotification(text, ORANGE, 5000); } - public void sendErrorNotification(Text text) { + public void sendErrorNotification(Component text) { sendNotification(text, RED, 5000); } - public void sendNotification(Text text, Color color, long durationInMillis) { + public void sendNotification(Component text, Color color, long durationInMillis) { Notification notification = new Notification(text, durationInMillis); notification.setColor(color); this.notifications.add(notification); @@ -75,7 +75,7 @@ public void notificationSound(int repeating) { public static class Notification { private final UUID id = randomUUID(); - private final Text text; + private final Component text; private final long durationInMillis; private final LocalDateTime timestamp = now(); private Color color = WHITE; diff --git a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java index 067cc9cd..2add00aa 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java @@ -6,10 +6,9 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import lombok.Getter; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.CyclingButtonWidget; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.awt.Color; @@ -50,35 +49,35 @@ public void initializeWidgets() { .collect(toCollection(LinkedHashSet::new)); } - public void addCyclingButton(@NotNull DirectionalLayoutWidget widget, - Text name, + public void addCyclingButton(@NotNull LinearLayout widget, + Component name, E[] values, - Function displayNameFunction, + Function displayNameFunction, BiConsumer onValueChange, @NotNull Function currentValue, int width) { - CyclingButtonWidget cyclingButton = CyclingButtonWidget.builder(displayNameFunction) - .values(values) - .initially(currentValue.apply(configuration.getOptions())) - .tooltip(CyclingButtonEntry::getTooltip) - .build(name, (button, value) -> onValueChange.accept(configuration.getOptions(), value)); - - cyclingButton.setWidth(width); - - widget.add(cyclingButton); +// FIXME CyclingButtonWidget cyclingButton = CyclingButtonWidget.builder(displayNameFunction) +// .values(values) +// .initially(currentValue.apply(configuration.getOptions())) +// .tooltip(CyclingButtonEntry::getTooltip) +// .build(name, (button, value) -> onValueChange.accept(configuration.getOptions(), value)); +// +// cyclingButton.setWidth(width); +// +// widget.addChild(cyclingButton); } - public void addToggleButton(@NotNull DirectionalLayoutWidget widget, - Text name, - Text tooltip, + public void addToggleButton(@NotNull LinearLayout widget, + Component name, + Component tooltip, BiConsumer onPress, @NotNull Function currentValue, int width) { ToggleButtonWidget toggleButton = new ToggleButtonWidget(name, value -> onPress.accept(configuration.getOptions(), value), currentValue.apply(configuration.getOptions())); toggleButton.setWidth(width); - toggleButton.setTooltip(Tooltip.of(tooltip)); + toggleButton.setTooltip(Tooltip.create(tooltip)); - widget.add(toggleButton); + widget.addChild(toggleButton); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java index 7488bdd0..788023e6 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java @@ -20,13 +20,13 @@ import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; public class SyncService { @@ -70,7 +70,7 @@ public void syncTeamMembers() { public void syncFactionSpecificData() { // parse from faction-related init commands after all faction members are synced - Faction faction = storage.getFaction(player.getStringifiedName()); + Faction faction = storage.getFaction(player.getPlainTextName()); switch (faction) { case FBI, POLIZEI -> commandService.sendCommandWithHiddenOutput("wanteds"); default -> { @@ -90,11 +90,11 @@ public void checkForUpdates() { String currentVersion = utilService.getVersion(); if (nonNull(latestVersion) && !currentVersion.equals(latestVersion)) { notificationService.sendNotification(empty() - .append(translatable("ucutils.notification.info.new_version").copy().formatted(GRAY)) - .append(literal(":").copy().formatted(DARK_GRAY)).append(" ") - .append(literal(currentVersion).copy().formatted(RED)).append(" ") - .append(literal("→").copy().formatted(GRAY)).append(" ") - .append(literal(latestVersion).copy().formatted(GREEN)), MAGENTA, MINUTES.toMillis(5)); + .append(translatable("ucutils.notification.info.new_version").withStyle(GRAY)) + .append(literal(":").withStyle(DARK_GRAY)).append(" ") + .append(literal(currentVersion).withStyle(RED)).append(" ") + .append(literal("→").withStyle(GRAY)).append(" ") + .append(literal(latestVersion).withStyle(GREEN)), MAGENTA, MINUTES.toMillis(5)); } }); } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/UtilService.java b/src/main/java/de/rettichlp/ucutils/common/services/UtilService.java index ac1c77a7..60cdf1e4 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/UtilService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/UtilService.java @@ -2,7 +2,7 @@ import lombok.Getter; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; import java.time.ZoneId; import java.util.Timer; @@ -19,7 +19,7 @@ public void delayedAction(Runnable runnable, long milliseconds) { new Timer().schedule(new TimerTask() { @Override public void run() { - MinecraftClient.getInstance().execute(runnable); + Minecraft.getInstance().execute(runnable); } }, milliseconds); } diff --git a/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java b/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java index 2d02c639..5501ee58 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java @@ -1,9 +1,9 @@ package de.rettichlp.ucutils.listener; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.gui.GuiGraphicsExtractor; public interface IHudRenderListener extends IUCUtilsListener { - void onHudRender(DrawContext drawContext, RenderTickCounter renderTickCounter); + void onHudRender(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker); } diff --git a/src/main/java/de/rettichlp/ucutils/listener/IMessageReceiveListener.java b/src/main/java/de/rettichlp/ucutils/listener/IMessageReceiveListener.java index 9f551e74..0cc76a15 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/IMessageReceiveListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/IMessageReceiveListener.java @@ -1,8 +1,8 @@ package de.rettichlp.ucutils.listener; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; public interface IMessageReceiveListener extends IUCUtilsListener { - boolean onMessageReceive(Text text, String message); + boolean onMessageReceive(Component text, String message); } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java index 1a724662..664a6d7f 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java @@ -2,7 +2,7 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -22,7 +22,7 @@ public class CarListener implements IMessageReceiveListener { private static final Pattern CAR_FIND_PATTERN = compile("^\\[Car] Das Fahrzeug befindet sich bei » X: (?-?\\d+) \\| Y: (?-?\\d+) \\| Z: (?-?\\d+)$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher carUnlockMatcher = CAR_UNLOCK_PATTERN.matcher(message); if (carUnlockMatcher.find()) { storage.setCarLocked(false); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java index 24f93fc7..be26f400 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java @@ -2,10 +2,10 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; import java.util.ArrayList; import java.util.List; @@ -24,9 +24,9 @@ import static java.lang.System.currentTimeMillis; import static java.util.Optional.ofNullable; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.UNDERLINE; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.UNDERLINE; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class EconomyListener implements IMessageReceiveListener { @@ -74,7 +74,7 @@ public class EconomyListener implements IMessageReceiveListener { private long lastMedicReviveAction = 0; @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher bankStatementMatcher = BANK_STATEMENT_PATTERN.matcher(message); if (bankStatementMatcher.find()) { int amount = parseInt(bankStatementMatcher.group("amount")); @@ -285,14 +285,14 @@ public boolean onMessageReceive(Text text, String message) { if (businessCashMatcher.find()) { String amountString = businessCashMatcher.group(1); - MutableText appendedText = text.copy().append(" ") - .append(of("Geld entnehmen").copy().formatted(GRAY, UNDERLINE)) - .styled(style -> style + MutableComponent appendedText = text.copy().append(" ") + .append(literal("Geld entnehmen").withStyle(GRAY, UNDERLINE)) + .withStyle(style -> style .withClickEvent(new ClickEvent.RunCommand("/biz kasse get " + amountString)) - .withHoverEvent(new HoverEvent.ShowText(of("Klicke, um " + amountString + "$ aus der Kasse zu nehmen."))) + .withHoverEvent(new HoverEvent.ShowText(literal("Klicke, um " + amountString + "$ aus der Kasse zu nehmen."))) ); - player.sendMessage(appendedText, false); + player.sendSystemMessage(appendedText); return false; } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java index 7a0502cc..c025a628 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java @@ -2,10 +2,11 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -14,9 +15,9 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static java.lang.Integer.parseInt; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.DARK_RED; +import static net.minecraft.ChatFormatting.BOLD; +import static net.minecraft.ChatFormatting.DARK_RED; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class BadFactionListener implements IMessageReceiveListener { @@ -24,14 +25,14 @@ public class BadFactionListener implements IMessageReceiveListener { private static final Pattern BLACK_MARKET_DEALER_ENTRY_PATTERN = compile("^» (?.+) – (gerade eben|vor \\d+ \\w+) {2}\\[Navi]$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher blackMarketDealerEntryMatcher = BLACK_MARKET_DEALER_ENTRY_PATTERN.matcher(message); if (blackMarketDealerEntryMatcher.find()) { - Vec3d blackMarketPosition = storage.getBlackMarketPosition(); - Vec3d dealerPosition = storage.getDealerPosition(); + Vec3i blackMarketPosition = storage.getBlackMarketPosition(); + Vec3i dealerPosition = storage.getDealerPosition(); // extract location from message - Text last = text.getSiblings().getLast(); + Component last = text.getSiblings().getLast(); ClickEvent clickEvent = last.getStyle().getClickEvent(); if (!(clickEvent instanceof ClickEvent.RunCommand(String command))) { return true; @@ -43,11 +44,11 @@ public boolean onMessageReceive(Text text, String message) { return true; } - Vec3d extractedPosition = new Vec3d(parseInt(locationPieces[0]), parseInt(locationPieces[1]), parseInt(locationPieces[2])); + Vec3i extractedPosition = new BlockPos(parseInt(locationPieces[0]), parseInt(locationPieces[1]), parseInt(locationPieces[2])); - if ((blackMarketPosition != null && extractedPosition.distanceTo(blackMarketPosition) < 5) || (dealerPosition != null && extractedPosition.distanceTo(dealerPosition) < 5)) { - MutableText text1 = text.copy().append(literal(" ⯐").formatted(DARK_RED, BOLD)); - player.sendMessage(text1, false); + if ((blackMarketPosition != null && extractedPosition.distSqr(blackMarketPosition) < 5) || (dealerPosition != null && extractedPosition.distSqr(dealerPosition) < 5)) { + MutableComponent text1 = text.copy().append(literal(" ⯐").withStyle(DARK_RED, BOLD)); + player.sendSystemMessage(text1); return false; } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/EmergencyServiceListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/EmergencyServiceListener.java index 99517535..fd44a577 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/EmergencyServiceListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/EmergencyServiceListener.java @@ -2,7 +2,7 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,7 +26,7 @@ public class EmergencyServiceListener implements IMessageReceiveListener { private static final Pattern SERVICE_NONE_PATTERN = compile("^Fehler: Es ist kein Service offen\\.$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher serviceMatcher = SERVICE_PATTERN.matcher(message); if (serviceMatcher.find()) { storage.setActiveServices(storage.getActiveServices() + 1); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java index 762d49bd..01cf649f 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java @@ -6,10 +6,10 @@ import de.rettichlp.ucutils.listener.IMessageReceiveListener; import de.rettichlp.ucutils.listener.IMessageSendListener; import lombok.NonNull; -import net.minecraft.client.MinecraftClient; -import net.minecraft.text.Text; -import net.minecraft.text.TextColor; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextColor; import java.util.List; import java.util.Optional; @@ -24,15 +24,14 @@ import static de.rettichlp.ucutils.common.configuration.options.Options.ReinforcementType.UNICACITYADDON; import static java.util.Optional.ofNullable; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.AQUA; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.DARK_AQUA; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.AQUA; +import static net.minecraft.ChatFormatting.BOLD; +import static net.minecraft.ChatFormatting.DARK_AQUA; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class FactionListener implements IMessageReceiveListener, IMessageSendListener { @@ -44,24 +43,24 @@ public class FactionListener implements IMessageReceiveListener, IMessageSendLis private static final Pattern FACTION_CHAT_PATTERN = compile("^(?[\\p{L} ]+) (?:\\[UC])?(?[a-zA-Z0-9_]+): (?.+)$"); private static final ReinforcementConsumer REINFORCEMENT = (type, sender, naviPoint, distance) -> empty() - .append(of(type).copy().formatted(RED, BOLD)).append(" ") - .append(of(sender).copy().formatted(AQUA)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(naviPoint).copy().formatted(AQUA)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(distance + "m").copy().formatted(DARK_AQUA)); + .append(literal(type).withStyle(RED, BOLD)).append(" ") + .append(literal(sender).withStyle(AQUA)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(naviPoint).withStyle(AQUA)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(distance + "m").withStyle(DARK_AQUA)); private static final ReinforcementOnTheWayConsumer REINFORCEMENT_ON_THE_WAY = (sender, target, distance) -> empty() - .append(of("➥").copy().formatted(GRAY)).append(" ") - .append(of(sender).copy().formatted(AQUA)).append(" ") - .append(of("➡").copy().formatted(GRAY)).append(" ") - .append(of(target).copy().formatted(DARK_AQUA)).append(" ") - .append(of("- (").copy().formatted(GRAY)) - .append(of(distance + "m").copy().formatted(DARK_AQUA)) - .append(of(")").copy().formatted(GRAY)); + .append(literal("➥").withStyle(GRAY)).append(" ") + .append(literal(sender).withStyle(AQUA)).append(" ") + .append(literal("➡").withStyle(GRAY)).append(" ") + .append(literal(target).withStyle(DARK_AQUA)).append(" ") + .append(literal("- (").withStyle(GRAY)) + .append(literal(distance + "m").withStyle(DARK_AQUA)) + .append(literal(")").withStyle(GRAY)); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher reinforcementMatcher = REINFORCEMENT_PATTERN.matcher(message); if (reinforcementMatcher.find()) { String type = ofNullable(reinforcementMatcher.group("type")).orElse("Reinforcement"); @@ -72,9 +71,9 @@ public boolean onMessageReceive(Text text, String message) { boolean modernReinforcementStyle = configuration.getOptions().reinforcementType() == UNICACITYADDON; if (modernReinforcementStyle) { - Text reinforcementText = REINFORCEMENT.create(type, senderRank + " " + senderPlayerName, naviPoint, distance); - player.sendMessage(empty(), false); - player.sendMessage(reinforcementText, false); + Component reinforcementText = REINFORCEMENT.create(type, senderRank + " " + senderPlayerName, naviPoint, distance); + player.sendSystemMessage(empty()); + player.sendSystemMessage(reinforcementText); } return !modernReinforcementStyle; @@ -85,7 +84,7 @@ public boolean onMessageReceive(Text text, String message) { boolean modernReinforcementStyle = configuration.getOptions().reinforcementType() == UNICACITYADDON; if (modernReinforcementStyle) { // send empty line after buttons - MinecraftClient.getInstance().execute(() -> player.sendMessage(empty(), false)); + Minecraft.getInstance().execute(() -> player.sendSystemMessage(empty())); } return true; @@ -100,8 +99,8 @@ public boolean onMessageReceive(Text text, String message) { boolean modernReinforcementStyle = configuration.getOptions().reinforcementType() == UNICACITYADDON; if (modernReinforcementStyle) { - Text reinforcementAnswer = REINFORCEMENT_ON_THE_WAY.create(senderRank + " " + senderPlayerName, target, distance); - player.sendMessage(reinforcementAnswer, false); + Component reinforcementAnswer = REINFORCEMENT_ON_THE_WAY.create(senderRank + " " + senderPlayerName, target, distance); + player.sendSystemMessage(reinforcementAnswer); } return !modernReinforcementStyle; @@ -113,11 +112,11 @@ public boolean onMessageReceive(Text text, String message) { return true; } - Formatting primaryFormatting = configuration.getOptions().factionChatColorPrimary().getFormatting(); - Formatting secondaryFormatting = configuration.getOptions().factionChatColorSecondary().getFormatting(); + ChatFormatting primaryFormatting = configuration.getOptions().factionChatColorPrimary().getFormatting(); + ChatFormatting secondaryFormatting = configuration.getOptions().factionChatColorSecondary().getFormatting(); // check if color already matches formatting - List siblings = text.getSiblings(); + List siblings = text.getSiblings(); if (siblings.size() != 3 || messageMatchesColor(siblings, primaryFormatting, secondaryFormatting)) { return true; } @@ -136,12 +135,12 @@ public boolean onMessageReceive(Text text, String message) { return true; } - player.sendMessage(empty() - .append(literal(playerPrefix).formatted(primaryFormatting)) + player.sendSystemMessage(empty() + .append(literal(playerPrefix).withStyle(primaryFormatting)) .append(literal(" ")) - .append(literal(senderPlayerName).formatted(primaryFormatting)) - .append(literal(": ").formatted(DARK_GRAY)) - .append(literal(factionMessage).formatted(secondaryFormatting)), false); + .append(literal(senderPlayerName).withStyle(primaryFormatting)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal(factionMessage).withStyle(secondaryFormatting))); return false; } @@ -160,21 +159,23 @@ public boolean onMessageSend(String message) { return true; } - private boolean messageMatchesColor(@NonNull List siblings, Formatting primaryFormatting, Formatting secondaryFormatting) { + private boolean messageMatchesColor(@NonNull List siblings, + ChatFormatting primaryFormatting, + ChatFormatting secondaryFormatting) { TextColor primaryFormattingCurrent = siblings.get(0).getStyle().getColor(); TextColor secondaryFormattingCurrent = siblings.get(2).getStyle().getColor(); - return primaryFormattingCurrent == null || secondaryFormattingCurrent == null || primaryFormattingCurrent.getRgb() == primaryFormatting.getColorValue() || secondaryFormattingCurrent.getRgb() == secondaryFormatting.getColorValue(); + return primaryFormattingCurrent == null || secondaryFormattingCurrent == null || primaryFormattingCurrent.getValue() == primaryFormatting.getColor() || secondaryFormattingCurrent.getValue() == secondaryFormatting.getColor(); } @FunctionalInterface public interface ReinforcementConsumer { - Text create(String type, String sender, String naviPoint, String distance); + Component create(String type, String sender, String naviPoint, String distance); } @FunctionalInterface public interface ReinforcementOnTheWayConsumer { - Text create(String sender, String target, String distance); + Component create(String sender, String target, String distance); } } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/AnglerListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/AnglerListener.java index 33e683c1..e2303a45 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/AnglerListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/AnglerListener.java @@ -2,12 +2,12 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.component.type.MapIdComponent; -import net.minecraft.item.ItemStack; -import net.minecraft.item.map.MapState; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.saveddata.maps.MapId; +import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import org.jetbrains.annotations.Nullable; import java.awt.image.BufferedImage; @@ -22,12 +22,12 @@ import static java.awt.image.BufferedImage.TYPE_INT_RGB; import static java.util.regex.Pattern.compile; import static javax.imageio.ImageIO.write; -import static net.minecraft.block.MapColor.getRenderColor; -import static net.minecraft.component.DataComponentTypes.MAP_ID; -import static net.minecraft.item.FilledMapItem.getMapState; -import static net.minecraft.item.Items.FILLED_MAP; -import static net.minecraft.item.Items.FISHING_ROD; -import static net.minecraft.util.Hand.MAIN_HAND; +import static net.minecraft.core.component.DataComponents.MAP_ID; +import static net.minecraft.world.InteractionHand.MAIN_HAND; +import static net.minecraft.world.item.Items.FILLED_MAP; +import static net.minecraft.world.item.Items.FISHING_ROD; +import static net.minecraft.world.item.MapItem.getSavedData; +import static net.minecraft.world.level.material.MapColor.getColorFromPackedId; @UCUtilsListener public class AnglerListener implements IMessageReceiveListener { @@ -36,17 +36,17 @@ public class AnglerListener implements IMessageReceiveListener { private static final Pattern ANGLER_CAPTCHA_CONTINUED_PATTERN = compile("^Deine Combo wurde fortgesetzt! \\(\\d+\\)$"); @Override - public boolean onMessageReceive(Text text, String message) { - MinecraftClient client = MinecraftClient.getInstance(); + public boolean onMessageReceive(Component text, String message) { + Minecraft client = Minecraft.getInstance(); Matcher anglerCaptchaMatcher = ANGLER_CAPTCHA_PATTERN.matcher(message); if (anglerCaptchaMatcher.find()) { utilService.delayedAction(() -> { - ItemStack offHandStack = player.getOffHandStack(); - if (offHandStack.isOf(FILLED_MAP)) { - MapIdComponent captchaMap = offHandStack.get(MAP_ID); - storage.setCaptchaMap(captchaMap); - saveCaptchaImage(captchaMap); + ItemStack offHandStack = player.getOffhandItem(); + if (offHandStack.is(FILLED_MAP)) { + MapId mapId = offHandStack.get(MAP_ID); + storage.setCaptchaMap(mapId); + saveCaptchaImage(mapId); } }, 500); @@ -57,21 +57,21 @@ public boolean onMessageReceive(Text text, String message) { if (anglerCaptchaContinuedMatcher.find()) { storage.setCaptchaMap(null); - ClientPlayerInteractionManager interactionManager = client.interactionManager; - if (interactionManager == null || !player.getMainHandStack().isOf(FISHING_ROD)) { + MultiPlayerGameMode gameMode = client.gameMode; + if (gameMode == null || !player.getMainHandItem().is(FISHING_ROD)) { return true; } - interactionManager.interactItem(player, MAIN_HAND); - player.swingHand(MAIN_HAND); + gameMode.useItem(player, MAIN_HAND); + player.swing(MAIN_HAND); return true; } return true; } - private void saveCaptchaImage(MapIdComponent captchaMap) { - BufferedImage mapImage = getMapImage(captchaMap); + private void saveCaptchaImage(MapId mapId) { + BufferedImage mapImage = getMapImage(mapId); if (mapImage == null) { return; } @@ -87,19 +87,20 @@ private void saveCaptchaImage(MapIdComponent captchaMap) { } } - private @Nullable BufferedImage getMapImage(MapIdComponent mapIdComponent) { - MapState mapState = getMapState(mapIdComponent, MinecraftClient.getInstance().world); - if (mapState == null) { + private @Nullable BufferedImage getMapImage(MapId mapId) { + assert Minecraft.getInstance().level != null; + MapItemSavedData savedData = getSavedData(mapId, Minecraft.getInstance().level); + if (savedData == null) { return null; } BufferedImage mapImage = new BufferedImage(128, 128, TYPE_INT_RGB); - for (int i = 0; i < mapState.colors.length; i++) { + for (int i = 0; i < savedData.colors.length; i++) { int x = i % 128; int y = i / 128; - int argb = getRenderColor(mapState.colors[i]); + int argb = getColorFromPackedId(savedData.colors[i]); mapImage.setRGB(x, y, argb); } From c367dc149339562291026cb5f29a34163d010fe4 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 19:57:18 +0200 Subject: [PATCH 05/64] Align option screens with Minecraft 26.1.2 API changes --- .../common/gui/screens/OptionsScreen.java | 36 ++++---- .../common/gui/screens/ShutdownScreen.java | 50 +++++------ .../common/gui/screens/UCUtilsScreen.java | 89 ++++++++++--------- .../components/CyclingButtonEntry.java | 6 +- .../components/ToggleButtonWidget.java | 37 ++++---- .../gui/screens/options/CarOptionsScreen.java | 83 +++++++++-------- .../screens/options/ChatOptionsScreen.java | 32 +++---- .../screens/options/MainOptionsScreen.java | 64 ++++++------- .../screens/options/NameTagOptionsScreen.java | 38 ++++---- .../options/NotificationOptionsScreen.java | 54 +++++------ .../screens/options/SoundOptionsScreen.java | 52 +++++------ .../options/WidgetOptionsPositionScreen.java | 77 ++++++++-------- .../screens/options/WidgetOptionsScreen.java | 61 ++++++------- 13 files changed, 343 insertions(+), 336 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java index 8e76ba1f..9c5943f0 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java @@ -1,20 +1,20 @@ package de.rettichlp.ucutils.common.gui.screens; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import java.net.URI; import static de.rettichlp.ucutils.UCUtils.configuration; -import static net.minecraft.client.gui.screen.ConfirmLinkScreen.opening; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.horizontal; -import static net.minecraft.screen.ScreenTexts.BACK; -import static net.minecraft.screen.ScreenTexts.DONE; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; +import static net.minecraft.client.gui.screens.ConfirmLinkScreen.confirmLink; +import static net.minecraft.network.chat.CommonComponents.GUI_BACK; +import static net.minecraft.network.chat.CommonComponents.GUI_DONE; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; public abstract class OptionsScreen extends UCUtilsScreen { @@ -29,13 +29,13 @@ public OptionsScreen(Screen parent) { .append(translatable("options.title")), parent); } - public OptionsScreen(Screen parent, Text subTitle) { + public OptionsScreen(Screen parent, Component subTitle) { super(empty() .append("UCUtils").append(" ") .append(translatable("options.title")), subTitle, parent); } - public OptionsScreen(Screen parent, Text subTitel, boolean renderBackground) { + public OptionsScreen(Screen parent, Component subTitel, boolean renderBackground) { super(empty() .append("UCUtils").append(" ") .append(translatable("options.title")), subTitel, parent, renderBackground); @@ -48,10 +48,10 @@ public void doOnClose() { @Override protected void initFooter() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addFooter(horizontal().spacing(8)); - directionalLayoutWidget.add(ButtonWidget.builder(BACK, button -> back()).width(120).build()); - directionalLayoutWidget.add(ButtonWidget.builder(DONE, button -> close()).width(200).build()); - directionalLayoutWidget.add(ButtonWidget.builder(of("Discord").copy().withColor(DISCORD_COLOR), opening(this, DISCORD_INVITE)).width(56).build()); - directionalLayoutWidget.add(ButtonWidget.builder(of("Modrinth").copy().withColor(MODRINTH_COLOR), opening(this, MODRINTH)).width(56).build()); + LinearLayout directionalLayoutWidget = this.layout.addToFooter(horizontal().spacing(8)); + directionalLayoutWidget.addChild(Button.builder(GUI_BACK, _ -> back()).width(120).build()); + directionalLayoutWidget.addChild(Button.builder(GUI_DONE, _ -> close()).width(200).build()); + directionalLayoutWidget.addChild(Button.builder(literal("Discord").copy().withColor(DISCORD_COLOR), confirmLink(this, DISCORD_INVITE)).width(56).build()); + directionalLayoutWidget.addChild(Button.builder(literal("Modrinth").copy().withColor(MODRINTH_COLOR), confirmLink(this, MODRINTH)).width(56).build()); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java index 633ad200..d40925a8 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java @@ -1,52 +1,52 @@ package de.rettichlp.ucutils.common.gui.screens; import de.rettichlp.ucutils.common.models.ShutdownReason; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.client.gui.widget.TextWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.storage; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.vertical; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.client.gui.layouts.LinearLayout.vertical; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; public class ShutdownScreen extends UCUtilsScreen { - private static final Text BUTTON_SHUTDOWN_ABORT_NAME = translatable("ucutils.screen.shutdown_abort.button.name"); + private static final Component BUTTON_SHUTDOWN_ABORT_NAME = translatable("ucutils.screen.shutdown_abort.button.name"); private final ShutdownReason shutdownReason; public ShutdownScreen(ShutdownReason shutdownReason) { - super(of("Automatisches Herunterfahren"), of(shutdownReason.getDisplayName())); + super(literal("Automatisches Herunterfahren"), literal(shutdownReason.getDisplayName())); this.shutdownReason = shutdownReason; } @Override public void initBody() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addBody(vertical().spacing(4)); - directionalLayoutWidget.getMainPositioner().alignHorizontalCenter(); + LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4)); + directionalLayoutWidget.newCellSettings().alignHorizontallyCenter(); - directionalLayoutWidget.add(new TextWidget(empty() - .append(of("Das Spiel wird beendet und der PC heruntergefahren,").copy().formatted(GRAY)), this.textRenderer), positioner -> positioner.marginTop(16)); + directionalLayoutWidget.addChild(new StringWidget(empty() + .append(literal("Das Spiel wird beendet und der PC heruntergefahren,").withStyle(GRAY)), this.font), positioner -> positioner.paddingTop(16)); - directionalLayoutWidget.add(new TextWidget(empty() - .append(of("wenn folgende Bedingung erfüllt ist:").copy().formatted(GRAY)), this.textRenderer), positioner -> positioner.marginBottom(16)); + directionalLayoutWidget.addChild(new StringWidget(empty() + .append(literal("wenn folgende Bedingung erfüllt ist:").withStyle(GRAY)), this.font), positioner -> positioner.paddingBottom(16)); - directionalLayoutWidget.add(new TextWidget(of(this.shutdownReason.getConditionString()).copy().formatted(GOLD), this.textRenderer)); + directionalLayoutWidget.addChild(new StringWidget(literal(this.shutdownReason.getConditionString()).withStyle(GOLD), this.font)); - directionalLayoutWidget.add(new TextWidget(empty() - .append(of("Wenn du dieses Fenster schließt,").copy().formatted(GRAY)), this.textRenderer), positioner -> positioner.marginTop(16)); + directionalLayoutWidget.addChild(new StringWidget(empty() + .append(literal("Wenn du dieses Fenster schließt,").withStyle(GRAY)), this.font), positioner -> positioner.paddingTop(16)); - directionalLayoutWidget.add(new TextWidget(empty() - .append(of("wird das automatische Herunterfahren gestoppt.").copy().formatted(GRAY)), this.textRenderer), positioner -> positioner.marginBottom(16)); + directionalLayoutWidget.addChild(new StringWidget(empty() + .append(literal("wird das automatische Herunterfahren gestoppt.").withStyle(GRAY)), this.font), positioner -> positioner.paddingBottom(16)); - directionalLayoutWidget.add(ButtonWidget.builder(BUTTON_SHUTDOWN_ABORT_NAME, button -> close()).width(150).build()); + directionalLayoutWidget.addChild(Button.builder(BUTTON_SHUTDOWN_ABORT_NAME, button -> close()).width(150).build()); - directionalLayoutWidget.forEachChild(this::addDrawableChild); + directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } @Override diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java index 73f2fab7..50a53928 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java @@ -1,49 +1,52 @@ package de.rettichlp.ucutils.common.gui.screens; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.client.gui.widget.EntryListWidget; -import net.minecraft.client.gui.widget.TextWidget; -import net.minecraft.client.gui.widget.ThreePartsLayoutWidget; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; +import org.jspecify.annotations.NonNull; import static de.rettichlp.ucutils.UCUtils.MOD_ID; import static java.util.Objects.nonNull; -import static net.minecraft.client.gl.RenderPipelines.GUI_TEXTURED; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.vertical; -import static net.minecraft.text.Text.of; +import static net.minecraft.client.gui.layouts.LinearLayout.vertical; +import static net.minecraft.client.renderer.RenderPipelines.GUI_TEXTURED; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.resources.Identifier.withDefaultNamespace; public abstract class UCUtilsScreen extends Screen { - public final ThreePartsLayoutWidget layout = new ThreePartsLayoutWidget(this); + public final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this); + + private static final Identifier MENU_LIST_BACKGROUND = withDefaultNamespace("textures/gui/menu_list_background.png"); + private static final Identifier INWORLD_MENU_LIST_BACKGROUND = withDefaultNamespace("textures/gui/inworld_menu_list_background.png"); private final Screen parent; - private Text subTitle = of("v" + getVersion()); + private Component subTitle = literal("v" + getVersion()); private boolean renderBackground = true; - public UCUtilsScreen(Text title, Screen parent) { + public UCUtilsScreen(Component title, Screen parent) { super(title); this.parent = parent; } - public UCUtilsScreen(Text title, Text subTitle) { + public UCUtilsScreen(Component title, Component subTitle) { super(title); this.parent = null; this.subTitle = subTitle; } - public UCUtilsScreen(Text title, Text subTitle, Screen parent) { + public UCUtilsScreen(Component title, Component subTitle, Screen parent) { super(title); this.parent = parent; this.subTitle = subTitle; } - public UCUtilsScreen(Text title, Text subTitle, Screen parent, boolean renderBackground) { + public UCUtilsScreen(Component title, Component subTitle, Screen parent, boolean renderBackground) { super(title); this.parent = parent; this.subTitle = subTitle; @@ -55,21 +58,21 @@ public UCUtilsScreen(Text title, Text subTitle, Screen parent, boolean renderBac public abstract void doOnClose(); @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { + public void extractRenderState(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { if (this.renderBackground) { - drawMenuListBackground(context); + extractListBackground(graphics); } - super.render(context, mouseX, mouseY, delta); + super.extractRenderState(graphics, mouseX, mouseY, a); if (this.renderBackground) { - drawHeaderAndFooterSeparators(context); + extractListSeparators(graphics); } } @Override - public void close() { - this.client.setScreen(null); + public void onClose() { + this.minecraft.setScreen(null); doOnClose(); } @@ -78,47 +81,49 @@ protected void init() { initHeader(); initBody(); initFooter(); - this.layout.forEachChild(this::addDrawableChild); - refreshWidgetPositions(); + this.layout.visitWidgets(this::addRenderableWidget); + repositionElements(); } @Override - protected void refreshWidgetPositions() { - this.layout.refreshPositions(); + protected void repositionElements() { + this.layout.arrangeElements(); } public void back() { if (nonNull(this.parent)) { - this.client.setScreen(this.parent); + this.minecraft.setScreen(this.parent); doOnClose(); } else { - close(); + onClose(); } } protected void initHeader() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addHeader(vertical().spacing(4)); - directionalLayoutWidget.getMainPositioner().alignHorizontalCenter(); - directionalLayoutWidget.add(new TextWidget(this.title, this.textRenderer)); - directionalLayoutWidget.add(new TextWidget(this.subTitle, this.textRenderer)); + LinearLayout linearLayout = this.layout.addToHeader(vertical().spacing(4)); + linearLayout.newCellSettings().alignHorizontallyCenter(); + linearLayout.addChild(new StringWidget(this.title, this.font)); + linearLayout.addChild(new StringWidget(this.subTitle, this.font)); } protected void initFooter() {} /** - * @see EntryListWidget#drawHeaderAndFooterSeparators(DrawContext) + * @see net.minecraft.client.gui.components.AbstractSelectionList#extractListSeparators(GuiGraphicsExtractor) */ - private void drawHeaderAndFooterSeparators(@NotNull DrawContext context) { - context.drawTexture(GUI_TEXTURED, INWORLD_HEADER_SEPARATOR_TEXTURE, this.layout.getX(), this.layout.getHeaderHeight(), 0.0F, 0.0F, this.layout.getWidth(), 2, 32, 2); - context.drawTexture(GUI_TEXTURED, INWORLD_FOOTER_SEPARATOR_TEXTURE, this.layout.getX(), this.layout.getHeight() - this.layout.getFooterHeight(), 0.0F, 0.0F, this.layout.getWidth(), 2, 32, 2); + protected void extractListSeparators(@NonNull GuiGraphicsExtractor graphics) { + Identifier headerSeparator = this.minecraft.level == null ? HEADER_SEPARATOR : INWORLD_HEADER_SEPARATOR; + Identifier footerSeparator = this.minecraft.level == null ? FOOTER_SEPARATOR : INWORLD_FOOTER_SEPARATOR; + graphics.blit(GUI_TEXTURED, headerSeparator, this.layout.getX(), this.layout.getHeaderHeight() - 2, 0.0F, 0.0F, this.layout.getWidth(), 2, 32, 2); + graphics.blit(GUI_TEXTURED, footerSeparator, this.layout.getX(), this.layout.getHeight() - this.layout.getFooterHeight(), 0.0F, 0.0F, this.layout.getWidth(), 2, 32, 2); } /** - * @see EntryListWidget#drawMenuListBackground(DrawContext) + * @see net.minecraft.client.gui.components.AbstractSelectionList#extractListBackground(GuiGraphicsExtractor) */ - private void drawMenuListBackground(@NotNull DrawContext context) { - Identifier identifier = Identifier.ofVanilla("textures/gui/inworld_menu_list_background.png"); - context.drawTexture(GUI_TEXTURED, identifier, this.layout.getX(), this.layout.getHeaderHeight(), 0.0F, 0.0F, this.layout.getWidth(), this.layout.getContentHeight(), 32, 32); + protected void extractListBackground(@NonNull GuiGraphicsExtractor graphics) { + Identifier menuListBackground = this.minecraft.level == null ? MENU_LIST_BACKGROUND : INWORLD_MENU_LIST_BACKGROUND; + graphics.blit(GUI_TEXTURED, menuListBackground, this.layout.getX(), this.layout.getHeaderHeight(), 0.0F, 0.0F, this.layout.getWidth(), this.layout.getContentHeight(), 32, 32); } private String getVersion() { diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/CyclingButtonEntry.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/CyclingButtonEntry.java index ee47adb2..749be661 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/CyclingButtonEntry.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/CyclingButtonEntry.java @@ -1,11 +1,11 @@ package de.rettichlp.ucutils.common.gui.screens.components; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; public interface CyclingButtonEntry { - Text getDisplayName(); + Component getDisplayName(); Tooltip getTooltip(); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/ToggleButtonWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/ToggleButtonWidget.java index a96b0a2a..5245d2c2 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/ToggleButtonWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/components/ToggleButtonWidget.java @@ -1,27 +1,28 @@ package de.rettichlp.ucutils.common.gui.screens.components; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.input.AbstractInput; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.input.InputWithModifiers; +import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; import java.util.function.Consumer; -import static net.minecraft.screen.ScreenTexts.OFF; -import static net.minecraft.screen.ScreenTexts.ON; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.CommonComponents.OPTION_OFF; +import static net.minecraft.network.chat.CommonComponents.OPTION_ON; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; -public class ToggleButtonWidget extends ButtonWidget { +public class ToggleButtonWidget extends Button.Plain { - private final Text text; + private final Component text; private final Consumer changeListener; private boolean state; - public ToggleButtonWidget(Text text, Consumer changeListener, boolean defaultState) { - super(0, 0, 150, 20, empty(), button -> {}, DEFAULT_NARRATION_SUPPLIER); + public ToggleButtonWidget(Component text, Consumer changeListener, boolean defaultState) { + super(0, 0, 150, 20, empty(), button -> {}, DEFAULT_NARRATION); this.text = text; this.changeListener = changeListener; this.state = defaultState; @@ -29,7 +30,7 @@ public ToggleButtonWidget(Text text, Consumer changeListener, boolean d } @Override - public void onPress(AbstractInput input) { + public void onPress(@NonNull InputWithModifiers input) { super.onPress(input); this.state = !this.state; this.changeListener.accept(this.state); @@ -40,9 +41,9 @@ public void updateText() { setMessage(getText()); } - private Text getText() { + private Component getText() { return this.text.copy() - .append(of(":").copy().formatted(GRAY)).append(" ") - .append(this.state ? ON.copy().formatted(GREEN) : OFF.copy().formatted(RED)); + .append(literal(":").withStyle(GRAY)).append(" ") + .append(this.state ? OPTION_ON.copy().withStyle(GREEN) : OPTION_OFF.copy().withStyle(RED)); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java index fe67b22f..edbd0927 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java @@ -3,33 +3,33 @@ import de.rettichlp.ucutils.common.configuration.options.CarOptions; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.GridWidget; -import net.minecraft.client.gui.widget.MultilineTextWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.layouts.LayoutSettings; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.configuration; -import static net.minecraft.client.gui.widget.Positioner.create; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.GOLD; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.network.chat.Component.translatable; public class CarOptionsScreen extends OptionsScreen { - private static final Text TEXT_CAR = translatable("ucutils.options.text.car"); - private static final Text CAR_PREMIUM_INFO = translatable("ucutils.options.car.premium_info"); - private static final Text CAR_GENERAL_FAST_FIND_NAME = translatable("ucutils.options.car.general.fast_find.name"); - private static final Text CAR_GENERAL_FAST_FIND_TOOLTIP = translatable("ucutils.options.car.general.fast_find.tooltip"); - private static final Text CAR_GENERAL_FAST_LOCK_NAME = translatable("ucutils.options.car.general.fast_lock.name"); - private static final Text CAR_GENERAL_FAST_LOCK_TOOLTIP = translatable("ucutils.options.car.general.fast_lock.tooltip"); - private static final Text CAR_GENERAL_HIGHLIGHT_NAME = translatable("ucutils.options.car.general.highlight.name"); - private static final Text CAR_GENERAL_HIGHLIGHT_TOOLTIP = translatable("ucutils.options.car.general.highlight.tooltip"); - private static final Text CAR_AUTOMATION_LOCK_NAME = translatable("ucutils.options.car.automation.lock.name"); - private static final Text CAR_AUTOMATION_LOCK_TOOLTIP = translatable("ucutils.options.car.automation.lock.tooltip"); - private static final Text CAR_AUTOMATION_START_NAME = translatable("ucutils.options.car.automation.start.name"); - private static final Text CAR_AUTOMATION_START_TOOLTIP = translatable("ucutils.options.car.automation.start.tooltip"); - private static final Text CAR_AUTOMATION_CHECK_KFZ_NAME = translatable("ucutils.options.car.automation.check_kfz.name"); - private static final Text CAR_AUTOMATION_CHECK_KFZ_TOOLTIP = translatable("ucutils.options.car.automation.check_kfz.tooltip"); + private static final Component TEXT_CAR = translatable("ucutils.options.text.car"); + private static final Component CAR_PREMIUM_INFO = translatable("ucutils.options.car.premium_info"); + private static final Component CAR_GENERAL_FAST_FIND_NAME = translatable("ucutils.options.car.general.fast_find.name"); + private static final Component CAR_GENERAL_FAST_FIND_TOOLTIP = translatable("ucutils.options.car.general.fast_find.tooltip"); + private static final Component CAR_GENERAL_FAST_LOCK_NAME = translatable("ucutils.options.car.general.fast_lock.name"); + private static final Component CAR_GENERAL_FAST_LOCK_TOOLTIP = translatable("ucutils.options.car.general.fast_lock.tooltip"); + private static final Component CAR_GENERAL_HIGHLIGHT_NAME = translatable("ucutils.options.car.general.highlight.name"); + private static final Component CAR_GENERAL_HIGHLIGHT_TOOLTIP = translatable("ucutils.options.car.general.highlight.tooltip"); + private static final Component CAR_AUTOMATION_LOCK_NAME = translatable("ucutils.options.car.automation.lock.name"); + private static final Component CAR_AUTOMATION_LOCK_TOOLTIP = translatable("ucutils.options.car.automation.lock.tooltip"); + private static final Component CAR_AUTOMATION_START_NAME = translatable("ucutils.options.car.automation.start.name"); + private static final Component CAR_AUTOMATION_START_TOOLTIP = translatable("ucutils.options.car.automation.start.tooltip"); + private static final Component CAR_AUTOMATION_CHECK_KFZ_NAME = translatable("ucutils.options.car.automation.check_kfz.name"); + private static final Component CAR_AUTOMATION_CHECK_KFZ_TOOLTIP = translatable("ucutils.options.car.automation.check_kfz.tooltip"); public CarOptionsScreen(Screen parent) { super(parent, TEXT_CAR); @@ -37,47 +37,46 @@ public CarOptionsScreen(Screen parent) { @Override public void initBody() { - GridWidget gridWidget = this.layout.addBody(new GridWidget()); - gridWidget.setColumnSpacing(8).setRowSpacing(4); - GridWidget.Adder gridWidgetAdder = gridWidget.createAdder(2); + GridLayout gridLayout = this.layout.addToContents(new GridLayout()); + gridLayout.columnSpacing(8).rowSpacing(4); + GridLayout.RowHelper gridLayoutRowHelper = gridLayout.createRowHelper(2); CarOptions carOptions = configuration.getOptions().car(); ToggleButtonWidget toggleButton1 = new ToggleButtonWidget(CAR_GENERAL_HIGHLIGHT_NAME, carOptions::highlight, carOptions.highlight()); toggleButton1.setWidth(150); - toggleButton1.setTooltip(Tooltip.of(CAR_GENERAL_HIGHLIGHT_TOOLTIP)); - gridWidgetAdder.add(toggleButton1); + toggleButton1.setTooltip(Tooltip.create(CAR_GENERAL_HIGHLIGHT_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton1); ToggleButtonWidget toggleButton2 = new ToggleButtonWidget(CAR_GENERAL_FAST_FIND_NAME, carOptions::fastFind, carOptions.fastFind()); toggleButton2.setWidth(150); - toggleButton2.setTooltip(Tooltip.of(CAR_GENERAL_FAST_FIND_TOOLTIP)); - gridWidgetAdder.add(toggleButton2); + toggleButton2.setTooltip(Tooltip.create(CAR_GENERAL_FAST_FIND_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton2); ToggleButtonWidget toggleButton3 = new ToggleButtonWidget(CAR_AUTOMATION_CHECK_KFZ_NAME, carOptions::automatedCheckKfz, carOptions.automatedCheckKfz()); toggleButton3.setWidth(150); - toggleButton3.setTooltip(Tooltip.of(CAR_AUTOMATION_CHECK_KFZ_TOOLTIP)); - gridWidgetAdder.add(toggleButton3); + toggleButton3.setTooltip(Tooltip.create(CAR_AUTOMATION_CHECK_KFZ_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton3); - MultilineTextWidget multilineTextWidget = gridWidgetAdder.add(new MultilineTextWidget(CAR_PREMIUM_INFO.copy().formatted(GOLD), this.textRenderer), 2, create().alignHorizontalCenter().marginTop(16)); - multilineTextWidget.setMaxWidth(308); - multilineTextWidget.setCentered(true); + StringWidget stringWidget = gridLayoutRowHelper.addChild(new StringWidget(CAR_PREMIUM_INFO.copy().withStyle(GOLD), this.font), 2, LayoutSettings.defaults().alignHorizontallyCenter().paddingTop(16)); + stringWidget.setMaxWidth(308); ToggleButtonWidget toggleButton4 = new ToggleButtonWidget(CAR_GENERAL_FAST_LOCK_NAME, carOptions::fastLock, carOptions.fastLock()); toggleButton4.setWidth(150); - toggleButton4.setTooltip(Tooltip.of(CAR_GENERAL_FAST_LOCK_TOOLTIP)); - gridWidgetAdder.add(toggleButton4); + toggleButton4.setTooltip(Tooltip.create(CAR_GENERAL_FAST_LOCK_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton4); ToggleButtonWidget toggleButton5 = new ToggleButtonWidget(CAR_AUTOMATION_LOCK_NAME, carOptions::automatedLock, carOptions.automatedLock()); toggleButton5.setWidth(150); - toggleButton5.setTooltip(Tooltip.of(CAR_AUTOMATION_LOCK_TOOLTIP)); - gridWidgetAdder.add(toggleButton5); + toggleButton5.setTooltip(Tooltip.create(CAR_AUTOMATION_LOCK_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton5); ToggleButtonWidget toggleButton6 = new ToggleButtonWidget(CAR_AUTOMATION_START_NAME, carOptions::automatedStart, carOptions.automatedStart()); toggleButton6.setWidth(150); - toggleButton6.setTooltip(Tooltip.of(CAR_AUTOMATION_START_TOOLTIP)); - gridWidgetAdder.add(toggleButton6); + toggleButton6.setTooltip(Tooltip.create(CAR_AUTOMATION_START_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton6); - gridWidget.refreshPositions(); - gridWidget.forEachChild(this::addDrawableChild); + gridLayout.arrangeElements(); + gridLayout.visitWidgets(this::addRenderableWidget); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/ChatOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/ChatOptionsScreen.java index cd2938f9..116ae829 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/ChatOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/ChatOptionsScreen.java @@ -4,24 +4,24 @@ import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import de.rettichlp.ucutils.common.gui.screens.components.CyclingButtonEntry; import de.rettichlp.ucutils.common.models.Color; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.client.gui.widget.Positioner; -import net.minecraft.client.gui.widget.TextWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.layouts.LayoutSettings; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.renderService; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.vertical; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.client.gui.layouts.LinearLayout.vertical; +import static net.minecraft.network.chat.Component.translatable; public class ChatOptionsScreen extends OptionsScreen { - private static final Text TEXT_CHAT = translatable("ucutils.options.text.chat"); - private static final Text TEXT_FACTION = translatable("ucutils.options.text.faction"); - private static final Text FACTION_COLOR_NAME = translatable("ucutils.options.faction_chat_color.name"); - private static final Text FACTION_COLOR_TOOLTIP = translatable("ucutils.options.faction_chat_color.tooltip"); - private static final Text FACTION_COLOR_PRIMARY = translatable("ucutils.options.faction_chat_color_primary.name"); - private static final Text FACTION_COLOR_SECONDARY = translatable("ucutils.options.faction_chat_color_secondary.name"); + private static final Component TEXT_CHAT = translatable("ucutils.options.text.chat"); + private static final Component TEXT_FACTION = translatable("ucutils.options.text.faction"); + private static final Component FACTION_COLOR_NAME = translatable("ucutils.options.faction_chat_color.name"); + private static final Component FACTION_COLOR_TOOLTIP = translatable("ucutils.options.faction_chat_color.tooltip"); + private static final Component FACTION_COLOR_PRIMARY = translatable("ucutils.options.faction_chat_color_primary.name"); + private static final Component FACTION_COLOR_SECONDARY = translatable("ucutils.options.faction_chat_color_secondary.name"); public ChatOptionsScreen(Screen parent) { super(parent, TEXT_CHAT); @@ -29,14 +29,14 @@ public ChatOptionsScreen(Screen parent) { @Override public void initBody() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addBody(vertical().spacing(4)); + LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4)); - directionalLayoutWidget.add(new TextWidget(TEXT_FACTION, this.textRenderer), Positioner::alignHorizontalCenter); + directionalLayoutWidget.addChild(new StringWidget(TEXT_FACTION, this.font), LayoutSettings::alignHorizontallyCenter); renderService.addToggleButton(directionalLayoutWidget, FACTION_COLOR_NAME, FACTION_COLOR_TOOLTIP, Options::changeFactionChatColor, Options::changeFactionChatColor, 308); renderService.addCyclingButton(directionalLayoutWidget, FACTION_COLOR_PRIMARY, Color.values(), CyclingButtonEntry::getDisplayName, Options::factionChatColorPrimary, Options::factionChatColorPrimary, 308); renderService.addCyclingButton(directionalLayoutWidget, FACTION_COLOR_SECONDARY, Color.values(), CyclingButtonEntry::getDisplayName, Options::factionChatColorSecondary, Options::factionChatColorSecondary, 308); - directionalLayoutWidget.forEachChild(this::addDrawableChild); + directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java index 7de6605b..2262efad 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java @@ -2,58 +2,58 @@ import de.rettichlp.ucutils.common.configuration.options.Options; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; -import net.minecraft.client.gui.screen.GameMenuScreen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.PauseScreen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.renderService; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.horizontal; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.vertical; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; +import static net.minecraft.client.gui.layouts.LinearLayout.vertical; +import static net.minecraft.network.chat.Component.translatable; public class MainOptionsScreen extends OptionsScreen { - private static final Text CHECK_UNICACITY_SERVER_NAME = translatable("ucutils.options.check_unicacity_server.name"); - private static final Text CHECK_UNICACITY_SERVER_TOOLTIP = translatable("ucutils.options.check_unicacity_server.tooltip"); - private static final Text REINFORCEMENT_STYLE_NAME = translatable("ucutils.options.reinforcement_style.name"); - private static final Text TEXT_NAMETAG = translatable("ucutils.options.text.nametag"); - private static final Text TEXT_CHAT = translatable("ucutils.options.text.chat"); - private static final Text TEXT_CAR = translatable("ucutils.options.text.car"); - private static final Text TEXT_SOUNDS = translatable("ucutils.options.text.sounds"); - private static final Text TEXT_WIDGETS = translatable("ucutils.options.text.widgets"); - private static final Text TEXT_NOTIFICATIONS = translatable("ucutils.options.text.notifications"); - private static final Text HYDRATION_NAME = translatable("ucutils.options.hydration.name"); - private static final Text HYDRATION_TOOLTIP = translatable("ucutils.options.hydration.tooltip"); - private static final Text BANK_INFORMATION_NAME = translatable("ucutils.options.atm_information.name"); + private static final Component CHECK_UNICACITY_SERVER_NAME = translatable("ucutils.options.check_unicacity_server.name"); + private static final Component CHECK_UNICACITY_SERVER_TOOLTIP = translatable("ucutils.options.check_unicacity_server.tooltip"); + private static final Component REINFORCEMENT_STYLE_NAME = translatable("ucutils.options.reinforcement_style.name"); + private static final Component TEXT_NAMETAG = translatable("ucutils.options.text.nametag"); + private static final Component TEXT_CHAT = translatable("ucutils.options.text.chat"); + private static final Component TEXT_CAR = translatable("ucutils.options.text.car"); + private static final Component TEXT_SOUNDS = translatable("ucutils.options.text.sounds"); + private static final Component TEXT_WIDGETS = translatable("ucutils.options.text.widgets"); + private static final Component TEXT_NOTIFICATIONS = translatable("ucutils.options.text.notifications"); + private static final Component HYDRATION_NAME = translatable("ucutils.options.hydration.name"); + private static final Component HYDRATION_TOOLTIP = translatable("ucutils.options.hydration.tooltip"); + private static final Component BANK_INFORMATION_NAME = translatable("ucutils.options.atm_information.name"); public MainOptionsScreen() { - super(new GameMenuScreen(true)); + super(new PauseScreen(true)); } @Override public void initBody() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addBody(vertical().spacing(4)); + LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4)); renderService.addToggleButton(directionalLayoutWidget, CHECK_UNICACITY_SERVER_NAME, CHECK_UNICACITY_SERVER_TOOLTIP, Options::checkUnicacityServer, Options::checkUnicacityServer, 308); renderService.addCyclingButton(directionalLayoutWidget, REINFORCEMENT_STYLE_NAME, Options.ReinforcementType.values(), Options.ReinforcementType::getDisplayName, Options::reinforcementType, Options::reinforcementType, 308); - DirectionalLayoutWidget directionalLayoutWidget1 = directionalLayoutWidget.add(horizontal().spacing(8)); - directionalLayoutWidget1.add(ButtonWidget.builder(TEXT_NAMETAG, button -> this.client.setScreen(new NameTagOptionsScreen(this))).width(150).build()); - directionalLayoutWidget1.add(ButtonWidget.builder(TEXT_CHAT, button -> this.client.setScreen(new ChatOptionsScreen(this))).width(150).build()); + LinearLayout directionalLayoutWidget1 = directionalLayoutWidget.addChild(horizontal().spacing(8)); + directionalLayoutWidget1.addChild(Button.builder(TEXT_NAMETAG, button -> this.minecraft.setScreen(new NameTagOptionsScreen(this))).width(150).build()); + directionalLayoutWidget1.addChild(Button.builder(TEXT_CHAT, button -> this.minecraft.setScreen(new ChatOptionsScreen(this))).width(150).build()); - DirectionalLayoutWidget directionalLayoutWidget2 = directionalLayoutWidget.add(horizontal().spacing(8)); - directionalLayoutWidget2.add(ButtonWidget.builder(TEXT_CAR, button -> this.client.setScreen(new CarOptionsScreen(this))).width(150).build()); - directionalLayoutWidget2.add(ButtonWidget.builder(TEXT_SOUNDS, button -> this.client.setScreen(new SoundOptionsScreen(this))).width(150).build()); + LinearLayout directionalLayoutWidget2 = directionalLayoutWidget.addChild(horizontal().spacing(8)); + directionalLayoutWidget2.addChild(Button.builder(TEXT_CAR, button -> this.minecraft.setScreen(new CarOptionsScreen(this))).width(150).build()); + directionalLayoutWidget2.addChild(Button.builder(TEXT_SOUNDS, button -> this.minecraft.setScreen(new SoundOptionsScreen(this))).width(150).build()); - DirectionalLayoutWidget directionalLayoutWidget3 = directionalLayoutWidget.add(horizontal().spacing(8)); - directionalLayoutWidget3.add(ButtonWidget.builder(TEXT_WIDGETS, button -> this.client.setScreen(new WidgetOptionsScreen(this))).width(150).build()); - directionalLayoutWidget3.add(ButtonWidget.builder(TEXT_NOTIFICATIONS, button -> this.client.setScreen(new NotificationOptionsScreen(this))).width(150).build()); + LinearLayout directionalLayoutWidget3 = directionalLayoutWidget.addChild(horizontal().spacing(8)); + directionalLayoutWidget3.addChild(Button.builder(TEXT_WIDGETS, button -> this.minecraft.setScreen(new WidgetOptionsScreen(this))).width(150).build()); + directionalLayoutWidget3.addChild(Button.builder(TEXT_NOTIFICATIONS, button -> this.minecraft.setScreen(new NotificationOptionsScreen(this))).width(150).build()); - DirectionalLayoutWidget directionalLayoutWidget4 = directionalLayoutWidget.add(horizontal().spacing(8)); + LinearLayout directionalLayoutWidget4 = directionalLayoutWidget.addChild(horizontal().spacing(8)); renderService.addToggleButton(directionalLayoutWidget4, HYDRATION_NAME, HYDRATION_TOOLTIP, Options::showHydration, Options::showHydration, 150); renderService.addCyclingButton(directionalLayoutWidget4, BANK_INFORMATION_NAME, Options.AtmInformationType.values(), Options.AtmInformationType::getDisplayName, Options::atmInformationType, Options::atmInformationType, 150); - directionalLayoutWidget.forEachChild(this::addDrawableChild); + directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NameTagOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NameTagOptionsScreen.java index bfcd5bff..15fea029 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NameTagOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NameTagOptionsScreen.java @@ -3,21 +3,21 @@ import de.rettichlp.ucutils.common.configuration.options.NameTagOptions; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.GridWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.configuration; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class NameTagOptionsScreen extends OptionsScreen { - private static final Text TEXT_NAMETAG = translatable("ucutils.options.text.nametag"); - private static final Text NAMETAG_AFK_NAME = translatable("ucutils.options.nametag.afk.name"); - private static final Text NAMETAG_AFK_TOOLTIP = translatable("ucutils.options.nametag.afk.tooltip"); - private static final Text NAMETAG_MEDICAL_INFORMATION_NAME = translatable("ucutils.options.nametag.medical_information.name"); - private static final Text NAMETAG_MEDICAL_INFORMATION_TOOLTIP = translatable("ucutils.options.nametag.medical_information.tooltip"); + private static final Component TEXT_NAMETAG = translatable("ucutils.options.text.nametag"); + private static final Component NAMETAG_AFK_NAME = translatable("ucutils.options.nametag.afk.name"); + private static final Component NAMETAG_AFK_TOOLTIP = translatable("ucutils.options.nametag.afk.tooltip"); + private static final Component NAMETAG_MEDICAL_INFORMATION_NAME = translatable("ucutils.options.nametag.medical_information.name"); + private static final Component NAMETAG_MEDICAL_INFORMATION_TOOLTIP = translatable("ucutils.options.nametag.medical_information.tooltip"); public NameTagOptionsScreen(Screen parent) { super(parent, TEXT_NAMETAG); @@ -25,23 +25,23 @@ public NameTagOptionsScreen(Screen parent) { @Override public void initBody() { - GridWidget gridWidget = this.layout.addBody(new GridWidget()); - gridWidget.setColumnSpacing(8).setRowSpacing(4); - GridWidget.Adder gridWidgetAdder = gridWidget.createAdder(2); + GridLayout gridLayout = this.layout.addToContents(new GridLayout()); + gridLayout.columnSpacing(8).rowSpacing(4); + GridLayout.RowHelper gridLayoutRowHelper = gridLayout.createRowHelper(2); NameTagOptions nameTagOptions = configuration.getOptions().nameTag(); ToggleButtonWidget toggleButton1 = new ToggleButtonWidget(NAMETAG_AFK_NAME, nameTagOptions::afk, nameTagOptions.afk()); toggleButton1.setWidth(150); - toggleButton1.setTooltip(Tooltip.of(NAMETAG_AFK_TOOLTIP)); - gridWidgetAdder.add(toggleButton1); + toggleButton1.setTooltip(Tooltip.create(NAMETAG_AFK_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton1); ToggleButtonWidget toggleButton2 = new ToggleButtonWidget(NAMETAG_MEDICAL_INFORMATION_NAME, nameTagOptions::medicalInformation, nameTagOptions.medicalInformation()); toggleButton2.setWidth(150); - toggleButton2.setTooltip(Tooltip.of(NAMETAG_MEDICAL_INFORMATION_TOOLTIP)); - gridWidgetAdder.add(toggleButton2); + toggleButton2.setTooltip(Tooltip.create(NAMETAG_MEDICAL_INFORMATION_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton2); - gridWidget.refreshPositions(); - gridWidget.forEachChild(this::addDrawableChild); + gridLayout.arrangeElements(); + gridLayout.visitWidgets(this::addRenderableWidget); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java index 12030037..b9fe79c8 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java @@ -4,26 +4,26 @@ import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.GridWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.renderService; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class NotificationOptionsScreen extends OptionsScreen { - private static final Text TEXT_NOTIFICATIONS = translatable("ucutils.options.text.notifications"); - private static final Text NOTIFICATION_JOIN_QUIT_NAME = translatable("ucutils.options.notifications.join_quit.name"); - private static final Text NOTIFICATION_JOIN_QUIT_TOOLTIP = translatable("ucutils.options.notifications.join_quit.tooltip"); - private static final Text NOTIFICATION_ADUTY_NAME = translatable("ucutils.options.notifications.aduty.name"); - private static final Text NOTIFICATION_ADUTY_TOOLTIP = translatable("ucutils.options.notifications.aduty.tooltip"); - private static final Text NOTIFICATION_REPORT_NAME = translatable("ucutils.options.notifications.report.name"); - private static final Text NOTIFICATION_REPORT_TOOLTIP = translatable("ucutils.options.notifications.report.tooltip"); - private static final Text NOTIFICATION_BUILD_MODE_NAME = translatable("ucutils.options.notifications.build_mode.name"); - private static final Text NOTIFICATION_BUILD_MODE_TOOLTIP = translatable("ucutils.options.notifications.build_mode.tooltip"); + private static final Component TEXT_NOTIFICATIONS = translatable("ucutils.options.text.notifications"); + private static final Component NOTIFICATION_JOIN_QUIT_NAME = translatable("ucutils.options.notifications.join_quit.name"); + private static final Component NOTIFICATION_JOIN_QUIT_TOOLTIP = translatable("ucutils.options.notifications.join_quit.tooltip"); + private static final Component NOTIFICATION_ADUTY_NAME = translatable("ucutils.options.notifications.aduty.name"); + private static final Component NOTIFICATION_ADUTY_TOOLTIP = translatable("ucutils.options.notifications.aduty.tooltip"); + private static final Component NOTIFICATION_REPORT_NAME = translatable("ucutils.options.notifications.report.name"); + private static final Component NOTIFICATION_REPORT_TOOLTIP = translatable("ucutils.options.notifications.report.tooltip"); + private static final Component NOTIFICATION_BUILD_MODE_NAME = translatable("ucutils.options.notifications.build_mode.name"); + private static final Component NOTIFICATION_BUILD_MODE_TOOLTIP = translatable("ucutils.options.notifications.build_mode.tooltip"); public NotificationOptionsScreen(Screen parent) { super(parent, TEXT_NOTIFICATIONS); @@ -37,33 +37,33 @@ public void doOnClose() { @Override public void initBody() { - GridWidget gridWidget = this.layout.addBody(new GridWidget()); - gridWidget.setColumnSpacing(8).setRowSpacing(4); - GridWidget.Adder gridWidgetAdder = gridWidget.createAdder(2); + GridLayout gridLayout = this.layout.addToContents(new GridLayout()); + gridLayout.columnSpacing(8).rowSpacing(4); + GridLayout.RowHelper gridLayoutRowHelper = gridLayout.createRowHelper(2); NotificationOptions notificationOptions = configuration.getOptions().notification(); ToggleButtonWidget toggleButton1 = new ToggleButtonWidget(NOTIFICATION_JOIN_QUIT_NAME, notificationOptions::joinQuit, notificationOptions.joinQuit()); toggleButton1.setWidth(150); - toggleButton1.setTooltip(Tooltip.of(NOTIFICATION_JOIN_QUIT_TOOLTIP)); - gridWidgetAdder.add(toggleButton1); + toggleButton1.setTooltip(Tooltip.create(NOTIFICATION_JOIN_QUIT_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton1); ToggleButtonWidget toggleButton2 = new ToggleButtonWidget(NOTIFICATION_ADUTY_NAME, notificationOptions::aDuty, notificationOptions.aDuty()); toggleButton2.setWidth(150); - toggleButton2.setTooltip(Tooltip.of(NOTIFICATION_ADUTY_TOOLTIP)); - gridWidgetAdder.add(toggleButton2); + toggleButton2.setTooltip(Tooltip.create(NOTIFICATION_ADUTY_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton2); ToggleButtonWidget toggleButton3 = new ToggleButtonWidget(NOTIFICATION_REPORT_NAME, notificationOptions::report, notificationOptions.report()); toggleButton3.setWidth(150); - toggleButton3.setTooltip(Tooltip.of(NOTIFICATION_REPORT_TOOLTIP)); - gridWidgetAdder.add(toggleButton3); + toggleButton3.setTooltip(Tooltip.create(NOTIFICATION_REPORT_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton3); ToggleButtonWidget toggleButton4 = new ToggleButtonWidget(NOTIFICATION_BUILD_MODE_NAME, notificationOptions::buildMode, notificationOptions.buildMode()); toggleButton4.setWidth(150); - toggleButton4.setTooltip(Tooltip.of(NOTIFICATION_BUILD_MODE_TOOLTIP)); - gridWidgetAdder.add(toggleButton4); + toggleButton4.setTooltip(Tooltip.create(NOTIFICATION_BUILD_MODE_TOOLTIP)); + gridLayoutRowHelper.addChild(toggleButton4); - gridWidget.refreshPositions(); - gridWidget.forEachChild(this::addDrawableChild); + gridLayout.arrangeElements(); + gridLayout.visitWidgets(this::addRenderableWidget); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/SoundOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/SoundOptionsScreen.java index 74e6e4c5..e508e52a 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/SoundOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/SoundOptionsScreen.java @@ -2,31 +2,31 @@ import de.rettichlp.ucutils.common.configuration.options.SoundOptions; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.renderService; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.horizontal; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.vertical; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; +import static net.minecraft.client.gui.layouts.LinearLayout.vertical; +import static net.minecraft.network.chat.Component.translatable; public class SoundOptionsScreen extends OptionsScreen { - private static final Text TEXT_SOUND = translatable("ucutils.options.text.sounds"); - private static final Text SOUND_BANK_ROBBERY_NAME = translatable("ucutils.sound.bank_robbery.name"); - private static final Text SOUND_BOMB_NAME = translatable("ucutils.sound.bomb.name"); - private static final Text SOUND_CONTRACT_SET_NAME = translatable("ucutils.sound.contract_set.name"); - private static final Text SOUND_CONTRACT_SET_TOOLTIP = translatable("ucutils.sound.contract_set.tooltip"); - private static final Text SOUND_CONTRACT_FULFILLED_NAME = translatable("ucutils.sound.contract_fulfilled.name"); - private static final Text SOUND_CONTRACT_FULFILLED_TOOLTIP = translatable("ucutils.sound.contract_fulfilled.tooltip"); - private static final Text SOUND_SERVICE_NAME = translatable("ucutils.sound.service.name"); - private static final Text SOUND_SERVICE_TOOLTIP = translatable("ucutils.sound.service.tooltip"); - private static final Text SOUND_FIRE_NAME = translatable("ucutils.sound.fire.name"); - private static final Text SOUND_REPORT_NAME = translatable("ucutils.sound.report.name"); - private static final Text SOUND_REPORT_TOOLTIP = translatable("ucutils.sound.report.tooltip"); - private static final Text SOUND_NOTIFICATION_NAME = translatable("ucutils.sound.notification.name"); - private static final Text SOUND_NOTIFICATION_TOOLTIP = translatable("ucutils.sound.notification.tooltip"); + private static final Component TEXT_SOUND = translatable("ucutils.options.text.sounds"); + private static final Component SOUND_BANK_ROBBERY_NAME = translatable("ucutils.sound.bank_robbery.name"); + private static final Component SOUND_BOMB_NAME = translatable("ucutils.sound.bomb.name"); + private static final Component SOUND_CONTRACT_SET_NAME = translatable("ucutils.sound.contract_set.name"); + private static final Component SOUND_CONTRACT_SET_TOOLTIP = translatable("ucutils.sound.contract_set.tooltip"); + private static final Component SOUND_CONTRACT_FULFILLED_NAME = translatable("ucutils.sound.contract_fulfilled.name"); + private static final Component SOUND_CONTRACT_FULFILLED_TOOLTIP = translatable("ucutils.sound.contract_fulfilled.tooltip"); + private static final Component SOUND_SERVICE_NAME = translatable("ucutils.sound.service.name"); + private static final Component SOUND_SERVICE_TOOLTIP = translatable("ucutils.sound.service.tooltip"); + private static final Component SOUND_FIRE_NAME = translatable("ucutils.sound.fire.name"); + private static final Component SOUND_REPORT_NAME = translatable("ucutils.sound.report.name"); + private static final Component SOUND_REPORT_TOOLTIP = translatable("ucutils.sound.report.tooltip"); + private static final Component SOUND_NOTIFICATION_NAME = translatable("ucutils.sound.notification.name"); + private static final Component SOUND_NOTIFICATION_TOOLTIP = translatable("ucutils.sound.notification.tooltip"); public SoundOptionsScreen(Screen parent) { super(parent, TEXT_SOUND); @@ -34,24 +34,24 @@ public SoundOptionsScreen(Screen parent) { @Override public void initBody() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addBody(vertical().spacing(4)); + LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4)); - DirectionalLayoutWidget directionalLayoutWidget1 = directionalLayoutWidget.add(horizontal().spacing(8)); + LinearLayout directionalLayoutWidget1 = directionalLayoutWidget.addChild(horizontal().spacing(8)); renderService.addCyclingButton(directionalLayoutWidget1, SOUND_BANK_ROBBERY_NAME, SoundOptions.StateSelect.values(), SoundOptions.StateSelect::getDisplayName, (options, e) -> options.sound().bankRobbery(e), options -> options.sound().bankRobbery(), 150); renderService.addCyclingButton(directionalLayoutWidget1, SOUND_BOMB_NAME, SoundOptions.StateSelect.values(), SoundOptions.StateSelect::getDisplayName, (options, e) -> options.sound().bomb(e), options -> options.sound().bomb(), 150); - DirectionalLayoutWidget directionalLayoutWidget2 = directionalLayoutWidget.add(horizontal().spacing(8)); + LinearLayout directionalLayoutWidget2 = directionalLayoutWidget.addChild(horizontal().spacing(8)); renderService.addToggleButton(directionalLayoutWidget2, SOUND_CONTRACT_SET_NAME, SOUND_CONTRACT_SET_TOOLTIP, (options, value) -> options.sound().contractSet(value), options -> options.sound().contractSet(), 150); renderService.addToggleButton(directionalLayoutWidget2, SOUND_CONTRACT_FULFILLED_NAME, SOUND_CONTRACT_FULFILLED_TOOLTIP, (options, value) -> options.sound().contractFulfilled(value), options -> options.sound().contractFulfilled(), 150); - DirectionalLayoutWidget directionalLayoutWidget3 = directionalLayoutWidget.add(horizontal().spacing(8)); + LinearLayout directionalLayoutWidget3 = directionalLayoutWidget.addChild(horizontal().spacing(8)); renderService.addToggleButton(directionalLayoutWidget3, SOUND_SERVICE_NAME, SOUND_SERVICE_TOOLTIP, (options, value) -> options.sound().service(value), options -> options.sound().service(), 150); renderService.addCyclingButton(directionalLayoutWidget3, SOUND_FIRE_NAME, SoundOptions.MedicSelect.values(), SoundOptions.MedicSelect::getDisplayName, (options, e) -> options.sound().fire(e), options -> options.sound().fire(), 150); - DirectionalLayoutWidget directionalLayoutWidget4 = directionalLayoutWidget.add(horizontal().spacing(8)); + LinearLayout directionalLayoutWidget4 = directionalLayoutWidget.addChild(horizontal().spacing(8)); renderService.addToggleButton(directionalLayoutWidget4, SOUND_REPORT_NAME, SOUND_REPORT_TOOLTIP, (options, value) -> options.sound().report(value), options -> options.sound().report(), 150); renderService.addToggleButton(directionalLayoutWidget4, SOUND_NOTIFICATION_NAME, SOUND_NOTIFICATION_TOOLTIP, (options, value) -> options.sound().notification(value), options -> options.sound().notification(), 150); - directionalLayoutWidget.forEachChild(this::addDrawableChild); + directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java index 694478ae..7436183e 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java @@ -1,15 +1,16 @@ package de.rettichlp.ucutils.common.gui.screens.options; +import com.mojang.blaze3d.platform.Window; import de.rettichlp.ucutils.common.gui.screens.UCUtilsScreen; import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.gui.Click; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.client.util.Window; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.input.MouseButtonEvent; +import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.renderService; @@ -20,11 +21,11 @@ import static java.awt.Color.GREEN; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.horizontal; -import static net.minecraft.screen.ScreenTexts.CANCEL; -import static net.minecraft.screen.ScreenTexts.DONE; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; +import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; +import static net.minecraft.network.chat.CommonComponents.GUI_CANCEL; +import static net.minecraft.network.chat.CommonComponents.GUI_DONE; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; public class WidgetOptionsPositionScreen extends UCUtilsScreen { @@ -38,20 +39,20 @@ public WidgetOptionsPositionScreen(Screen parent) { @Override public void initBody() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addBody(horizontal().spacing(8), positioner -> positioner.marginTop(this.client.getWindow().getScaledHeight() / 4)); + LinearLayout directionalLayoutWidget = this.layout.addToContents(horizontal().spacing(8), positioner -> positioner.paddingTop(this.minecraft.getWindow().getGuiScaledHeight() / 4)); - directionalLayoutWidget.add(ButtonWidget.builder(DONE, button -> { + directionalLayoutWidget.addChild(Button.builder(GUI_DONE, button -> { renderService.getWidgets().forEach(AbstractUCUtilsWidget::saveConfiguration); back(); }).width(150).build()); - directionalLayoutWidget.add(ButtonWidget.builder(CANCEL, button -> { + directionalLayoutWidget.addChild(Button.builder(GUI_CANCEL, button -> { // restore configurations from the configuration file renderService.getWidgets().forEach(AbstractUCUtilsWidget::loadConfiguration); back(); }).width(150).build()); - directionalLayoutWidget.forEachChild(this::addDrawableChild); + directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } @Override @@ -60,15 +61,15 @@ public void doOnClose() { } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - super.render(context, mouseX, mouseY, delta); + public void extractRenderState(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + super.extractRenderState(graphics, mouseX, mouseY, a); // draw center help lines - Window window = this.client.getWindow(); - int scaledWidth = window.getScaledWidth(); - int scaledHeight = window.getScaledHeight(); - context.drawHorizontalLine(0, scaledWidth, scaledHeight / 2 - 1, GREEN.getRGB()); - context.drawVerticalLine(scaledWidth / 2 - 1, 0, scaledHeight, GREEN.getRGB()); + Window window = this.minecraft.getWindow(); + int scaledWidth = window.getGuiScaledWidth(); + int scaledHeight = window.getGuiScaledHeight(); + graphics.horizontalLine(0, scaledWidth, scaledHeight / 2 - 1, GREEN.getRGB()); + graphics.verticalLine(scaledWidth / 2 - 1, 0, scaledHeight, GREEN.getRGB()); // draw widget help lines renderService.getWidgets().forEach(abstractUCUtilsWidget -> { @@ -77,10 +78,10 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { double xBottomRight = xTopLeft + abstractUCUtilsWidget.getWidth(); double yBottomRight = yTopLeft + abstractUCUtilsWidget.getHeight(); - context.drawHorizontalLine(0, scaledWidth, (int) yTopLeft, GRAY.getRGB()); - context.drawHorizontalLine(0, scaledWidth, (int) yBottomRight - 1, GRAY.getRGB()); - context.drawVerticalLine((int) xTopLeft, 0, scaledHeight, GRAY.getRGB()); - context.drawVerticalLine((int) xBottomRight - 1, 0, scaledHeight, GRAY.getRGB()); + graphics.horizontalLine(0, scaledWidth, (int) yTopLeft, GRAY.getRGB()); + graphics.horizontalLine(0, scaledWidth, (int) yBottomRight - 1, GRAY.getRGB()); + graphics.verticalLine((int) xTopLeft, 0, scaledHeight, GRAY.getRGB()); + graphics.verticalLine((int) xBottomRight - 1, 0, scaledHeight, GRAY.getRGB()); }); if (isNull(this.selectedWidget)) { @@ -97,20 +98,20 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { double y = widgetConfiguration.getY(); // draw widget location text box - Text widgetLocationText = of("X: " + x + " Y: " + y + " (W: " + this.selectedWidget.getWidth() + " H: " + this.selectedWidget.getHeight() + ")"); - context.fill(textX - TEXT_BOX_PADDING, textY - TEXT_BOX_PADDING, textX + this.textRenderer.getWidth(widgetLocationText) + TEXT_BOX_PADDING, textY + this.textRenderer.fontHeight + TEXT_BOX_PADDING, renderService.getSecondaryColor(BLACK).getRGB()); - context.drawText(this.textRenderer, widgetLocationText, textX, textY, 0xFFFFFFFF, false); + Component widgetLocationText = literal("X: " + x + " Y: " + y + " (W: " + this.selectedWidget.getWidth() + " H: " + this.selectedWidget.getHeight() + ")"); + graphics.fill(textX - TEXT_BOX_PADDING, textY - TEXT_BOX_PADDING, textX + this.font.width(widgetLocationText) + TEXT_BOX_PADDING, textY + this.font.lineHeight + TEXT_BOX_PADDING, renderService.getSecondaryColor(BLACK).getRGB()); + graphics.text(this.font, widgetLocationText, textX, textY, 0xFFFFFFFF, false); // draw widget center lines double centerX = x + (this.selectedWidget.getWidth() / 2.0); double centerY = y + (this.selectedWidget.getHeight() / 2.0); - context.drawHorizontalLine(0, scaledWidth, (int) centerY, BLUE.getRGB()); - context.drawVerticalLine((int) centerX, 0, scaledHeight, BLUE.getRGB()); + graphics.horizontalLine(0, scaledWidth, (int) centerY, BLUE.getRGB()); + graphics.verticalLine((int) centerX, 0, scaledHeight, BLUE.getRGB()); } // disable background rendering to see overlay better @Override - public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {} + public void extractBackground(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {} @Override public void mouseMoved(double mouseX, double mouseY) { @@ -130,11 +131,11 @@ public void mouseMoved(double mouseX, double mouseY) { } @Override - public boolean mouseClicked(Click click, boolean doubled) { - boolean mouseClicked = super.mouseClicked(click, doubled); + public boolean mouseClicked(@NonNull MouseButtonEvent event, boolean doubleClick) { + boolean mouseClicked = super.mouseClicked(event, doubleClick); renderService.getWidgets().stream() - .filter(abstractUCUtilsWidget -> abstractUCUtilsWidget.isMouseOver(click.x(), click.y())) + .filter(abstractUCUtilsWidget -> abstractUCUtilsWidget.isMouseOver(event.x(), event.y())) .findFirst() .ifPresent(abstractUCUtilsWidget -> this.selectedWidget = abstractUCUtilsWidget); @@ -142,8 +143,8 @@ public boolean mouseClicked(Click click, boolean doubled) { } @Override - public boolean mouseReleased(Click click) { - boolean mouseReleased = super.mouseReleased(click); + public boolean mouseReleased(@NonNull MouseButtonEvent event) { + boolean mouseReleased = super.mouseReleased(event); this.selectedWidget = null; return mouseReleased; } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java index be8b47ee..f77aa9c5 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java @@ -4,25 +4,25 @@ import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.IOptionWidget; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.client.gui.widget.GridWidget; -import net.minecraft.client.gui.widget.Positioner; -import net.minecraft.client.gui.widget.TextWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.layouts.LayoutSettings; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.renderService; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.vertical; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.client.gui.layouts.LinearLayout.vertical; +import static net.minecraft.network.chat.Component.translatable; public class WidgetOptionsScreen extends OptionsScreen { - private static final Text TEXT_WIDGETS = translatable("ucutils.options.text.widgets"); - private static final Text TEXT_GENERAL = translatable("ucutils.options.text.general"); - private static final Text TEXT_POSITION = translatable("ucutils.options.text.position"); + private static final Component TEXT_WIDGETS = translatable("ucutils.options.text.widgets"); + private static final Component TEXT_GENERAL = translatable("ucutils.options.text.general"); + private static final Component TEXT_POSITION = translatable("ucutils.options.text.position"); public WidgetOptionsScreen(Screen parent) { super(parent, TEXT_WIDGETS, false); @@ -36,27 +36,27 @@ public void doOnClose() { @Override public void initBody() { - DirectionalLayoutWidget directionalLayoutWidget = this.layout.addBody(vertical().spacing(4)); + LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4)); // general - directionalLayoutWidget.add(new TextWidget(TEXT_GENERAL, this.textRenderer), Positioner::alignHorizontalCenter); + directionalLayoutWidget.addChild(new StringWidget(TEXT_GENERAL, this.font), LayoutSettings::alignHorizontallyCenter); - directionalLayoutWidget.add(ButtonWidget.builder(TEXT_POSITION, button -> this.client.setScreen(new WidgetOptionsPositionScreen(this))).width(308).build()); + directionalLayoutWidget.addChild(Button.builder(TEXT_POSITION, button -> this.minecraft.setScreen(new WidgetOptionsPositionScreen(this))).width(308).build()); // general - enable status - GridWidget gridWidget = directionalLayoutWidget.add(new GridWidget()); - gridWidget.setColumnSpacing(8).setRowSpacing(4); - GridWidget.Adder gridWidgetAdder = gridWidget.createAdder(2); + GridLayout gridLayout = this.layout.addToContents(new GridLayout()); + gridLayout.columnSpacing(8).rowSpacing(4); + GridLayout.RowHelper gridLayoutRowHelper = gridLayout.createRowHelper(2); renderService.getWidgets().forEach(abstractUCUtilsWidget -> { - Text displayName = abstractUCUtilsWidget.getDisplayName(); + Component displayName = abstractUCUtilsWidget.getDisplayName(); ToggleButtonWidget toggleButton = new ToggleButtonWidget(displayName, value -> abstractUCUtilsWidget.getWidgetConfiguration().setEnabled(value), abstractUCUtilsWidget.getWidgetConfiguration().isEnabled()); - toggleButton.setTooltip(Tooltip.of(abstractUCUtilsWidget.getTooltip())); - gridWidgetAdder.add(toggleButton); + toggleButton.setTooltip(Tooltip.create(abstractUCUtilsWidget.getTooltip())); + gridLayoutRowHelper.addChild(toggleButton); }); - gridWidget.refreshPositions(); - gridWidget.forEachChild(this::addDrawableChild); + gridLayout.arrangeElements(); + gridLayout.visitWidgets(this::addRenderableWidget); // options section per widget renderService.getWidgets().stream() @@ -65,17 +65,18 @@ public void initBody() { IOptionWidget iOptionWidget = (IOptionWidget) abstractUCUtilsWidget.getWidgetConfiguration(); // section title - Text text = abstractUCUtilsWidget.getDisplayName(); - directionalLayoutWidget.add(new TextWidget(text, this.textRenderer), positioner -> positioner.alignHorizontalCenter().marginTop(16)); + Component text = abstractUCUtilsWidget.getDisplayName(); + directionalLayoutWidget.addChild(new StringWidget(text, this.font), positioner -> positioner.alignHorizontallyCenter().paddingTop(16)); // options widget - directionalLayoutWidget.add(iOptionWidget.optionsWidget(), Positioner::alignHorizontalCenter); + directionalLayoutWidget.addChild(iOptionWidget.optionsWidget(), LayoutSettings::alignHorizontallyCenter); }); - directionalLayoutWidget.forEachChild(this::addDrawableChild); + directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } // disable background rendering to see overlay better + @Override - public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {} + public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {} } From b9c0482f09c7e65d9ae22e8676a6dc85dfb1d1be Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 20:12:58 +0200 Subject: [PATCH 06/64] Align widgets with Minecraft 26.1.2 API changes --- .../common/gui/widgets/CarLockedWidget.java | 61 +++++++++---------- .../common/gui/widgets/CountdownWidget.java | 12 ++-- .../common/gui/widgets/DateTimeWidget.java | 14 ++--- .../common/gui/widgets/HearthWidget.java | 30 ++++----- .../common/gui/widgets/MoneyWidget.java | 14 ++--- .../gui/widgets/NotificationWidget.java | 12 ++-- .../common/gui/widgets/PayDayWidget.java | 48 +++++++-------- .../gui/widgets/ServiceCountWidget.java | 17 +++--- .../alignment/AlignHorizontalWidget.java | 14 ++--- .../alignment/AlignVerticalWidget.java | 14 ++--- .../AbstractUCUtilsProgressTextWidget.java | 14 ++--- .../base/AbstractUCUtilsTextWidget.java | 36 +++++------ .../widgets/base/AbstractUCUtilsWidget.java | 26 ++++---- .../gui/widgets/base/IOptionWidget.java | 4 +- 14 files changed, 158 insertions(+), 158 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java index 83f0486b..c54a0c77 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java @@ -9,46 +9,46 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; -import net.minecraft.client.gui.tooltip.Tooltip; -import net.minecraft.client.gui.widget.CyclingButtonWidget; -import net.minecraft.client.gui.widget.Widget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.CycleButton; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.layouts.LayoutElement; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.common.gui.widgets.CarLockedWidget.Style.MINIMALISTIC; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; @UCUtilsWidget(registryName = "car_locked", defaultX = 110.0, defaultY = 4.0) public class CarLockedWidget extends AbstractUCUtilsTextWidget { - private static final Text WIDGETS_CAR_LOCKED_OPTIONS_NAME = translatable("ucutils.options.widgets.car_locked.options.name"); - private static final Text WIDGETS_CAR_LOCKED_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.car_locked.options.tooltip"); - private static final Text WIDGETS_CAR_LOCKED_OPTIONS_STYLE_NAME = translatable("ucutils.options.widgets.car_locked.options.style.name"); + private static final Component WIDGETS_CAR_LOCKED_OPTIONS_NAME = translatable("ucutils.options.widgets.car_locked.options.name"); + private static final Component WIDGETS_CAR_LOCKED_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.car_locked.options.tooltip"); + private static final Component WIDGETS_CAR_LOCKED_OPTIONS_STYLE_NAME = translatable("ucutils.options.widgets.car_locked.options.style.name"); @Override - public Text text() { + public Component text() { return getWidgetConfiguration().getStyle() == MINIMALISTIC - ? (storage.isCarLocked() ? of("🔒").copy().formatted(GREEN) : of("🔓").copy().formatted(GOLD)) + ? (storage.isCarLocked() ? literal("🔒").withStyle(GREEN) : literal("🔓").withStyle(GOLD)) : empty() - .append(of("Fahrzeug").copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(storage.isCarLocked() ? of("zu").copy().formatted(GREEN) : of("offen").copy().formatted(GOLD)); + .append(literal("Fahrzeug").withStyle(GRAY)) + .append(literal(":").withStyle(DARK_GRAY)).append(" ") + .append(storage.isCarLocked() ? literal("zu").withStyle(GREEN) : literal("offen").withStyle(GOLD)); } @Override - public Text getDisplayName() { + public Component getDisplayName() { return WIDGETS_CAR_LOCKED_OPTIONS_NAME; } @Override - public Text getTooltip() { + public Component getTooltip() { return WIDGETS_CAR_LOCKED_OPTIONS_TOOLTIP; } @@ -59,17 +59,17 @@ public enum Style implements CyclingButtonEntry { DEFAULT(translatable("ucutils.options.widgets.car_locked.options.style.value.default.name"), translatable("ucutils.options.widgets.car_locked.options.style.value.default.tooltip")), MINIMALISTIC(translatable("ucutils.options.widgets.car_locked.options.style.value.minimalistic.name"), translatable("ucutils.options.widgets.car_locked.options.style.value.minimalistic.tooltip")); - private final Text name; - private final Text tooltip; + private final Component name; + private final Component tooltip; @Override - public @NotNull Text getDisplayName() { + public @NotNull Component getDisplayName() { return this.name; } @Override public @NotNull Tooltip getTooltip() { - return Tooltip.of(this.tooltip); + return Tooltip.create(this.tooltip); } } @@ -80,12 +80,11 @@ public static class Configuration extends UCUtilsWidgetConfiguration implements private Style style = MINIMALISTIC; @Override - public Widget optionsWidget() { - return CyclingButtonWidget.builder(Style::getDisplayName) - .values(Style.values()) - .initially(this.style) - .tooltip(Style::getTooltip) - .build(WIDGETS_CAR_LOCKED_OPTIONS_STYLE_NAME, (button, style) -> this.style = style); + public LayoutElement optionsWidget() { + return CycleButton.builder(Style::getDisplayName, this.style) + .withValues(Style.values()) + .withTooltip(Style::getTooltip) + .create(WIDGETS_CAR_LOCKED_OPTIONS_STYLE_NAME, (_, style) -> this.style = style); } } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java index 6fc18894..15fb3e45 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java @@ -4,24 +4,24 @@ import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; import lombok.RequiredArgsConstructor; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.time.LocalDateTime; import static java.time.LocalDateTime.now; import static java.time.temporal.ChronoUnit.MILLIS; -import static net.minecraft.text.Text.empty; +import static net.minecraft.network.chat.Component.empty; @RequiredArgsConstructor @UCUtilsWidget(registryName = "countdown") public class CountdownWidget extends AbstractUCUtilsProgressTextWidget { - private final Text text; + private final Component text; private final LocalDateTime creationTime; private final long durationInMillis; @Override - public Text text() { + public Component text() { return this.text; } @@ -31,12 +31,12 @@ public double progress() { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return empty(); } @Override - public Text getTooltip() { + public Component getTooltip() { return empty(); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java index b2efd55d..4ed2de69 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java @@ -3,28 +3,28 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.messageService; import static java.time.LocalDateTime.now; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; @UCUtilsWidget(registryName = "date_time", defaultX = 4.0, defaultY = 4.0) public class DateTimeWidget extends AbstractUCUtilsTextWidget { @Override - public Text text() { - return of(messageService.dateTimeToFriendlyString(now())); + public Component text() { + return literal(messageService.dateTimeToFriendlyString(now())); } @Override - public Text getDisplayName() { + public Component getDisplayName() { return translatable("ucutils.options.widgets.date_time.options.name"); } @Override - public Text getTooltip() { + public Component getTooltip() { return translatable("ucutils.options.widgets.date_time.options.tooltip"); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java index db7bbc78..206abaca 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java @@ -4,34 +4,34 @@ import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; import lombok.AllArgsConstructor; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import java.awt.Color; import static java.lang.String.format; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.RED; -import static net.minecraft.util.Formatting.YELLOW; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; @UCUtilsWidget(registryName = "hearth", defaultX = 4.0, defaultY = 4.0, defaultEnabled = false) public class HearthWidget extends AbstractUCUtilsTextWidget { @Override - public Text text() { - ClientPlayerEntity player = MinecraftClient.getInstance().player; + public Component text() { + LocalPlayer player = Minecraft.getInstance().player; assert player != null; // cannot be null at this point float absorptionAmount = player.getAbsorptionAmount(); float overallAmount = player.getHealth() + absorptionAmount; String overallAmountString = format("%.1f", overallAmount / 2).replaceAll(",0$", ""); - MutableText text = of(overallAmountString).copy().formatted(absorptionAmount > 0 ? YELLOW : GRAY); - return text.append(of("❤").copy().formatted(RED)); + MutableComponent text = literal(overallAmountString).withStyle(absorptionAmount > 0 ? YELLOW : GRAY); + return text.append(literal("❤").withStyle(RED)); } @Override @@ -45,12 +45,12 @@ public Color getBackgroundColor() { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return translatable("ucutils.options.widgets.hearth.options.name"); } @Override - public Text getTooltip() { + public Component getTooltip() { return translatable("ucutils.options.widgets.hearth.options.tooltip"); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java index 3411898e..16d8312a 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java @@ -4,36 +4,36 @@ import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; import lombok.AllArgsConstructor; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.configuration; import static java.awt.Color.RED; import static java.lang.System.currentTimeMillis; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.translatable; @UCUtilsWidget(registryName = "money", defaultX = 4.0, defaultY = 23.0) public class MoneyWidget extends AbstractUCUtilsTextWidget { @Override - public Text text() { + public Component text() { // with over 100.000$ on bank and PayDay within next 5 minutes, animate text return configuration.getMinutesSinceLastPayDay() >= 55 && configuration.getMoneyBankAmount() > 100000 && (currentTimeMillis() / 500 % 2 == 0) ? empty() .append(keyValue("Geld", configuration.getMoneyCashAmount() + "$")).append(" ") - .append(keyValue("Bank", configuration.getMoneyBankAmount() + "$").withColor(RED.getRGB())) + .append(keyValue("Bank", configuration.getMoneyBankAmount() + "$").copy().withColor(RED.getRGB())) : empty() .append(keyValue("Geld", configuration.getMoneyCashAmount() + "$")).append(" ") .append(keyValue("Bank", configuration.getMoneyBankAmount() + "$")); } @Override - public Text getDisplayName() { + public Component getDisplayName() { return translatable("ucutils.options.widgets.money.options.name"); } @Override - public Text getTooltip() { + public Component getTooltip() { return translatable("ucutils.options.widgets.money.options.tooltip"); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java index e03d5065..8b2b3d83 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java @@ -4,26 +4,26 @@ import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; import lombok.RequiredArgsConstructor; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.awt.Color; import java.time.LocalDateTime; import static java.time.LocalDateTime.now; import static java.time.temporal.ChronoUnit.MILLIS; -import static net.minecraft.text.Text.empty; +import static net.minecraft.network.chat.Component.empty; @RequiredArgsConstructor @UCUtilsWidget(registryName = "notification") public class NotificationWidget extends AbstractUCUtilsProgressTextWidget { - private final Text text; + private final Component text; private final Color borderColor; private final LocalDateTime creationTime; private final long durationInMillis; @Override - public Text text() { + public Component text() { return this.text; } @@ -38,12 +38,12 @@ public Color getBorderColor() { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return empty(); } @Override - public Text getTooltip() { + public Component getTooltip() { return empty(); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java index f8f75eea..dbc8ef29 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java @@ -6,10 +6,10 @@ import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; import lombok.Data; import lombok.EqualsAndHashCode; -import net.minecraft.client.gui.widget.DirectionalLayoutWidget; -import net.minecraft.client.gui.widget.Widget; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.client.gui.layouts.LayoutElement; +import net.minecraft.client.gui.layouts.LinearLayout; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import java.awt.Color; @@ -18,28 +18,28 @@ import static java.awt.Color.RED; import static java.lang.String.valueOf; import static java.lang.System.currentTimeMillis; -import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.horizontal; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; @UCUtilsWidget(registryName = "payday", defaultX = 126.0, defaultY = 4.0) public class PayDayWidget extends AbstractUCUtilsTextWidget { - private static final Text WIDGETS_PAYDAY_OPTIONS_NAME = translatable("ucutils.options.widgets.payday.options.name"); - private static final Text WIDGETS_PAYDAY_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.payday.options.tooltip"); - private static final Text WIDGETS_PAYDAY_OPTIONS_SALARY_NAME = translatable("ucutils.options.widgets.payday.options.salary.name"); - private static final Text WIDGETS_PAYDAY_OPTIONS_SALARY_TOOLTIP = translatable("ucutils.options.widgets.payday.options.salary.tooltip"); - private static final Text WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_NAME = translatable("ucutils.options.widgets.payday.options.experience.name"); - private static final Text WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_TOOLTIP = translatable("ucutils.options.widgets.payday.options.experience.tooltip"); + private static final Component WIDGETS_PAYDAY_OPTIONS_NAME = translatable("ucutils.options.widgets.payday.options.name"); + private static final Component WIDGETS_PAYDAY_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.payday.options.tooltip"); + private static final Component WIDGETS_PAYDAY_OPTIONS_SALARY_NAME = translatable("ucutils.options.widgets.payday.options.salary.name"); + private static final Component WIDGETS_PAYDAY_OPTIONS_SALARY_TOOLTIP = translatable("ucutils.options.widgets.payday.options.salary.tooltip"); + private static final Component WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_NAME = translatable("ucutils.options.widgets.payday.options.experience.name"); + private static final Component WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_TOOLTIP = translatable("ucutils.options.widgets.payday.options.experience.tooltip"); @Override - public Text text() { - MutableText payDayInfoText = keyValue("PayDay", empty() - .append(of(valueOf(configuration.getMinutesSinceLastPayDay()))) - .append(of("/").copy().formatted(DARK_GRAY)) - .append(of("60"))); + public Component text() { + MutableComponent payDayInfoText = keyValue("PayDay", empty() + .append(literal(valueOf(configuration.getMinutesSinceLastPayDay()))) + .append(literal("/").withStyle(DARK_GRAY)) + .append(literal("60"))); if (getWidgetConfiguration().isShowSalary()) { payDayInfoText.append(" ").append(keyValue("Gehalt", configuration.getPredictedPayDaySalary() + "$")); @@ -61,12 +61,12 @@ public Color getBackgroundColor() { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return WIDGETS_PAYDAY_OPTIONS_NAME; } @Override - public Text getTooltip() { + public Component getTooltip() { return WIDGETS_PAYDAY_OPTIONS_TOOLTIP; } @@ -78,8 +78,8 @@ public static class Configuration extends UCUtilsWidgetConfiguration implements private boolean showExperience = true; @Override - public Widget optionsWidget() { - DirectionalLayoutWidget directionalLayoutWidget = horizontal().spacing(8); + public LayoutElement optionsWidget() { + LinearLayout directionalLayoutWidget = horizontal().spacing(8); renderService.addToggleButton(directionalLayoutWidget, WIDGETS_PAYDAY_OPTIONS_SALARY_NAME, WIDGETS_PAYDAY_OPTIONS_SALARY_TOOLTIP, (options, value) -> this.showSalary = value, options -> this.showSalary, 150); renderService.addToggleButton(directionalLayoutWidget, WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_NAME, WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_TOOLTIP, (options, value) -> this.showExperience = value, options -> this.showExperience, 150); return directionalLayoutWidget; diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java index 5eb50719..bc3ce753 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java @@ -4,23 +4,24 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.MinecraftClient; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; import java.awt.Color; import static de.rettichlp.ucutils.UCUtils.storage; import static java.awt.Color.RED; import static java.lang.String.valueOf; +import static net.minecraft.network.chat.Component.translatable; @UCUtilsWidget(registryName = "service_count", defaultX = 4.0, defaultY = 42.0) public class ServiceCountWidget extends AbstractUCUtilsTextWidget { - private static final Text WIDGETS_SERVICE_COUNT_OPTIONS_NAME = Text.translatable("ucutils.options.widgets.service_count.options.name"); - private static final Text WIDGETS_SERVICE_COUNT_OPTIONS_TOOLTIP = Text.translatable("ucutils.options.widgets.service_count.options.tooltip"); + private static final Component WIDGETS_SERVICE_COUNT_OPTIONS_NAME = translatable("ucutils.options.widgets.service_count.options.name"); + private static final Component WIDGETS_SERVICE_COUNT_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.service_count.options.tooltip"); @Override - public Text text() { + public Component text() { return keyValue("Services", valueOf(storage.getActiveServices())); } @@ -30,19 +31,19 @@ public Color getBorderColor() { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return WIDGETS_SERVICE_COUNT_OPTIONS_NAME; } @Override - public Text getTooltip() { + public Component getTooltip() { return WIDGETS_SERVICE_COUNT_OPTIONS_TOOLTIP; } @Override public boolean isVisible() { // visible if in the position options screen to allow positioning - return storage.getActiveServices() > 0 || MinecraftClient.getInstance().currentScreen instanceof WidgetOptionsPositionScreen; + return storage.getActiveServices() > 0 || Minecraft.getInstance().screen instanceof WidgetOptionsPositionScreen; } public static class Configuration extends UCUtilsWidgetConfiguration {} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java index e1bdac05..654d46e4 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java @@ -2,11 +2,11 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; -import static net.minecraft.text.Text.empty; +import static net.minecraft.network.chat.Component.empty; public class AlignHorizontalWidget extends AlignWidget> { @@ -16,12 +16,12 @@ public void add(AbstractUCUtilsWidget entry) { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return empty(); } @Override - public Text getTooltip() { + public Component getTooltip() { return empty(); } @@ -36,11 +36,11 @@ public int getHeight() { } @Override - public void draw(@NotNull DrawContext drawContext, int x, int y, AbstractUCUtilsWidget.Alignment alignment) { + public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, AbstractUCUtilsWidget.Alignment alignment) { int xOffset = x; for (AbstractUCUtilsWidget ucUtilsWidget : this.ucUtilsWidgets) { - ucUtilsWidget.draw(drawContext, xOffset, y, alignment); + ucUtilsWidget.draw(graphics, xOffset, y, alignment); xOffset += ucUtilsWidget.getWidth(); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java index d29a174d..4225a760 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java @@ -2,11 +2,11 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; -import static net.minecraft.text.Text.empty; +import static net.minecraft.network.chat.Component.empty; public class AlignVerticalWidget extends AlignWidget> { @@ -16,12 +16,12 @@ public void add(AbstractUCUtilsWidget entry) { } @Override - public Text getDisplayName() { + public Component getDisplayName() { return empty(); } @Override - public Text getTooltip() { + public Component getTooltip() { return empty(); } @@ -36,7 +36,7 @@ public int getHeight() { } @Override - public void draw(@NotNull DrawContext drawContext, int x, int y, AbstractUCUtilsWidget.Alignment alignment) { + public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, AbstractUCUtilsWidget.Alignment alignment) { int yOffset = y; for (AbstractUCUtilsWidget ucUtilsWidget : this.ucUtilsWidgets) { @@ -47,7 +47,7 @@ public void draw(@NotNull DrawContext drawContext, int x, int y, AbstractUCUtils case RIGHT -> getWidth() - ucUtilsWidget.getWidth(); }; - ucUtilsWidget.draw(drawContext, x + alignmentXModifier, yOffset, alignment); + ucUtilsWidget.draw(graphics, x + alignmentXModifier, yOffset, alignment); yOffset += ucUtilsWidget.getHeight(); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java index 8ecfb7b3..a0d66b6a 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java @@ -1,7 +1,7 @@ package de.rettichlp.ucutils.common.gui.widgets.base; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.time.temporal.Temporal; @@ -14,18 +14,18 @@ public abstract class AbstractUCUtilsProgressTextWidget extends AbstractUCUtilsTextWidget { @Override - public abstract Text text(); + public abstract Component text(); @Override - public void draw(@NotNull DrawContext drawContext, int x, int y, Alignment alignment) { - drawContext.fill(x, y, x + getWidth(), y + getHeight(), getBackgroundColor().getRGB()); - drawContext.drawText(getTextRenderer(), text(), x + TEXT_BOX_PADDING, y + TEXT_BOX_PADDING, 0xFFFFFFFF, false); + public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, Alignment alignment) { + graphics.fill(x, y, x + getWidth(), y + getHeight(), getBackgroundColor().getRGB()); + graphics.text(getFont(), text(), x + TEXT_BOX_PADDING, y + TEXT_BOX_PADDING, 0xFFFFFFFF, false); int maxProgressWidth = getWidth() - TEXT_BOX_PADDING * 2; int xProgressStart = (int) (x + TEXT_BOX_PADDING + maxProgressWidth * progress()); int xProgressEnd = x + getWidth() - TEXT_BOX_PADDING; - drawContext.drawHorizontalLine(xProgressStart, xProgressEnd, y + getHeight() - 3, getBorderColor().getRGB()); + graphics.horizontalLine(xProgressStart, xProgressEnd, y + getHeight() - 3, getBorderColor().getRGB()); } public abstract double progress(); diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java index 4288c9f3..1b0e3f21 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java @@ -1,8 +1,8 @@ package de.rettichlp.ucutils.common.gui.widgets.base; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import org.jetbrains.annotations.NotNull; import java.awt.Color; @@ -10,30 +10,30 @@ import static de.rettichlp.ucutils.UCUtils.renderService; import static de.rettichlp.ucutils.common.services.RenderService.TEXT_BOX_PADDING; import static java.awt.Color.WHITE; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GRAY; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; public abstract class AbstractUCUtilsTextWidget extends AbstractUCUtilsWidget { - public abstract Text text(); + public abstract Component text(); @Override public int getWidth() { - int fontWidth = getTextRenderer().getWidth(text()); + int fontWidth = getFont().width(text()); return fontWidth + 2 * TEXT_BOX_PADDING; } @Override public int getHeight() { - return getTextRenderer().fontHeight + 2 * TEXT_BOX_PADDING; + return getFont().lineHeight + 2 * TEXT_BOX_PADDING; } @Override - public void draw(@NotNull DrawContext drawContext, int x, int y, Alignment alignment) { - drawContext.fill(x, y, x + getWidth(), y + getHeight(), getBackgroundColor().getRGB()); - drawContext.drawText(getTextRenderer(), text(), x + TEXT_BOX_PADDING, y + TEXT_BOX_PADDING, 0xFFFFFFFF, false); + public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, Alignment alignment) { + graphics.fill(x, y, x + getWidth(), y + getHeight(), getBackgroundColor().getRGB()); + graphics.text(getFont(), text(), x + TEXT_BOX_PADDING, y + TEXT_BOX_PADDING, 0xFFFFFFFF, false); } public Color getBorderColor() { @@ -44,14 +44,14 @@ public Color getBackgroundColor() { return renderService.getSecondaryColor(getBorderColor()); } - protected MutableText keyValue(String key, String value) { - return keyValue(key, of(value)); + protected Component keyValue(String key, String value) { + return keyValue(key, literal(value)); } - protected MutableText keyValue(String key, Text value) { + protected MutableComponent keyValue(String key, Component value) { return empty() - .append(of(key).copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") + .append(literal(key).withStyle(GRAY)) + .append(literal(":").withStyle(DARK_GRAY)).append(" ") .append(value); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java index b6261389..9f7b2385 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java @@ -2,10 +2,10 @@ import com.google.common.reflect.TypeToken; import lombok.Getter; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.lang.reflect.ParameterizedType; @@ -21,39 +21,39 @@ import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; import static java.util.Objects.isNull; import static java.util.Optional.ofNullable; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; @Getter public abstract class AbstractUCUtilsWidget { private static final Type MAP_TYPE = new TypeToken>() {}.getType(); - private final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + private final Font font = Minecraft.getInstance().font; private C widgetConfiguration; - public abstract Text getDisplayName(); + public abstract Component getDisplayName(); - public abstract Text getTooltip(); + public abstract Component getTooltip(); public abstract int getWidth(); public abstract int getHeight(); - public abstract void draw(@NotNull DrawContext drawContext, int x, int y, Alignment alignment); + public abstract void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, Alignment alignment); public void init() { loadConfiguration(); } - public void draw(@NotNull DrawContext drawContext) { - if (!isVisible() || !this.widgetConfiguration.isEnabled() || MinecraftClient.getInstance().options.hudHidden) { + public void draw(@NotNull GuiGraphicsExtractor graphics) { + if (!isVisible() || !this.widgetConfiguration.isEnabled() || Minecraft.getInstance().options.hideGui) { return; } int x = (int) this.widgetConfiguration.getX(); int y = (int) this.widgetConfiguration.getY(); - draw(drawContext, x, y, getAlignment()); + draw(graphics, x, y, getAlignment()); } public boolean isMouseOver(double mouseX, double mouseY) { @@ -125,7 +125,7 @@ public void saveConfiguration() { } private Alignment getAlignment() { - int scaledWidth = MinecraftClient.getInstance().getWindow().getScaledWidth(); + int scaledWidth = Minecraft.getInstance().getWindow().getGuiScaledWidth(); int widthSegment = scaledWidth / 3; Alignment alignment; diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java index 6cf458a1..20ba27af 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java @@ -1,8 +1,8 @@ package de.rettichlp.ucutils.common.gui.widgets.base; -import net.minecraft.client.gui.widget.Widget; +import net.minecraft.client.gui.layouts.LayoutElement; public interface IOptionWidget { - Widget optionsWidget(); + LayoutElement optionsWidget(); } From 5c66b51b0932e8b2a12fcf1de31f0674ad555fc2 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 22:16:21 +0200 Subject: [PATCH 07/64] Remove unused `HandledScreenMixin` and align remaining mixins with Minecraft 26.1.2 API changes --- .../mixin/AbstractContainerScreenMixin.java | 103 ++++++ .../AbstractMinecartEntityRendererMixin.java | 32 -- .../mixin/AbstractMinecartRendererMixin.java | 38 ++ .../ucutils/mixin/ChatScreenMixin.java | 4 +- .../mixin/ClientPlayNetworkHandlerMixin.java | 327 +++++++++--------- .../mixin/ClientPlayerEntityMixin.java | 26 +- .../rettichlp/ucutils/mixin/EntityMixin.java | 22 +- .../ucutils/mixin/EntityRendererMixin.java | 59 ++++ .../ucutils/mixin/GameMenuScreenMixin.java | 29 +- .../de/rettichlp/ucutils/mixin/GuiMixin.java | 134 +++++++ .../ucutils/mixin/HandledScreenMixin.java | 112 ------ .../ucutils/mixin/InGameHudMixin.java | 177 ---------- .../ucutils/mixin/ItemStackMixin.java | 18 +- ...artEntityMixin.java => MinecartMixin.java} | 24 +- .../mixin/PlayerEntityRendererMixin.java | 62 ---- .../ucutils/mixin/PlayerListHudMixin.java | 43 --- .../ucutils/mixin/PlayerTabOverlayMixin.java | 42 +++ 17 files changed, 605 insertions(+), 647 deletions(-) create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java delete mode 100644 src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartEntityRendererMixin.java create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java delete mode 100644 src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java delete mode 100644 src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java rename src/main/java/de/rettichlp/ucutils/mixin/{MinecartEntityMixin.java => MinecartMixin.java} (56%) delete mode 100644 src/main/java/de/rettichlp/ucutils/mixin/PlayerEntityRendererMixin.java delete mode 100644 src/main/java/de/rettichlp/ucutils/mixin/PlayerListHudMixin.java create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/PlayerTabOverlayMixin.java diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java new file mode 100644 index 00000000..04359741 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java @@ -0,0 +1,103 @@ +package de.rettichlp.ucutils.mixin; + +import com.mojang.authlib.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.gui.screens.inventory.MenuAccess; +import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.network.chat.Component; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.component.ItemLore; +import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.regex.Matcher; + +import static de.rettichlp.ucutils.UCUtils.LOGGER; +import static de.rettichlp.ucutils.UCUtils.commandService; +import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.player; +import static de.rettichlp.ucutils.UCUtils.storage; +import static java.lang.Integer.parseInt; +import static java.util.regex.Pattern.compile; +import static net.minecraft.client.gui.screens.inventory.BookEditScreen.BACKGROUND_TEXTURE_HEIGHT; +import static net.minecraft.client.gui.screens.inventory.BookEditScreen.BACKGROUND_TEXTURE_WIDTH; +import static net.minecraft.core.component.DataComponents.LORE; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.world.inventory.ContainerInput.PICKUP; + +@Mixin(AbstractContainerScreen.class) +public abstract class AbstractContainerScreenMixin extends Screen implements MenuAccess { + + protected AbstractContainerScreenMixin(Component title) { + super(title); + } + + @Inject(method = "extractRenderState", at = @At("TAIL")) + private void ucutils$extractRenderStateTail(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a, CallbackInfo ci) { + MultiPlayerGameMode gameMode = Minecraft.getInstance().gameMode; + + if (gameMode == null) { + return; + } + + String title = getTitle().getString(); + + switch (getTitle().getString()) { + case "ʟᴀɢᴇʀ" -> { + int ingredient1StoredAmount = getStoredAmount(this, 11); + int ingredient2StoredAmount = getStoredAmount(this, 13); + int ingredient3StoredAmount = getStoredAmount(this, 15); + + int x = (this.width - BACKGROUND_TEXTURE_WIDTH) / 2; + int y = (this.height - BACKGROUND_TEXTURE_HEIGHT) / 2; + int buttonX = x + BACKGROUND_TEXTURE_WIDTH + 2; + + // render button right to the inventory + Button button = new Button.Builder(literal("➤"), _ -> commandService.sendCommand("f " + ingredient1StoredAmount + "x Wirkstoff | " + ingredient2StoredAmount + "x Trägerstoff | " + ingredient3StoredAmount + "x Zusatzstoff")) + .bounds(buttonX, y, 20, 20) + .build(); + + if (ingredient1StoredAmount != 0 && ingredient2StoredAmount != 0 && ingredient3StoredAmount != 0) { + button.extractRenderState(graphics, mouseX, mouseY, a); + addRenderableWidget(button); + } + } + case "ᴄᴀʀᴄᴏɴᴛʀᴏʟ" -> { + if (configuration.getOptions().car().fastLock() && !storage.isPremium()) { + gameMode.handleContainerInput(getMenu().containerId, 0, 0, PICKUP, player); + } + } + default -> { + if (commandService.isSuperUser()) { + LOGGER.info("Screen opened: {}", title); + } + } + } + } + + @Unique + private int getStoredAmount(@NonNull MenuAccess containerScreen, int slotId) { + Slot slot = containerScreen.getMenu().getSlot(slotId); + ItemLore itemLore = slot.getItem().get(LORE); + + if (itemLore == null) { + return 0; + } + + String amountString = itemLore.lines().get(1).getString(); + Matcher matcher = compile("\\d+").matcher(amountString); + return matcher.find() ? parseInt(matcher.group()) : 0; + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartEntityRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartEntityRendererMixin.java deleted file mode 100644 index c68410d7..00000000 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartEntityRendererMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.rettichlp.ucutils.mixin; - -import net.minecraft.client.render.entity.AbstractMinecartEntityRenderer; -import net.minecraft.client.render.entity.state.MinecartEntityRenderState; -import net.minecraft.entity.vehicle.AbstractMinecartEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.storage; - -@Mixin(AbstractMinecartEntityRenderer.class) -public class AbstractMinecartEntityRendererMixin { - - @Inject(method = "updateRenderState(Lnet/minecraft/entity/vehicle/AbstractMinecartEntity;Lnet/minecraft/client/render/entity/state/MinecartEntityRenderState;F)V", - at = @At("TAIL")) - private void ucutils$updateRenderStateTail(T entity, S state, float tickDelta, CallbackInfo ci) { - if (!storage.isUnicaCity()) { - return; - } - - if (!configuration.getOptions().car().highlight()) { - return; - } - - if (storage.getMinecartEntityToHighlight() != null && storage.getMinecartEntityToHighlight().getUuid().equals(entity.getUuid())) { - state.outlineColor = 0xFFFFAA00; - } - } -} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java new file mode 100644 index 00000000..7a1f6719 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java @@ -0,0 +1,38 @@ +package de.rettichlp.ucutils.mixin; + +import net.minecraft.client.renderer.entity.AbstractMinecartRenderer; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.state.MinecartRenderState; +import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.storage; + +@Mixin(AbstractMinecartRenderer.class) +public abstract class AbstractMinecartRendererMixin extends EntityRenderer { + + protected AbstractMinecartRendererMixin(EntityRendererProvider.Context context) { + super(context); + } + + @Inject(method = "extractRenderState(Lnet/minecraft/world/entity/vehicle/minecart/AbstractMinecart;Lnet/minecraft/client/renderer/entity/state/MinecartRenderState;F)V", + at = @At("TAIL")) + private void ucutils$updateRenderStateTail(T entity, S state, float partialTicks, CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + if (!configuration.getOptions().car().highlight()) { + return; + } + + if (storage.getMinecartEntityToHighlight() != null && storage.getMinecartEntityToHighlight().getUUID().equals(entity.getUUID())) { + state.outlineColor = 0xFFFFAA00; + } + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java index 19da773f..3453c6af 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java @@ -1,7 +1,7 @@ package de.rettichlp.ucutils.mixin; import de.rettichlp.ucutils.common.models.ScreenshotType; -import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.gui.screens.ChatScreen; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -16,7 +16,7 @@ import static de.rettichlp.ucutils.common.models.ScreenshotType.OTHER; import static java.lang.Thread.sleep; import static java.util.Arrays.stream; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; @Mixin(ChatScreen.class) public abstract class ChatScreenMixin { diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java index ee81c8d5..6d291a3c 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -4,18 +4,16 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NonNull; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.Entity; -import net.minecraft.entity.passive.VillagerEntity; -import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; -import net.minecraft.network.packet.s2c.play.PlayerRemoveS2CPacket; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -31,92 +29,93 @@ import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static java.awt.Color.WHITE; -import static java.lang.System.currentTimeMillis; import static java.util.Objects.requireNonNull; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.text.Text.translatable; -import static net.minecraft.util.Formatting.BLUE; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.RED; -import static net.minecraft.util.Formatting.YELLOW; +import static net.minecraft.ChatFormatting.BLUE; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; -@Mixin(ClientPlayNetworkHandler.class) +@Mixin(ClientPacketListener.class) public abstract class ClientPlayNetworkHandlerMixin { @Unique - private static final MutableText A_DUTY_PREFIX = empty() - .append(literal("[").formatted(DARK_GRAY) - .append(literal("UC").formatted(BLUE)) - .append(literal("]").formatted(DARK_GRAY))); + private static final MutableComponent A_DUTY_PREFIX = empty() + .append(literal("[").withStyle(DARK_GRAY) + .append(literal("UC").withStyle(BLUE)) + .append(literal("]").withStyle(DARK_GRAY))); @Unique - private static final MutableText BUILD_MODE_PREFIX = empty() - .append(literal("[").formatted(DARK_GRAY) - .append(literal("B").formatted(YELLOW)) - .append(literal("]").formatted(DARK_GRAY))); + private static final MutableComponent BUILD_MODE_PREFIX = empty() + .append(literal("[").withStyle(DARK_GRAY) + .append(literal("B").withStyle(YELLOW)) + .append(literal("]").withStyle(DARK_GRAY))); @Unique - private static final MutableText REPORT_PREFIX = empty() - .append(literal("[").formatted(DARK_GRAY) - .append(literal("R").formatted(GOLD)) - .append(literal("]").formatted(DARK_GRAY))); + private static final MutableComponent REPORT_PREFIX = empty() + .append(literal("[").withStyle(DARK_GRAY) + .append(literal("R").withStyle(GOLD)) + .append(literal("]").withStyle(DARK_GRAY))); @Unique private final Collection enrichedGameProfiles = new HashSet<>(); - @Inject(method = "onEntityTrackerUpdate", at = @At("TAIL")) - private void onEntityTrackerUpdate(EntityTrackerUpdateS2CPacket packet, CallbackInfo ci) { + @Inject(method = "handlePlayerInfoUpdate", at = @At("TAIL")) + private void ucutils$handlePlayerInfoUpdateTail(ClientboundPlayerInfoUpdatePacket packet, CallbackInfo ci) { if (!storage.isUnicaCity()) { return; } - ClientWorld world = MinecraftClient.getInstance().world; + Level world = Minecraft.getInstance().level; if (world == null) { return; } - Entity entity = world.getEntityById(packet.id()); - if (!(entity instanceof VillagerEntity villager) || !villager.hasCustomName()) { - return; - } + packet.entries().forEach(entry -> { + Entity entity = world.getEntity(entry.profileId()); + if (!(entity instanceof Villager villager) || !villager.hasCustomName()) { + return; + } - String customNameString = requireNonNull(villager.getCustomName()).getString(); - Vec3d entityPos = villager.getEntityPos(); + String customNameString = requireNonNull(villager.getCustomName()).getString(); + Vec3 entityPos = villager.position(); - // already notified check - if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition())) { - return; - } - - switch (customNameString) { - case "Dealer" -> { - storage.setBlackMarketPosition(entityPos); - player.sendMessage(empty() - .append(literal("[").formatted(DARK_GRAY)) - .append(literal("Dealer").formatted(RED)) - .append(literal("] ").formatted(DARK_GRAY)) - .append(literal("Der Dealer ist in der Nähe!").formatted(GRAY)), false); + // already notified check + if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition())) { + return; } - case "Schwarzmarkt" -> { - storage.setDealerPosition(entityPos); - player.sendMessage(empty() - .append(literal("[").formatted(DARK_GRAY)) - .append(literal("Schwarzmarkt").formatted(RED)) - .append(literal("] ").formatted(DARK_GRAY)) - .append(literal("Der Schwarzmarkt ist in der Nähe!").formatted(GRAY)), false); + + switch (customNameString) { + case "Dealer" -> { + storage.setBlackMarketPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Dealer").withStyle(RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Dealer ist in der Nähe!").withStyle(GRAY))); + } + case "Schwarzmarkt" -> { + storage.setDealerPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Schwarzmarkt").withStyle(RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Schwarzmarkt ist in der Nähe!").withStyle(GRAY))); + } } - } + }); } - @Inject(method = "onPlayerRemove", + @Inject(method = "handlePlayerInfoRemove", at = @At(value = "INVOKE", - target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/network/PacketApplyBatcher;)V", + target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", shift = AFTER)) - private void ucutils$onPlayerRemoveHead(PlayerRemoveS2CPacket packet, CallbackInfo ci) { + private void ucutils$handlePlayerInfoRemoveInvoke(ClientboundPlayerInfoRemovePacket packet, CallbackInfo ci) { if (!storage.isUnicaCity()) { return; } @@ -133,106 +132,108 @@ private void onEntityTrackerUpdate(EntityTrackerUpdateS2CPacket packet, Callback } } - @Inject(method = "handlePlayerListAction", at = @At("HEAD")) - private void ucutils$handlePlayerListActionHead(PlayerListS2CPacket.Action action, - PlayerListS2CPacket.Entry receivedEntry, - PlayerListEntry currentEntry, - CallbackInfo ci) { - if (!storage.isUnicaCity()) { - return; - } - - GameProfile profile = receivedEntry.profile(); - UUID profileId = receivedEntry.profileId(); - Text currentDisplayName = receivedEntry.displayName(); - - if (currentDisplayName == null) { - return; - } - - switch (action) { - case ADD_PLAYER -> { - if (!configuration.getOptions().notification().joinQuit()) { - return; - } - - EnrichedGameProfile enrichedGameProfile = new EnrichedGameProfile(profile, currentDisplayName, currentDisplayName); - this.enrichedGameProfiles.removeIf(egp -> egp.getProfile().id().equals(profileId)); - this.enrichedGameProfiles.add(enrichedGameProfile); - - // if the client joined the server few moments ago, hide notifications due to initial sync of player list - if (currentTimeMillis() - storage.getJoinTimestamp() < 1000) { - return; - } - - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_join"); - } - case UPDATE_DISPLAY_NAME -> { - EnrichedGameProfile enrichedGameProfile = this.enrichedGameProfiles.stream() - .filter(egp -> egp.getProfile().id().equals(profileId)) - .findFirst() - .orElseGet(() -> { - EnrichedGameProfile egp = new EnrichedGameProfile(profile, currentDisplayName, currentDisplayName); - this.enrichedGameProfiles.add(egp); - return egp; - }); - - Text previousDisplayName = enrichedGameProfile.getPreviousDisplayName(); - - // handle report change - if (configuration.getOptions().notification().report()) { - if (!previousDisplayName.contains(REPORT_PREFIX) && currentDisplayName.contains(REPORT_PREFIX)) { - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_report"); - enrichedGameProfile.setPreviousDisplayName(currentDisplayName); - return; - } - - if (previousDisplayName.contains(REPORT_PREFIX) && !currentDisplayName.contains(REPORT_PREFIX)) { - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_report"); - enrichedGameProfile.setPreviousDisplayName(currentDisplayName); - return; - } - } - - // handle build mode change - if (configuration.getOptions().notification().buildMode()) { - if (!previousDisplayName.contains(BUILD_MODE_PREFIX) && currentDisplayName.contains(BUILD_MODE_PREFIX)) { - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_buildmode"); - enrichedGameProfile.setPreviousDisplayName(currentDisplayName); - return; - } - - if (previousDisplayName.contains(BUILD_MODE_PREFIX) && !currentDisplayName.contains(BUILD_MODE_PREFIX)) { - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_buildmode"); - enrichedGameProfile.setPreviousDisplayName(currentDisplayName); - return; - } - } - - // handle admin-duty change - if (configuration.getOptions().notification().aDuty()) { - if (!previousDisplayName.contains(A_DUTY_PREFIX) && currentDisplayName.contains(A_DUTY_PREFIX)) { - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_a_duty"); - } - - if (previousDisplayName.contains(A_DUTY_PREFIX) && !currentDisplayName.contains(A_DUTY_PREFIX)) { - sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_a_duty"); - } - } - - enrichedGameProfile.setPreviousDisplayName(currentDisplayName); - } - } - } +// @Inject(method = "", at = @At("HEAD")) +// private void ucutils$handlePlayerListActionHead(PlayerListS2CPacket.Action action, +// PlayerListS2CPacket.Entry receivedEntry, +// PlayerListEntry currentEntry, +// CallbackInfo ci) { +// if (!storage.isUnicaCity()) { +// return; +// } +// +// +// +// GameProfile profile = receivedEntry.profile(); +// UUID profileId = receivedEntry.profileId(); +// Component currentDisplayName = receivedEntry.displayName(); +// +// if (currentDisplayName == null) { +// return; +// } +// +// switch (action) { +// case ADD_PLAYER -> { +// if (!configuration.getOptions().notification().joinQuit()) { +// return; +// } +// +// EnrichedGameProfile enrichedGameProfile = new EnrichedGameProfile(profile, currentDisplayName, currentDisplayName); +// this.enrichedGameProfiles.removeIf(egp -> egp.getProfile().id().equals(profileId)); +// this.enrichedGameProfiles.add(enrichedGameProfile); +// +// // if the client joined the server few moments ago, hide notifications due to initial sync of player list +// if (currentTimeMillis() - storage.getJoinTimestamp() < 1000) { +// return; +// } +// +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_join"); +// } +// case UPDATE_DISPLAY_NAME -> { +// EnrichedGameProfile enrichedGameProfile = this.enrichedGameProfiles.stream() +// .filter(egp -> egp.getProfile().id().equals(profileId)) +// .findFirst() +// .orElseGet(() -> { +// EnrichedGameProfile egp = new EnrichedGameProfile(profile, currentDisplayName, currentDisplayName); +// this.enrichedGameProfiles.add(egp); +// return egp; +// }); +// +// Component previousDisplayName = enrichedGameProfile.getPreviousDisplayName(); +// +// // handle report change +// if (configuration.getOptions().notification().report()) { +// if (!previousDisplayName.contains(REPORT_PREFIX) && currentDisplayName.contains(REPORT_PREFIX)) { +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_report"); +// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); +// return; +// } +// +// if (previousDisplayName.contains(REPORT_PREFIX) && !currentDisplayName.contains(REPORT_PREFIX)) { +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_report"); +// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); +// return; +// } +// } +// +// // handle build mode change +// if (configuration.getOptions().notification().buildMode()) { +// if (!previousDisplayName.contains(BUILD_MODE_PREFIX) && currentDisplayName.contains(BUILD_MODE_PREFIX)) { +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_buildmode"); +// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); +// return; +// } +// +// if (previousDisplayName.contains(BUILD_MODE_PREFIX) && !currentDisplayName.contains(BUILD_MODE_PREFIX)) { +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_buildmode"); +// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); +// return; +// } +// } +// +// // handle admin-duty change +// if (configuration.getOptions().notification().aDuty()) { +// if (!previousDisplayName.contains(A_DUTY_PREFIX) && currentDisplayName.contains(A_DUTY_PREFIX)) { +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_a_duty"); +// } +// +// if (previousDisplayName.contains(A_DUTY_PREFIX) && !currentDisplayName.contains(A_DUTY_PREFIX)) { +// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_a_duty"); +// } +// } +// +// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); +// } +// } +// } @Unique private void sendChangeNotification(@NonNull EnrichedGameProfile enrichedGameProfile, String translationKey) { - Text currentDisplayName = enrichedGameProfile.getCurrentDisplayName(); + Component currentDisplayName = enrichedGameProfile.getCurrentDisplayName(); if (currentDisplayName.equals(empty())) { return; } - MutableText text = translatable(translationKey, currentDisplayName); + MutableComponent text = translatable(translationKey, currentDisplayName); notificationService.sendNotification(text, WHITE, 5000); } @@ -241,8 +242,8 @@ private void sendChangeNotification(@NonNull EnrichedGameProfile enrichedGamePro public static class EnrichedGameProfile { private final GameProfile profile; - private Text previousDisplayName; - private Text currentDisplayName; + private Component previousDisplayName; + private Component currentDisplayName; public boolean isTeamMember() { return storage.getTeam().ucTeam().stream().anyMatch(teamMember -> teamMember.uuid().equals(this.profile.id())); diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java index cb7891a2..3c928f33 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java @@ -1,7 +1,9 @@ package de.rettichlp.ucutils.mixin; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -13,24 +15,24 @@ import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; -import static net.minecraft.item.Items.GLASS_BOTTLE; +import static net.minecraft.world.item.Items.GLASS_BOTTLE; -@Mixin(ClientPlayerEntity.class) +@Mixin(Player.class) public abstract class ClientPlayerEntityMixin { @Unique - private final static List SHOP_LOCATIONS = List.of( - new BlockPos(45, 69, 200), - new BlockPos(1049, 69, -189) + private final static List SHOP_LOCATIONS = List.of( + new Vec3(45, 69, 200), + new Vec3(1049, 69, -189) ); - @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) - private void ucutils$dropSelectedItemHead(boolean entireStack, CallbackInfoReturnable cir) { + @Inject(method = "drop", at = @At("HEAD"), cancellable = true) + private void ucutils$dropHead(ItemStack itemStack, boolean thrownFromHand, CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; } - if (player.getMainHandStack().isOf(GLASS_BOTTLE) && isNearShop()) { + if (player.getMainHandItem().is(GLASS_BOTTLE) && isNearShop()) { // cancel drop cir.setReturnValue(null); @@ -41,8 +43,8 @@ public abstract class ClientPlayerEntityMixin { @Unique private boolean isNearShop() { - BlockPos playerPos = player.getBlockPos(); + Vec3 position = player.position(); return SHOP_LOCATIONS.stream() - .anyMatch(blockPos -> playerPos.isWithinDistance(blockPos, 10)); + .anyMatch(blockPos -> position.closerThan(blockPos, 10)); } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java index 9f508ead..b868a9ba 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java @@ -1,9 +1,9 @@ package de.rettichlp.ucutils.mixin; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.vehicle.MinecartEntity; -import net.minecraft.world.entity.UniquelyIdentifiable; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.minecart.Minecart; +import net.minecraft.world.level.entity.UniquelyIdentifyable; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -20,10 +20,10 @@ @Mixin(Entity.class) public abstract class EntityMixin { - @Inject(method = "startRiding(Lnet/minecraft/entity/Entity;ZZ)Z", at = @At("RETURN")) - private void ucutils$startRidingReturn(Entity vehicle, + @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;ZZ)Z", at = @At("RETURN")) + private void ucutils$startRidingReturn(Entity entityToRide, boolean force, - boolean emitEvent, + boolean sendEventAndTriggers, @NotNull CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; @@ -34,8 +34,8 @@ public abstract class EntityMixin { return; } - UniquelyIdentifiable self = (Entity) (Object) this; - if (self.getUuid().equals(player.getUuid()) && vehicle instanceof MinecartEntity) { + UniquelyIdentifyable self = (Entity) (Object) this; + if (self.getUUID().equals(player.getUUID()) && entityToRide instanceof Minecart) { storage.setMinecartEntityToHighlight(null); if (configuration.getOptions().car().automatedStart() && !storage.isPremium()) { @@ -57,8 +57,8 @@ public abstract class EntityMixin { } Entity self = (Entity) (Object) this; - if (self instanceof ClientPlayerEntity && self.hasVehicle() && self.getVehicle() instanceof MinecartEntity minecartEntity) { - storage.setMinecartEntityToHighlight(minecartEntity); + if (self instanceof Player && self.isPassenger() && self.getVehicle() instanceof Minecart minecart) { + storage.setMinecartEntityToHighlight(minecart); } } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java new file mode 100644 index 00000000..ea7d5bea --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java @@ -0,0 +1,59 @@ +package de.rettichlp.ucutils.mixin; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.client.renderer.state.level.CameraRenderState; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.nameTagService; +import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.services.NameTagService.AFK_TAG; + +@Mixin(EntityRenderer.class) +public abstract class EntityRendererMixin { + + @Inject(method = "submitNameDisplay(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;I)V", + at = @At(value = "INVOKE", + target = "Lcom/mojang/blaze3d/vertex/PoseStack;popPose()V")) + private void ucutils$submitNameDisplayInvoke(S state, + PoseStack poseStack, + SubmitNodeCollector submitNodeCollector, + CameraRenderState camera, + int offset, + CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + // extract player name + // empty[style={color=red,clickEvent=class_10610[command=/tell Maagma46 ],hoverEvent=class_10611[entity=net.minecraft.class_2568$class_5248@a9702189],insertion=Maagma46}, siblings=[literal{[}[style={color=dark_gray}, siblings=[literal{UC}[style={color=blue}], literal{]}[style={color=dark_gray}]]], literal{Maagma46}, empty]] + Component displayName = state.nameTag; + if (displayName == null) { + return; + } + + String playerName = displayName.getStyle().getInsertion(); + + // handle medical information (bandages + pills) + MutableComponent medicInformation = nameTagService.getMedicInformation(playerName); + boolean medicInformationPresent = !medicInformation.getSiblings().isEmpty(); + if (configuration.getOptions().nameTag().medicalInformation() && medicInformationPresent) { + submitNodeCollector.submitNameTag(poseStack, state.nameTagAttachment, offset, medicInformation, !state.isDiscrete, state.lightCoords, state.distanceToCameraSq, camera); + } + + // handle afk tag + if (configuration.getOptions().nameTag().afk() && nameTagService.isAfk(playerName)) { + submitNodeCollector.submitNameTag(poseStack, state.nameTagAttachment, offset, AFK_TAG, !state.isDiscrete, state.lightCoords, state.distanceToCameraSq, camera); + return; + } + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java index 4981304f..9017f4a7 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java @@ -2,40 +2,39 @@ import com.llamalad7.mixinextras.sugar.Local; import de.rettichlp.ucutils.common.gui.screens.options.MainOptionsScreen; -import net.minecraft.client.gui.screen.GameMenuScreen; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.GridWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.screens.PauseScreen; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static net.minecraft.text.Text.of; +import static net.minecraft.network.chat.Component.literal; -@Mixin(GameMenuScreen.class) +@Mixin(PauseScreen.class) public abstract class GameMenuScreenMixin extends Screen { - protected GameMenuScreenMixin(Text title) { + protected GameMenuScreenMixin(Component title) { super(title); } - @Inject( - method = "initWidgets", + @Inject(method = "createPauseMenu", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/gui/widget/GridWidget$Adder;add(Lnet/minecraft/client/gui/widget/Widget;ILnet/minecraft/client/gui/widget/Positioner;)Lnet/minecraft/client/gui/widget/Widget;", + target = "Lnet/minecraft/client/gui/layouts/GridLayout$RowHelper;addChild(Lnet/minecraft/client/gui/layouts/LayoutElement;ILnet/minecraft/client/gui/layouts/LayoutSettings;)Lnet/minecraft/client/gui/layouts/LayoutElement;", ordinal = 0)) private void ucutils$initWidgetsInvoke(CallbackInfo ci, - @Local @NotNull GridWidget gridWidget, - @Local GridWidget.@NotNull Adder adder) { - ButtonWidget buttonWidget = ButtonWidget.builder(of("UCUtils Settings"), button -> this.client.setScreen(new MainOptionsScreen())) + @Local(name = "gridLayout") GridLayout gridLayout, + @Local(name = "helper") GridLayout.@NotNull RowHelper helper) { + Button buttonWidget = Button.builder(literal("UCUtils Settings"), button -> this.minecraft.setScreen(new MainOptionsScreen())) .width(204) .build(); // the first item of the adder has a top margin of 50, so we add a negative top margin to compensate (46 for a small gap of 4) - adder.add(buttonWidget, 2, gridWidget.copyPositioner().marginTop(50).marginBottom(-46)); + helper.addChild(buttonWidget, 2, gridLayout.newCellSettings().paddingTop(50).paddingBottom(-46)); } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java new file mode 100644 index 00000000..2d9f625b --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java @@ -0,0 +1,134 @@ +package de.rettichlp.ucutils.mixin; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.platform.NativeImage; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.renderer.texture.AbstractTexture; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.resources.Identifier; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.world.entity.LivingEntity; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.io.InputStream; +import java.nio.file.Path; + +import static com.mojang.blaze3d.platform.NativeImage.read; +import static de.rettichlp.ucutils.UCUtils.LOGGER; +import static de.rettichlp.ucutils.UCUtils.MOD_ID; +import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.player; +import static de.rettichlp.ucutils.UCUtils.storage; +import static java.lang.Math.ceil; +import static java.lang.Math.clamp; +import static java.lang.Math.round; +import static java.nio.file.Files.newInputStream; +import static net.minecraft.client.renderer.RenderPipelines.GUI_TEXTURED; +import static net.minecraft.resources.Identifier.fromNamespaceAndPath; +import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; + +@Mixin(Gui.class) +public abstract class GuiMixin { + + @Unique + private static final Identifier HYDRATION_EMPTY_TEXTURE = fromNamespaceAndPath(MOD_ID, "textures/hud/hydration_empty.png"); + + @Unique + private static final Identifier HYDRATION_HALF_TEXTURE = fromNamespaceAndPath(MOD_ID, "textures/hud/hydration_half.png"); + + @Unique + private static final Identifier HYDRATION_FULL_TEXTURE = fromNamespaceAndPath(MOD_ID, "textures/hud/hydration_full.png"); + + @Unique + private static final Identifier CAPTCHA_IDENTIFIER = fromNamespaceAndPath("ucutils", "captcha"); + + @Shadow + @Final + private Minecraft minecraft; + + @Inject(method = "extractChat", at = @At("TAIL")) + private void ucutils$extractChatTail(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) { + if (storage.getCaptchaMap() == null) { + return; + } + + NativeImage nativeImage; + try (InputStream is = newInputStream(Path.of("screenshots/ucutils/captcha.png"))) { + nativeImage = read(is); + } catch (Exception e) { + LOGGER.error("Failed to read captcha image", e); + return; + } + + AbstractTexture texture = new DynamicTexture(() -> "captcha", nativeImage); + this.minecraft.getTextureManager().register(CAPTCHA_IDENTIFIER, texture); + + int side = graphics.guiWidth() / 4; + int x = graphics.guiWidth() / 2 - side / 2; + int y = graphics.guiHeight() / 4 - side / 2; + + graphics.blit(GUI_TEXTURED, CAPTCHA_IDENTIFIER, x, y, 0, 0, side, side, side, side); + } + + @Inject(method = "extractPlayerHealth", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/Gui;extractHearts(Lnet/minecraft/client/gui/GuiGraphicsExtractor;Lnet/minecraft/world/entity/player/Player;IIIIFIIIZ)V", + shift = AFTER)) + private void ucutils$renderStatusBarsInvoke(GuiGraphicsExtractor graphics, + CallbackInfo ci, + @Local(name = "xRight") int xRight, + @Local(name = "yLineAir") int yLineAir) { + if (!storage.isUnicaCity()) { + return; + } + + if (!configuration.getOptions().showHydration() || storage.getHydration() < 0) { + return; + } + + Profiler.get().popPush("hydration"); + renderHydration(graphics, yLineAir, xRight); + Profiler.get().pop(); + } + + @Unique + private void renderHydration(GuiGraphicsExtractor context, int yLineAir, int xRight) { + double maxHydrated = 20; + long round = round(storage.getHydration()); + int hydration = (int) clamp(round, 0, maxHydrated); + + if (player.isUnderWater() || player.getAirSupply() < player.getMaxAirSupply()) { + yLineAir -= 10; + } + + if (player.getVehicle() instanceof LivingEntity livingEntity) { + int hearthRows = (int) ceil(livingEntity.getHealth() / 20.0); + yLineAir -= hearthRows * 10; + } + + for (int n = 0; n < 10; n++) { + int o = xRight - 9 - n * 8; + + // always render empty hydration + context.blit(GUI_TEXTURED, HYDRATION_EMPTY_TEXTURE, o, yLineAir, 0, 0, 9, 9, 9, 9); + + // render texture depending on hydration + int hydrationLeft = hydration - (n * 2); + if (hydrationLeft >= 2.0) { + context.blit(GUI_TEXTURED, HYDRATION_FULL_TEXTURE, o, yLineAir, 0, 0, 9, 9, 9, 9); + } else if (hydrationLeft >= 1.0) { + context.blit(GUI_TEXTURED, HYDRATION_HALF_TEXTURE, o, yLineAir, 0, 0, 9, 9, 9, 9); + } + } + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java deleted file mode 100644 index 8bb8606b..00000000 --- a/src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.rettichlp.ucutils.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.component.type.LoreComponent; -import net.minecraft.screen.GenericContainerScreenHandler; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.slot.Slot; -import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.regex.Matcher; - -import static de.rettichlp.ucutils.UCUtils.LOGGER; -import static de.rettichlp.ucutils.UCUtils.commandService; -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.player; -import static de.rettichlp.ucutils.UCUtils.storage; -import static java.lang.Integer.parseInt; -import static java.util.regex.Pattern.compile; -import static net.minecraft.component.DataComponentTypes.LORE; -import static net.minecraft.screen.slot.SlotActionType.PICKUP; -import static net.minecraft.text.Text.literal; - -@Mixin(HandledScreen.class) -public abstract class HandledScreenMixin extends Screen { - - @Shadow - protected int backgroundWidth; - - @Shadow - protected int backgroundHeight; - - protected HandledScreenMixin(Text title) { - super(title); - } - - @Inject(method = "render", at = @At("TAIL")) - private void ucutils$renderTail(DrawContext context, int mouseX, int mouseY, float deltaTicks, CallbackInfo ci) { - HandledScreen self = (HandledScreen) (Object) this; - ScreenHandler screenHandler = self.getScreenHandler(); - ClientPlayerInteractionManager interactionManager = MinecraftClient.getInstance().interactionManager; - - if (interactionManager == null) { - return; - } - - String title = self.getTitle().getString(); - - switch (screenHandler) { - case GenericContainerScreenHandler genericContainerScreenHandler -> { - switch (title) { - case "ʟᴀɢᴇʀ" -> { - int ingredient1StoredAmount = getStoredAmount(genericContainerScreenHandler, 11); - int ingredient2StoredAmount = getStoredAmount(genericContainerScreenHandler, 13); - int ingredient3StoredAmount = getStoredAmount(genericContainerScreenHandler, 15); - - int x = (this.width - this.backgroundWidth) / 2; - int y = (this.height - this.backgroundHeight) / 2; - int buttonX = x + this.backgroundWidth + 2; - - // render button right to the inventory - ButtonWidget buttonWidget = new ButtonWidget.Builder(literal("➤"), button -> commandService.sendCommand("f " + ingredient1StoredAmount + "x Wirkstoff | " + ingredient2StoredAmount + "x Trägerstoff | " + ingredient3StoredAmount + "x Zusatzstoff")) - .dimensions(buttonX, y, 20, 20) - .build(); - - if (ingredient1StoredAmount != 0 && ingredient2StoredAmount != 0 && ingredient3StoredAmount != 0) { - buttonWidget.render(context, mouseX, mouseY, deltaTicks); - addDrawableChild(buttonWidget); - } - } - case "ᴄᴀʀᴄᴏɴᴛʀᴏʟ" -> { - if (configuration.getOptions().car().fastLock() && !storage.isPremium()) { - interactionManager.clickSlot(genericContainerScreenHandler.syncId, 0, 0, PICKUP, player); - } - } - default -> { - if (commandService.isSuperUser()) { - LOGGER.info("Screen opened: {}", title); - } - } - } - } - case null, default -> { - } - } - } - - @Unique - private int getStoredAmount(@NotNull ScreenHandler screenHandler, int slotId) { - Slot slot = screenHandler.slots.get(slotId); - LoreComponent loreComponent = slot.getStack().get(LORE); - - if (loreComponent == null) { - return 0; - } - - String amountString = loreComponent.lines().get(1).getString(); - Matcher matcher = compile("\\d+").matcher(amountString); - return matcher.find() ? parseInt(matcher.group()) : 0; - } -} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java deleted file mode 100644 index 5a62d371..00000000 --- a/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java +++ /dev/null @@ -1,177 +0,0 @@ -package de.rettichlp.ucutils.mixin; - -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.render.RenderTickCounter; -import net.minecraft.client.texture.NativeImage; -import net.minecraft.client.texture.NativeImageBackedTexture; -import net.minecraft.entity.LivingEntity; -import net.minecraft.util.Identifier; -import net.minecraft.util.profiler.Profilers; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.io.InputStream; -import java.nio.file.Path; - -import static de.rettichlp.ucutils.UCUtils.LOGGER; -import static de.rettichlp.ucutils.UCUtils.MOD_ID; -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.nameTagService; -import static de.rettichlp.ucutils.UCUtils.player; -import static de.rettichlp.ucutils.UCUtils.storage; -import static java.awt.Color.RED; -import static java.awt.Color.WHITE; -import static java.lang.Math.ceil; -import static java.lang.Math.clamp; -import static java.lang.Math.round; -import static java.lang.System.currentTimeMillis; -import static java.nio.file.Files.newInputStream; -import static net.minecraft.client.gl.RenderPipelines.GUI_TEXTURED; -import static net.minecraft.client.texture.NativeImage.read; -import static net.minecraft.item.Items.GOLDEN_HOE; -import static net.minecraft.registry.tag.FluidTags.WATER; -import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; - -@Mixin(InGameHud.class) -public abstract class InGameHudMixin { - - @Unique - private static final Identifier HYDRATION_EMPTY_TEXTURE = Identifier.of(MOD_ID, "textures/hud/hydration_empty.png"); - - @Unique - private static final Identifier HYDRATION_HALF_TEXTURE = Identifier.of(MOD_ID, "textures/hud/hydration_half.png"); - - @Unique - private static final Identifier HYDRATION_FULL_TEXTURE = Identifier.of(MOD_ID, "textures/hud/hydration_full.png"); - - @Unique - private static final Identifier CAPTCHA_IDENTIFIER = Identifier.of("ucutils", "captcha"); - - @Shadow - @Final - private MinecraftClient client; - - @Shadow - public abstract TextRenderer getTextRenderer(); - - @Inject(method = "renderChat", at = @At("TAIL")) - private void ucutils$renderChatTail(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { - if (storage.getCaptchaMap() == null) { - return; - } - - NativeImage nativeImage; - try (InputStream is = newInputStream(Path.of("screenshots/ucutils/captcha.png"))) { - nativeImage = read(is); - } catch (Exception e) { - LOGGER.error("Failed to read captcha image", e); - return; - } - - NativeImageBackedTexture nativeImageBackedTexture = new NativeImageBackedTexture(() -> "captcha", nativeImage); - this.client.getTextureManager().registerTexture(CAPTCHA_IDENTIFIER, nativeImageBackedTexture); - - int side = context.getScaledWindowWidth() / 4; - int x = context.getScaledWindowWidth() / 2 - side / 2; - int y = context.getScaledWindowHeight() / 4 - side / 2; - - context.drawTexture(GUI_TEXTURED, CAPTCHA_IDENTIFIER, x, y, 0, 0, side, side, side, side); - } - - @Inject(method = "renderCrosshair", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/util/Identifier;IIII)V", - ordinal = 0, - shift = AFTER)) - private void ucutils$renderCrosshairInvoke(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { - if (!storage.isUnicaCity()) { - return; - } - - if (!nameTagService.isADuty(player.getStringifiedName())) { - return; - } - - if (!player.getMainHandStack().isOf(GOLDEN_HOE)) { - return; - } - - Profilers.get().swap("aduty_warning"); - String text = "ᴀᴅᴜᴛʏ"; - - int width = getTextRenderer().getWidth(text); - int x = context.getScaledWindowWidth() / 2 - width / 2; - int y = context.getScaledWindowHeight() / 2 - 20; - - context.drawText(getTextRenderer(), text, x + 1, y, -16777216, false); - context.drawText(getTextRenderer(), text, x - 1, y, -16777216, false); - context.drawText(getTextRenderer(), text, x, y + 1, -16777216, false); - context.drawText(getTextRenderer(), text, x, y - 1, -16777216, false); - context.drawText(getTextRenderer(), text, x, y, (currentTimeMillis() / 500 % 2 == 0 ? RED : WHITE).getRGB(), false); - - Profilers.get().pop(); - } - - @Inject(method = "renderStatusBars", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHealthBar(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/entity/player/PlayerEntity;IIIIFIIIZ)V", - shift = AFTER)) - private void ucutils$renderStatusBarsInvoke(DrawContext context, - CallbackInfo ci, - @Local(ordinal = 3) int m, - @Local(ordinal = 8) int r) { - if (!storage.isUnicaCity()) { - return; - } - - if (!configuration.getOptions().showHydration() || storage.getHydration() < 0) { - return; - } - - Profilers.get().swap("hydration"); - renderHydration(context, r, m); - Profilers.get().pop(); - } - - @Unique - private void renderHydration(DrawContext context, int top, int left) { - double maxHydrated = 20; - long round = round(storage.getHydration()); - int hydration = (int) clamp(round, 0, maxHydrated); - - if (player.isSubmergedIn(WATER) || player.getAir() < player.getMaxAir()) { - top -= 10; - } - - if (player.getVehicle() instanceof LivingEntity livingEntity) { - int hearthRows = (int) ceil(livingEntity.getHealth() / 20.0); - top -= hearthRows * 10; - } - - for (int n = 0; n < 10; n++) { - int o = left - 9 - n * 8; - - // always render empty hydration - context.drawTexture(GUI_TEXTURED, HYDRATION_EMPTY_TEXTURE, o, top, 0, 0, 9, 9, 9, 9); - - // render texture depending on hydration - int hydrationLeft = hydration - (n * 2); - if (hydrationLeft >= 2.0) { - context.drawTexture(GUI_TEXTURED, HYDRATION_FULL_TEXTURE, o, top, 0, 0, 9, 9, 9, 9); - } else if (hydrationLeft >= 1.0) { - context.drawTexture(GUI_TEXTURED, HYDRATION_HALF_TEXTURE, o, top, 0, 0, 9, 9, 9, 9); - } - } - } -} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ItemStackMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ItemStackMixin.java index 2954846c..c0362225 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ItemStackMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ItemStackMixin.java @@ -1,8 +1,10 @@ package de.rettichlp.ucutils.mixin; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; +import net.minecraft.core.TypedInstance; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -10,19 +12,19 @@ import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.storage; -import static net.minecraft.item.Items.POTION; +import static net.minecraft.world.item.Items.POTION; @Mixin(ItemStack.class) public abstract class ItemStackMixin { - @Inject(method = "finishUsing", at = @At("HEAD")) - private void ucutils$finishUsingHead(World world, LivingEntity user, CallbackInfoReturnable cir) { + @Inject(method = "finishUsingItem", at = @At("HEAD")) + private void ucutils$finishUsingItemHead(Level level, LivingEntity livingEntity, CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; } - ItemStack itemStack = (ItemStack) (Object) this; - if (itemStack.isOf(POTION)) { + TypedInstance itemStack = (ItemStack) (Object) this; + if (itemStack.is(POTION)) { commandService.sendCommandWithHiddenOutput("health"); } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/MinecartEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/MinecartMixin.java similarity index 56% rename from src/main/java/de/rettichlp/ucutils/mixin/MinecartEntityMixin.java rename to src/main/java/de/rettichlp/ucutils/mixin/MinecartMixin.java index 47a43c29..9a1aed17 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/MinecartEntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/MinecartMixin.java @@ -1,10 +1,11 @@ package de.rettichlp.ucutils.mixin; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.vehicle.MinecartEntity; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.minecart.Minecart; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -15,22 +16,25 @@ import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.storage; import static java.lang.System.currentTimeMillis; -import static net.minecraft.util.ActionResult.CONSUME; +import static net.minecraft.world.InteractionResult.CONSUME; -@Mixin(MinecartEntity.class) -public abstract class MinecartEntityMixin { +@Mixin(Minecart.class) +public abstract class MinecartMixin { @Unique private long lastClick = 0; @Inject(method = "interact", at = @At("HEAD"), cancellable = true) - private void ucutils$interactHead(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + private void ucutils$interactHead(Player player, + InteractionHand hand, + Vec3 location, + CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; } Entity entity = (Entity) (Object) this; - if (configuration.getOptions().car().automatedCheckKfz() && entity instanceof MinecartEntity && player.isSneaking() && currentTimeMillis() - this.lastClick > 1000) { + if (configuration.getOptions().car().automatedCheckKfz() && entity instanceof Minecart && player.isCrouching() && currentTimeMillis() - this.lastClick > 1000) { commandService.sendCommand("checkkfz"); this.lastClick = currentTimeMillis(); cir.setReturnValue(CONSUME); diff --git a/src/main/java/de/rettichlp/ucutils/mixin/PlayerEntityRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/PlayerEntityRendererMixin.java deleted file mode 100644 index 0359660b..00000000 --- a/src/main/java/de/rettichlp/ucutils/mixin/PlayerEntityRendererMixin.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.rettichlp.ucutils.mixin; - -import lombok.NonNull; -import net.minecraft.client.render.command.OrderedRenderCommandQueue; -import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.render.state.CameraRenderState; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.nameTagService; -import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.common.services.NameTagService.AFK_TAG; - -@Mixin(PlayerEntityRenderer.class) -public abstract class PlayerEntityRendererMixin { - - @Inject(method = "renderLabelIfPresent(Lnet/minecraft/client/render/entity/state/PlayerEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/command/OrderedRenderCommandQueue;Lnet/minecraft/client/render/state/CameraRenderState;)V", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V")) - private void ucutils$renderLabelIfPresent(@NonNull PlayerEntityRenderState playerEntityRenderState, - @NonNull MatrixStack matrixStack, - @NonNull OrderedRenderCommandQueue orderedRenderCommandQueue, - CameraRenderState cameraRenderState, - CallbackInfo ci) { - if (!storage.isUnicaCity()) { - return; - } - - // extract player name - // empty[style={color=red,clickEvent=class_10610[command=/tell Maagma46 ],hoverEvent=class_10611[entity=net.minecraft.class_2568$class_5248@a9702189],insertion=Maagma46}, siblings=[literal{[}[style={color=dark_gray}, siblings=[literal{UC}[style={color=blue}], literal{]}[style={color=dark_gray}]]], literal{Maagma46}, empty]] - Text displayName = playerEntityRenderState.displayName; - if (displayName == null) { - return; - } - - String playerName = displayName.getStyle().getInsertion(); - - matrixStack.scale(0.5F, 0.5F, 0.5F); - - // handle medical information (bandages + pills) - MutableText medicInformation = nameTagService.getMedicInformation(playerName); - boolean medicInformationPresent = !medicInformation.getSiblings().isEmpty(); - if (configuration.getOptions().nameTag().medicalInformation() && medicInformationPresent) { - matrixStack.translate(0.0F, 1.8F, 0.0F); - orderedRenderCommandQueue.submitLabel(matrixStack, playerEntityRenderState.nameLabelPos, 0, medicInformation, !playerEntityRenderState.sneaking, playerEntityRenderState.light, playerEntityRenderState.squaredDistanceToCamera, cameraRenderState); - } - - // handle afk tag - if (configuration.getOptions().nameTag().afk() && nameTagService.isAfk(playerName)) { - matrixStack.translate(0.0F, medicInformationPresent ? 0.8F : 2.6, 0.0F); - orderedRenderCommandQueue.submitLabel(matrixStack, playerEntityRenderState.nameLabelPos, 0, AFK_TAG, !playerEntityRenderState.sneaking, playerEntityRenderState.light, playerEntityRenderState.squaredDistanceToCamera, cameraRenderState); - return; - } - } -} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/PlayerListHudMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/PlayerListHudMixin.java deleted file mode 100644 index 1c972763..00000000 --- a/src/main/java/de/rettichlp/ucutils/mixin/PlayerListHudMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package de.rettichlp.ucutils.mixin; - -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import static de.rettichlp.ucutils.UCUtils.storage; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.RED; - -@Mixin(PlayerListHud.class) -public abstract class PlayerListHudMixin { - - @Inject(method = "getPlayerName", at = @At("RETURN"), cancellable = true) - private void ucutils$getPlayerNameReturn(PlayerListEntry playerListEntry, @NotNull CallbackInfoReturnable cir) { - if (!storage.isUnicaCity()) { - return; - } - - String playerName = playerListEntry.getProfile().name(); - Text originText = cir.getReturnValue(); - - MutableText text = null; - - boolean isWanted = storage.getWantedEntries().stream() - .anyMatch(wantedEntry -> wantedEntry.getPlayerName().equals(playerName)); - - if (isWanted) { - text = literal(" 🔍").formatted(RED, BOLD); - } - - if (text != null) { - cir.setReturnValue(originText.copy().append(" ").append(text)); - } - } -} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/PlayerTabOverlayMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/PlayerTabOverlayMixin.java new file mode 100644 index 00000000..56b3191f --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/PlayerTabOverlayMixin.java @@ -0,0 +1,42 @@ +package de.rettichlp.ucutils.mixin; + +import net.minecraft.client.gui.components.PlayerTabOverlay; +import net.minecraft.client.multiplayer.PlayerInfo; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import static de.rettichlp.ucutils.UCUtils.storage; +import static net.minecraft.ChatFormatting.BOLD; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.literal; + +@Mixin(PlayerTabOverlay.class) +public abstract class PlayerTabOverlayMixin { + + @Inject(method = "getNameForDisplay", at = @At("RETURN"), cancellable = true) + private void ucutils$getNameForDisplayReturn(PlayerInfo info, CallbackInfoReturnable cir) { + if (!storage.isUnicaCity()) { + return; + } + + String playerName = info.getProfile().name(); + Component originText = cir.getReturnValue(); + + MutableComponent text = null; + + boolean isWanted = storage.getWantedEntries().stream() + .anyMatch(wantedEntry -> wantedEntry.getPlayerName().equals(playerName)); + + if (isWanted) { + text = literal(" 🔍").withStyle(RED, BOLD); + } + + if (text != null) { + cir.setReturnValue(originText.copy().append(" ").append(text)); + } + } +} From 5cbffe9fa1b3ebcea55416fecbd3a1eba7da45a7 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 22:31:29 +0200 Subject: [PATCH 08/64] Add Mod Menu integration and update build scripts for Mod Menu dependency configuration --- build.gradle.kts | 8 ++++++++ gradle.properties | 3 +++ .../ucutils/integrations/ModMenuIntegration.java | 13 +++++++++++++ src/main/resources/fabric.mod.json | 15 +++++++++------ 4 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/main/java/de/rettichlp/ucutils/integrations/ModMenuIntegration.java diff --git a/build.gradle.kts b/build.gradle.kts index ea342e78..51fb3605 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,6 +12,11 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + + maven { + name = "Terraformers" + url = uri("https://maven.terraformersmc.com/") + } } dependencies { @@ -27,6 +32,9 @@ dependencies { compileOnly("org.projectlombok:lombok:1.18.46") annotationProcessor("org.projectlombok:lombok:1.18.46") + // https://github.com/TerraformersMC/ModMenu + compileOnly("com.terraformersmc:modmenu:${providers.gradleProperty("modmenu_version").get()}") + // https://github.com/atteo/classindex implementation("org.atteo.classindex:classindex:3.13") annotationProcessor("org.atteo.classindex:classindex:3.13") diff --git a/gradle.properties b/gradle.properties index a57de59b..ddec5b40 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,3 +17,6 @@ maven_group=de.rettichlp # Dependencies fabric_api_version=0.151.0+26.1.2 + +# External mods +modmenu_version=18.0.0-beta.1 diff --git a/src/main/java/de/rettichlp/ucutils/integrations/ModMenuIntegration.java b/src/main/java/de/rettichlp/ucutils/integrations/ModMenuIntegration.java new file mode 100644 index 00000000..1f741ba6 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/integrations/ModMenuIntegration.java @@ -0,0 +1,13 @@ +package de.rettichlp.ucutils.integrations; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import de.rettichlp.ucutils.common.gui.screens.options.MainOptionsScreen; + +public class ModMenuIntegration implements ModMenuApi { + + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return _ -> new MainOptionsScreen(); + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 22a2a728..34783bd1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -5,7 +5,7 @@ "name": "UCUtils", "description": "Essential utilities and QoL tools for the UnicaCity roleplay server.", "authors": [ - "rettichlp" + "RettichLP" ], "contributors": [ "Fauliikou", @@ -24,18 +24,21 @@ "entrypoints": { "main": [ "de.rettichlp.ucutils.UCUtils" + ], + "modmenu": [ + "de.rettichlp.ucutils.integrations.ModMenuIntegration" ] }, "mixins": [ "ucutils.mixins.json" ], "depends": { - "fabricloader": ">=0.17.0", - "minecraft": "~1.21.3", - "java": ">=21", + "fabricloader": ">=0.19.3", + "minecraft": "~26.1.2", + "java": ">=25", "fabric-api": "*" }, - "suggests": { - "another-mod": "*" + "recommends": { + "modmenu": ">=18.0.0" } } From eb8aee13a072e2b009acdb6d558d222222f7628c Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 22:32:25 +0200 Subject: [PATCH 09/64] Align codebase to Minecraft 26.1.2 API changes and update affected components to use new messaging and formatting APIs --- .../de/rettichlp/ucutils/common/Storage.java | 5 +- .../common/gui/screens/OptionsScreen.java | 2 +- .../common/gui/screens/ShutdownScreen.java | 2 +- .../common/services/CommandService.java | 8 +- .../common/services/NameTagService.java | 2 +- .../ucutils/listener/impl/HouseListener.java | 71 ++-- .../ucutils/listener/impl/MobileListener.java | 4 +- .../ucutils/listener/impl/PlayerListener.java | 31 +- .../ucutils/listener/impl/PrayListener.java | 4 +- .../ucutils/listener/impl/RenderListener.java | 22 +- .../listener/impl/SoundTriggerListener.java | 4 +- .../impl/faction/BadFactionListener.java | 11 +- .../listener/impl/faction/MedicListener.java | 106 +++--- .../listener/impl/faction/WantedListener.java | 302 +++++++++--------- .../impl/job/DeepSeaFisherListener.java | 10 +- .../listener/impl/job/GarbageManListener.java | 56 ++-- .../listener/impl/job/JobListener.java | 10 +- .../ucutils/mixin/ChatScreenMixin.java | 8 +- src/main/resources/ucutils.mixins.json | 12 +- 19 files changed, 333 insertions(+), 337 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index 6d36d8c9..606e0bfe 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -15,6 +15,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.entity.vehicle.minecart.Minecart; import net.minecraft.world.level.saveddata.maps.MapId; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import java.time.LocalDateTime; @@ -61,7 +62,7 @@ public class Storage { @Getter @Setter @Nullable - private Vec3i blackMarketPosition; + private Vec3 blackMarketPosition; @Getter @Setter @@ -84,7 +85,7 @@ public class Storage { @Getter @Setter @Nullable - private Vec3i dealerPosition; + private Vec3 dealerPosition; @Getter @Setter diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java index 9c5943f0..f9e61c2d 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java @@ -50,7 +50,7 @@ public void doOnClose() { protected void initFooter() { LinearLayout directionalLayoutWidget = this.layout.addToFooter(horizontal().spacing(8)); directionalLayoutWidget.addChild(Button.builder(GUI_BACK, _ -> back()).width(120).build()); - directionalLayoutWidget.addChild(Button.builder(GUI_DONE, _ -> close()).width(200).build()); + directionalLayoutWidget.addChild(Button.builder(GUI_DONE, _ -> onClose()).width(200).build()); directionalLayoutWidget.addChild(Button.builder(literal("Discord").copy().withColor(DISCORD_COLOR), confirmLink(this, DISCORD_INVITE)).width(56).build()); directionalLayoutWidget.addChild(Button.builder(literal("Modrinth").copy().withColor(MODRINTH_COLOR), confirmLink(this, MODRINTH)).width(56).build()); } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java index d40925a8..f0f23f46 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java @@ -44,7 +44,7 @@ public void initBody() { directionalLayoutWidget.addChild(new StringWidget(empty() .append(literal("wird das automatische Herunterfahren gestoppt.").withStyle(GRAY)), this.font), positioner -> positioner.paddingBottom(16)); - directionalLayoutWidget.addChild(Button.builder(BUTTON_SHUTDOWN_ABORT_NAME, button -> close()).width(150).build()); + directionalLayoutWidget.addChild(Button.builder(BUTTON_SHUTDOWN_ABORT_NAME, button -> onClose()).width(150).build()); directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/CommandService.java b/src/main/java/de/rettichlp/ucutils/common/services/CommandService.java index a6a00ca4..7554f09b 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/CommandService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/CommandService.java @@ -33,16 +33,16 @@ public class CommandService { public void sendCommand(String command) { LOGGER.info("UCUtils executing command: {}", command); - networkHandler.sendChatCommand(command); + networkHandler.sendCommand(command); } public void sendCommandWithAfkCheck(String command) { - boolean isAfk = nameTagService.isAfk(player.getStringifiedName()); + boolean isAfk = nameTagService.isAfk(player.getPlainTextName()); boolean isDead = storage.isDead(); LOGGER.info("UCUtils executing command with AFK check (is AFK: {}, is dead: {}): {}", isAfk, isDead, command); if (!isAfk && !isDead) { - networkHandler.sendChatCommand(command); + networkHandler.sendCommand(command); } } @@ -84,6 +84,6 @@ public boolean showCommandOutputMessage(String command) { } public boolean isSuperUser() { - return nonNull(player) && (UUID_RETTICHLP.equals(player.getUuidAsString()) || getBoolean("fabric.development")); + return nonNull(player) && (UUID_RETTICHLP.equals(player.getStringUUID()) || getBoolean("fabric.development")); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java b/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java index 5880e357..ceac3396 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java @@ -73,7 +73,7 @@ public boolean isADuty(String targetName) { return color; } - public Component getMedicInformation(String playerName) { + public MutableComponent getMedicInformation(String playerName) { MutableComponent text = empty(); LocalDateTime bandageCooldownExpiration = storage.getMedicBandageCooldowns().getOrDefault(playerName, now()); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/HouseListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/HouseListener.java index 9f965caf..481c17ed 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/HouseListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/HouseListener.java @@ -2,10 +2,10 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; import java.time.LocalDateTime; import java.util.regex.Matcher; @@ -19,15 +19,14 @@ import static java.time.LocalDateTime.now; import static java.time.LocalDateTime.parse; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.DARK_RED; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_RED; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class HouseListener implements IMessageReceiveListener { @@ -39,7 +38,7 @@ public class HouseListener implements IMessageReceiveListener { private int lastHouseNumber = 0; @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher houseRenterHeaderMatcher = HOUSE_RENTER_HEADER_PATTERN.matcher(message); if (houseRenterHeaderMatcher.find()) { this.lastHouseNumber = parseInt(houseRenterHeaderMatcher.group("number")); @@ -50,19 +49,19 @@ public boolean onMessageReceive(Text text, String message) { if (houseRenterEntryOnlineMatcher.find() && this.lastHouseNumber != 0) { String playerName = houseRenterEntryOnlineMatcher.group("playerName"); - MutableText modifiedText = empty() - .append(literal(" » ").formatted(GRAY)) - .append(literal(playerName).formatted(GOLD)) - .append(literal(" (").formatted(DARK_GRAY)) - .append(literal("Online").formatted(GREEN)) - .append(literal(") ").formatted(DARK_GRAY)) - .append(literal("⨉").styled(style -> style + MutableComponent modifiedText = empty() + .append(literal(" » ").withStyle(GRAY)) + .append(literal(playerName).withStyle(GOLD)) + .append(literal(" (").withStyle(DARK_GRAY)) + .append(literal("Online").withStyle(GREEN)) + .append(literal(") ").withStyle(DARK_GRAY)) + .append(literal("⨉").withStyle(style -> style .withColor(RED) - .withFormatting(BOLD) - .withHoverEvent(new HoverEvent.ShowText(literal("Kündigen").formatted(RED))) + .withBold(true) + .withHoverEvent(new HoverEvent.ShowText(literal("Kündigen").withStyle(RED))) .withClickEvent(new ClickEvent.RunCommand("/unrent " + this.lastHouseNumber + " " + playerName)))); - player.sendMessage(modifiedText, false); + player.sendSystemMessage(modifiedText); return false; } @@ -73,21 +72,21 @@ public boolean onMessageReceive(Text text, String message) { LocalDateTime dateTime = parse(dateTimeString, DATE_TIME_FORMAT); long daysSinceOffline = abs(between(now(), dateTime).toDays()); - MutableText modifiedText = empty() - .append(literal(" » ").formatted(GRAY)) - .append(literal(playerName).formatted(GOLD)) - .append(literal(" (").formatted(DARK_GRAY)) - .append(literal("Offline seit " + dateTimeString).formatted(RED)) - .append(literal(" - ").formatted(DARK_GRAY)) - .append(literal(daysSinceOffline + " " + (daysSinceOffline == 1 ? "Tag" : "Tage")).formatted(DARK_RED)) - .append(literal(") ").formatted(DARK_GRAY)) - .append(literal("⨉").styled(style -> style + MutableComponent modifiedText = empty() + .append(literal(" » ").withStyle(GRAY)) + .append(literal(playerName).withStyle(GOLD)) + .append(literal(" (").withStyle(DARK_GRAY)) + .append(literal("Offline seit " + dateTimeString).withStyle(RED)) + .append(literal(" - ").withStyle(DARK_GRAY)) + .append(literal(daysSinceOffline + " " + (daysSinceOffline == 1 ? "Tag" : "Tage")).withStyle(DARK_RED)) + .append(literal(") ").withStyle(DARK_GRAY)) + .append(literal("⨉").withStyle(style -> style .withColor(RED) - .withFormatting(BOLD) - .withHoverEvent(new HoverEvent.ShowText(literal("Kündigen").formatted(RED))) + .withBold(true) + .withHoverEvent(new HoverEvent.ShowText(literal("Kündigen").withStyle(RED))) .withClickEvent(new ClickEvent.RunCommand("/unrent " + this.lastHouseNumber + " " + playerName)))); - player.sendMessage(modifiedText, false); + player.sendSystemMessage(modifiedText); return false; } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/MobileListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/MobileListener.java index 6551c205..67bf6161 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/MobileListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/MobileListener.java @@ -2,7 +2,7 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -18,7 +18,7 @@ public class MobileListener implements IMessageReceiveListener { private static final Pattern MOBILE_OFF_PATTERN = compile("^Dein Handy ist ausgeschaltet\\.$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher mobileOffMatcher = MOBILE_OFF_PATTERN.matcher(message); if (mobileOffMatcher.find()) { utilService.delayedAction(() -> commandService.sendCommand("togglephone"), COMMAND_COOLDOWN_MILLIS); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java index 80b7f074..7aa6b372 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java @@ -4,9 +4,9 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; import de.rettichlp.ucutils.listener.ITickListener; -import net.minecraft.network.ClientConnection; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.Text; +import net.minecraft.network.Connection; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; import java.io.IOException; import java.util.List; @@ -26,12 +26,11 @@ import static java.lang.Runtime.getRuntime; import static java.lang.System.getProperty; import static java.time.Duration.ofMinutes; -import static java.util.Objects.nonNull; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class PlayerListener implements IMessageReceiveListener, ITickListener { @@ -61,7 +60,7 @@ public class PlayerListener implements IMessageReceiveListener, ITickListener { private static final Pattern DECLINE_PATTERN = compile("^\\[Deal] (?:\\[UC])?(?[a-zA-Z0-9_]+) hat das Angebot abgelehnt\\.$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher deadAReviveMatcher = DEAD_AREVIVE_PATTERN.matcher(message); if (deadAReviveMatcher.find()) { storage.getActiveShutdowns().removeIf(shutdownReason -> shutdownReason == CEMETERY); @@ -156,7 +155,7 @@ public boolean onMessageReceive(Text text, String message) { @Override public void onTick() { - if (player.age % 1200 == 0 && !nameTagService.isAfk(player.getStringifiedName())) { + if (player.tickCount % 1200 == 0 && !nameTagService.isAfk(player.getPlainTextName())) { configuration.addMinutesSinceLastPayDay(1); } } @@ -171,13 +170,11 @@ private void shutdownPC() { command = new String[]{ "shutdown", "-h", "+" + SHUTDOWN_TIMEOUT }; // will fail potentially without sudo } - ClientConnection connection = player.networkHandler.getConnection(); - if (nonNull(connection)) { - connection.disconnect(empty() - .append(of("Der PC wird in").copy().formatted(GRAY)).append(" ") - .append(of(SHUTDOWN_TIMEOUT + " Sekunden").copy().formatted(RED)).append(" ") - .append(of("durch UCUtils heruntergefahren...").copy().formatted(GRAY))); - } + Connection connection = player.connection.getConnection(); + connection.disconnect(empty() + .append(literal("Der PC wird in").withStyle(GRAY)).append(" ") + .append(literal(SHUTDOWN_TIMEOUT + " Sekunden").withStyle(RED)).append(" ") + .append(literal("durch UCUtils heruntergefahren...").withStyle(GRAY))); if (command.length == 0) { LOGGER.warn("Unknown operating system {} - shutdown aborted", os); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/PrayListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/PrayListener.java index 897d11e8..9fb77309 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/PrayListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/PrayListener.java @@ -2,7 +2,7 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -17,7 +17,7 @@ public class PrayListener implements IMessageReceiveListener { private static final Pattern PRAYING_START_PATTERN = compile("^\\[Kirche] Du hast begonnen für (?:\\[UC])?(?[a-zA-Z0-9_]+) zu beten\\.$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher prayingStartMatcher = PRAYING_START_PATTERN.matcher(message); if (prayingStartMatcher.find()) { String playerName = prayingStartMatcher.group("playerName"); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java index 119cdcb8..2b5a3710 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java @@ -7,9 +7,9 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.common.services.NotificationService; import de.rettichlp.ucutils.listener.IHudRenderListener; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -25,21 +25,21 @@ public class RenderListener implements IHudRenderListener { @Override - public void onHudRender(DrawContext drawContext, RenderTickCounter renderTickCounter) { - renderNotifications(drawContext); - renderWidgets(drawContext); + public void onHudRender(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) { + renderNotifications(graphics); + renderWidgets(graphics); } - private void renderNotifications(DrawContext drawContext) { + private void renderNotifications(GuiGraphicsExtractor graphics) { ArrayList> widgets = new ArrayList<>(); widgets.addAll(getCountdownWidgets()); widgets.addAll(getNotificationWidgets()); for (int i = 0; i < widgets.size(); i++) { AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); - int x = MinecraftClient.getInstance().getWindow().getScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; + int x = Minecraft.getInstance().getWindow().getGuiScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; int y = 19 * i + 4; - abstractUCUtilsProgressTextWidget.draw(drawContext, x, y, RIGHT); + abstractUCUtilsProgressTextWidget.draw(graphics, x, y, RIGHT); } } @@ -56,7 +56,7 @@ private void renderNotifications(DrawContext drawContext) { .toList(); } - private void renderWidgets(DrawContext drawContext) { - renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(drawContext)); + private void renderWidgets(GuiGraphicsExtractor graphics) { + renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(graphics)); } } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/SoundTriggerListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/SoundTriggerListener.java index d435e368..c584d149 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/SoundTriggerListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/SoundTriggerListener.java @@ -3,7 +3,7 @@ import de.rettichlp.ucutils.common.models.Faction; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,7 +28,7 @@ public class SoundTriggerListener implements IMessageReceiveListener { private static final Pattern FIRE_START_PATTERN = compile("^News: Es wurde ein Feuer bei .+ gemeldet!$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Faction playerFaction = storage.getFaction(player.getGameProfile().name()); Matcher bankRobberyMatcher = BANK_ROBBERY_PATTERN.matcher(message); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java index c025a628..f83e145d 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/BadFactionListener.java @@ -2,11 +2,10 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.phys.Vec3; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,8 +27,8 @@ public class BadFactionListener implements IMessageReceiveListener { public boolean onMessageReceive(Component text, String message) { Matcher blackMarketDealerEntryMatcher = BLACK_MARKET_DEALER_ENTRY_PATTERN.matcher(message); if (blackMarketDealerEntryMatcher.find()) { - Vec3i blackMarketPosition = storage.getBlackMarketPosition(); - Vec3i dealerPosition = storage.getDealerPosition(); + Vec3 blackMarketPosition = storage.getBlackMarketPosition(); + Vec3 dealerPosition = storage.getDealerPosition(); // extract location from message Component last = text.getSiblings().getLast(); @@ -44,9 +43,9 @@ public boolean onMessageReceive(Component text, String message) { return true; } - Vec3i extractedPosition = new BlockPos(parseInt(locationPieces[0]), parseInt(locationPieces[1]), parseInt(locationPieces[2])); + Vec3 extractedPosition = new Vec3(parseInt(locationPieces[0]), parseInt(locationPieces[1]), parseInt(locationPieces[2])); - if ((blackMarketPosition != null && extractedPosition.distSqr(blackMarketPosition) < 5) || (dealerPosition != null && extractedPosition.distSqr(dealerPosition) < 5)) { + if ((blackMarketPosition != null && extractedPosition.distanceToSqr(blackMarketPosition) < 5) || (dealerPosition != null && extractedPosition.distanceToSqr(dealerPosition) < 5)) { MutableComponent text1 = text.copy().append(literal(" ⯐").withStyle(DARK_RED, BOLD)); player.sendSystemMessage(text1); return false; diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java index 3e839209..c9d667d3 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java @@ -3,11 +3,11 @@ import de.rettichlp.ucutils.common.models.Countdown; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; import java.awt.Color; import java.time.Duration; @@ -24,17 +24,17 @@ import static java.time.Duration.ofMinutes; import static java.time.LocalDateTime.now; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.DARK_AQUA; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.DARK_GREEN; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.GREEN; -import static net.minecraft.util.Formatting.RED; -import static net.minecraft.util.Formatting.YELLOW; +import static net.minecraft.ChatFormatting.BOLD; +import static net.minecraft.ChatFormatting.DARK_AQUA; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_GREEN; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class MedicListener implements IMessageReceiveListener { @@ -51,7 +51,7 @@ public class MedicListener implements IMessageReceiveListener { private static final Pattern STORAGE_INGREDIENT_SHARE_PATTERN = compile("^.+ (?:\\[UC])?(?[a-zA-Z0-9_]+): (?\\d+)x Wirkstoff \\| (?\\d+)x Trägerstoff \\| (?\\d+)x Zusatzstoff$"); private static final Pattern STORAGE_INGREDIENT_ACCEPT_PATTERN = compile("^.+ (?:\\[UC])?(?[a-zA-Z0-9_]+): Ich nehme (?Wirkstoff|Trägerstoff|Zusatzstoff)! \\(geschätzt: (?\\d+) → (?\\d+)\\)$"); - private static final MutableText STORAGE_TEXT = empty() + private static final MutableComponent STORAGE_TEXT = empty() .append(literal("ʟ").withColor(Color.decode("#AA0000").getRGB())) .append(literal("ᴀ").withColor(Color.decode("#BF1515").getRGB())) .append(literal("ʙ").withColor(Color.decode("#D52B2B").getRGB())) @@ -59,7 +59,7 @@ public class MedicListener implements IMessageReceiveListener { .append(literal("ʀ").withColor(Color.decode("#FF5555").getRGB())); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher medicBandageMatcher = MEDIC_BANDAGE_PATTERN.matcher(message); if (medicBandageMatcher.find()) { storage.getCountdowns().add(new Countdown("Bandage", MEDIC_BANDAGE_DURATION)); @@ -106,22 +106,22 @@ public boolean onMessageReceive(Text text, String message) { int ingredient2 = parseInt(storageIngredientShareMatcher.group("ingredient2")); int ingredient3 = parseInt(storageIngredientShareMatcher.group("ingredient3")); - player.sendMessage(empty(), false); + player.sendSystemMessage(empty()); - MutableText storageText = empty() - .append(literal("[").formatted(DARK_GRAY)) + MutableComponent storageText = empty() + .append(literal("[").withStyle(DARK_GRAY)) .append(STORAGE_TEXT) - .append(literal("] ").formatted(DARK_GRAY)) - .append(literal("Aktueller Bestand (geteilt von " + playerName + ")").formatted(GRAY)) - .append(literal(":").formatted(DARK_GRAY)); + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Aktueller Bestand (geteilt von " + playerName + ")").withStyle(GRAY)) + .append(literal(":").withStyle(DARK_GRAY)); - player.sendMessage(storageText, false); + player.sendSystemMessage(storageText); - player.sendMessage(getIngredientText("Wirkstoff", ingredient1), false); - player.sendMessage(getIngredientText("Trägerstoff", ingredient2), false); - player.sendMessage(getIngredientText("Zusatzstoff", ingredient3), false); + player.sendSystemMessage(getIngredientText("Wirkstoff", ingredient1)); + player.sendSystemMessage(getIngredientText("Trägerstoff", ingredient2)); + player.sendSystemMessage(getIngredientText("Zusatzstoff", ingredient3)); - player.sendMessage(empty(), false); + player.sendSystemMessage(empty()); return false; } @@ -132,42 +132,42 @@ public boolean onMessageReceive(Text text, String message) { int amountBefore = parseInt(storageIngredientAcceptMatcher.group("amountBefore")); int amountAfter = parseInt(storageIngredientAcceptMatcher.group("amountAfter")); - player.sendMessage(empty() - .append(literal("[").formatted(DARK_GRAY)) + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) .append(STORAGE_TEXT) - .append(literal("] ").formatted(DARK_GRAY)) - .append(literal(playerName).formatted(RED)) - .append(literal(" übernimmt ").formatted(GRAY)) - .append(literal(ingredient).formatted(RED)) - .append(literal(":").formatted(DARK_GRAY)), false); - - player.sendMessage(empty() - .append(literal(" > ").formatted(DARK_GRAY)) - .append(literal("Geschätzte Menge nach Transport").formatted(GRAY)) - .append(literal(": ").formatted(DARK_GRAY)) - .append(literal(amountBefore + " → ").formatted(GRAY)) - .append(literal(valueOf(amountAfter)).formatted(getColor(amountAfter), BOLD)), false); + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal(playerName).withStyle(RED)) + .append(literal(" übernimmt ").withStyle(GRAY)) + .append(literal(ingredient).withStyle(RED)) + .append(literal(":").withStyle(DARK_GRAY))); + + player.sendSystemMessage(empty() + .append(literal(" > ").withStyle(DARK_GRAY)) + .append(literal("Geschätzte Menge nach Transport").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal(amountBefore + " → ").withStyle(GRAY)) + .append(literal(valueOf(amountAfter)).withStyle(getColor(amountAfter), BOLD))); return false; } return true; } - private MutableText getIngredientText(String ingredient, int amount) { + private MutableComponent getIngredientText(String ingredient, int amount) { return empty() - .append(literal(" > ").formatted(DARK_GRAY)) - .append(literal("[").formatted(DARK_GRAY)) - .append(literal("Ich übernehme!").styled(style -> style - .withFormatting(DARK_AQUA) + .append(literal(" > ").withStyle(DARK_GRAY)) + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Ich übernehme!").withStyle(style -> style + .withColor(DARK_AQUA) .withHoverEvent(new HoverEvent.ShowText(literal("Klicke um bescheid zu sagen, dass Du den Transport übernimmst"))) .withClickEvent(new ClickEvent.RunCommand("/f Ich nehme " + ingredient + "! (geschätzt: " + amount + " → " + (amount + 20) + ")")))) - .append(literal("] ").formatted(DARK_GRAY)) - .append(literal(ingredient).formatted(GRAY)) - .append(literal(": ").formatted(DARK_GRAY)) - .append(literal(valueOf(amount)).formatted(getColor(amount), BOLD)); + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal(ingredient).withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal(valueOf(amount)).withStyle(getColor(amount), BOLD)); } - private Formatting getColor(int amount) { + private ChatFormatting getColor(int amount) { if (amount >= 80) { return DARK_GREEN; } else if (amount >= 60) { diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/WantedListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/WantedListener.java index c2391bc5..617e24af 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/WantedListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/WantedListener.java @@ -3,8 +3,8 @@ import de.rettichlp.ucutils.common.models.WantedEntry; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import java.util.function.Predicate; import java.util.regex.Matcher; @@ -19,14 +19,14 @@ import static java.lang.Integer.parseInt; import static java.lang.String.valueOf; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.of; -import static net.minecraft.util.Formatting.BLUE; -import static net.minecraft.util.Formatting.DARK_AQUA; -import static net.minecraft.util.Formatting.DARK_GRAY; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.RED; +import static net.minecraft.ChatFormatting.BLUE; +import static net.minecraft.ChatFormatting.DARK_AQUA; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; @UCUtilsListener public class WantedListener implements IMessageReceiveListener { @@ -53,7 +53,7 @@ public class WantedListener implements IMessageReceiveListener { private static final Pattern TRACKER_AGENT_PATTERN = compile("^HQ: (Agent|Agentin) (?:\\[UC])?(?[a-zA-Z0-9_]+) hat ein Peilsender an (?:\\[UC])?(?[a-zA-Z0-9_]+) befestigt, over\\.$"); @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher wantedGivenPointsMatcher = WANTED_GIVEN_POINTS_PATTERN.matcher(message); if (wantedGivenPointsMatcher.find()) { String playerName = wantedGivenPointsMatcher.group(1); @@ -67,12 +67,12 @@ public boolean onMessageReceive(Text text, String message) { storage.getWantedEntries().add(wantedEntry); }); - Text modifiedMessage = empty() - .append(of("➥").copy().formatted(GRAY)).append(" ") - .append(of(wantedGivenPointsMatcher.group(2)).copy().formatted(BLUE)).append(" ") - .append(of("Wanteds").copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("➥").withStyle(GRAY)).append(" ") + .append(literal(wantedGivenPointsMatcher.group(2)).withStyle(BLUE)).append(" ") + .append(literal("Wanteds").withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -87,14 +87,14 @@ public boolean onMessageReceive(Text text, String message) { .findFirst() .ifPresent(wantedEntry -> wantedEntry.setReason(reason)); - Text modifiedMessage = empty() - .append(of("Gesucht").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(wantedGivenReasonMatcher.group(1)).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(wantedGivenReasonMatcher.group(2)).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Gesucht").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(wantedGivenReasonMatcher.group(1)).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(wantedGivenReasonMatcher.group(2)).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -104,13 +104,13 @@ public boolean onMessageReceive(Text text, String message) { String reason = wantedReasonMatcher.group("reason"); String time = wantedReasonMatcher.group("time"); - Text modifiedMessage = empty() - .append(of("➥").copy().formatted(GRAY)).append(" ") - .append(of(reason).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(time).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("➥").withStyle(GRAY)).append(" ") + .append(literal(reason).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(time).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -122,17 +122,17 @@ public boolean onMessageReceive(Text text, String message) { int wpAmount = getWpAmountAndDelete(targetName); - Text modifiedMessage = empty() - .append(of("Gelöscht").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("(").copy().formatted(GRAY)) - .append(of(valueOf(wpAmount)).copy().formatted(RED)) - .append(of(")").copy().formatted(GRAY)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Gelöscht").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("(").withStyle(GRAY)) + .append(literal(valueOf(wpAmount)).withStyle(RED)) + .append(literal(")").withStyle(GRAY)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -143,17 +143,17 @@ public boolean onMessageReceive(Text text, String message) { String playerName = wantedKillMatcher.group("playerName"); int wpAmount = getWpAmountAndDelete(targetName); - Text modifiedMessage = empty() - .append(of("Getötet").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("(").copy().formatted(GRAY)) - .append(of(valueOf(wpAmount)).copy().formatted(RED)) - .append(of(")").copy().formatted(GRAY)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); - - player.sendMessage(modifiedMessage, false); + Component modifiedMessage = empty() + .append(literal("Getötet").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("(").withStyle(GRAY)) + .append(literal(valueOf(wpAmount)).withStyle(RED)) + .append(literal(")").withStyle(GRAY)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); + + player.sendSystemMessage(modifiedMessage); return false; } @@ -163,17 +163,17 @@ public boolean onMessageReceive(Text text, String message) { String playerName = wantedJailMatcher.group("playerName"); int wpAmount = getWpAmountAndDelete(targetName); - Text modifiedMessage = empty() - .append(of("Eingesperrt").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("(").copy().formatted(GRAY)) - .append(of(valueOf(wpAmount)).copy().formatted(RED)) - .append(of(")").copy().formatted(GRAY)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); - - player.sendMessage(modifiedMessage, false); + Component modifiedMessage = empty() + .append(literal("Eingesperrt").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("(").withStyle(GRAY)) + .append(literal(valueOf(wpAmount)).withStyle(RED)) + .append(literal(")").withStyle(GRAY)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); + + player.sendSystemMessage(modifiedMessage); return false; } @@ -188,14 +188,14 @@ public boolean onMessageReceive(Text text, String message) { String officerName = carParkticketMatcher.group("playerName"); String plate = carParkticketMatcher.group("plate"); - Text modifiedMessage = empty() - .append(of("Strafzettel").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(plate).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(officerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Strafzettel").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(plate).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(officerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -204,14 +204,14 @@ public boolean onMessageReceive(Text text, String message) { String officerName = carParkticketRemoveMatcher.group("playerName"); String plate = carParkticketRemoveMatcher.group("plate"); - Text modifiedMessage = empty() - .append(of("Strafzettel entfernt").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(plate).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(officerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Strafzettel entfernt").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(plate).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(officerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -221,14 +221,14 @@ public boolean onMessageReceive(Text text, String message) { String officerName = searchTrunkMatcher.group("playerName"); String plate = searchTrunkMatcher.group("plate"); - Text modifiedMessage = empty() - .append(of("Fahrzeugkontrolle").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(plate).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(officerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Fahrzeugkontrolle").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(plate).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(officerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -238,14 +238,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = wantedUnarrestMatcher.group("playerName"); String targetName = wantedUnarrestMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Entlassen").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Entlassen").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -266,21 +266,21 @@ public boolean onMessageReceive(Text text, String message) { WantedEntry wantedEntry = new WantedEntry(playerName, wantedPointAmount, reason); storage.getWantedEntries().add(wantedEntry); - Formatting color = nameTagService.getWantedPointColor(wantedPointAmount); + ChatFormatting color = nameTagService.getWantedPointColor(wantedPointAmount); if (commandService.showCommandOutputMessage("wanteds")) { - Text modifiedMessage = empty() - .append(of("➥").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(color)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(reason).copy().formatted(color)).append(" ") - .append(of("(").copy().formatted(GRAY)) - .append(of(valueOf(wantedPointAmount)).copy().formatted(BLUE)) - .append(of(")").copy().formatted(GRAY)).append(" ") - .append(of(isAfk ? "|" : "").copy().formatted(DARK_GRAY)).append(" ") - .append(of(isAfk ? "AFK" : "").copy().formatted(GRAY)); - - player.sendMessage(modifiedMessage, false); + Component modifiedMessage = empty() + .append(literal("➥").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(color)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(reason).withStyle(color)).append(" ") + .append(literal("(").withStyle(GRAY)) + .append(literal(valueOf(wantedPointAmount)).withStyle(BLUE)) + .append(literal(")").withStyle(GRAY)).append(" ") + .append(literal(isAfk ? "|" : "").withStyle(DARK_GRAY)).append(" ") + .append(literal(isAfk ? "AFK" : "").withStyle(GRAY)); + + player.sendSystemMessage(modifiedMessage); } return false; @@ -291,14 +291,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = licenseDrivingGiveMatcher.group("playerName"); String targetName = licenseDrivingGiveMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Führerscheinrückgabe").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Führerscheinrückgabe").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -308,14 +308,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = licenseDrivingTakeMatcher.group("playerName"); String targetName = licenseDrivingTakeMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Führerscheinabnahme").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Führerscheinabnahme").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -325,14 +325,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = licenseGunGiveMatcher.group("playerName"); String targetName = licenseGunGiveMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Waffenscheinrückgabe").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Waffenscheinrückgabe").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -342,14 +342,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = licenseGunTakeMatcher.group("playerName"); String targetName = licenseGunTakeMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Waffenscheinabnahme").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Waffenscheinabnahme").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -359,14 +359,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = takeGunsMatcher.group("playerName"); String targetName = takeGunsMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Waffenabnahme").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Waffenabnahme").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -376,14 +376,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = takeDrugsMatcher.group("playerName"); String targetName = takeDrugsMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Drogenabnahme").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(BLUE)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(BLUE)); + Component modifiedMessage = empty() + .append(literal("Drogenabnahme").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(BLUE)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(BLUE)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } @@ -393,14 +393,14 @@ public boolean onMessageReceive(Text text, String message) { String playerName = trackerMatcher.group("playerName"); String targetName = trackerMatcher.group("targetName"); - Text modifiedMessage = empty() - .append(of("Peilsender").copy().formatted(RED)).append(" ") - .append(of("-").copy().formatted(GRAY)).append(" ") - .append(of(playerName).copy().formatted(DARK_AQUA)).append(" ") - .append(of("»").copy().formatted(GRAY)).append(" ") - .append(of(targetName).copy().formatted(GOLD)); + Component modifiedMessage = empty() + .append(literal("Peilsender").withStyle(RED)).append(" ") + .append(literal("-").withStyle(GRAY)).append(" ") + .append(literal(playerName).withStyle(DARK_AQUA)).append(" ") + .append(literal("»").withStyle(GRAY)).append(" ") + .append(literal(targetName).withStyle(GOLD)); - player.sendMessage(modifiedMessage, false); + player.sendSystemMessage(modifiedMessage); return false; } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/DeepSeaFisherListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/DeepSeaFisherListener.java index c520b8e8..8093d89b 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/DeepSeaFisherListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/DeepSeaFisherListener.java @@ -5,8 +5,8 @@ import de.rettichlp.ucutils.listener.INaviSpotReachedListener; import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.text.Text; -import net.minecraft.util.math.BlockPos; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -38,7 +38,7 @@ public class DeepSeaFisherListener implements IMessageReceiveListener, INaviSpot private boolean canCatchFish = true; @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher deepSeaFisherStartMatcher = DEEP_SEA_FISHER_START_PATTERN.matcher(message); if (deepSeaFisherStartMatcher.find()) { this.visitedDeepSeaFisherJobSpots = new ArrayList<>(); @@ -106,8 +106,8 @@ private void startFishing() { private @NotNull Optional getNearestFisherJobSpot(@NotNull Collection deepSeaFisherJobSpots) { return deepSeaFisherJobSpots.stream() .min((spot1, spot2) -> { - double distance1 = player.squaredDistanceTo(spot1.getPosition().getX(), spot1.getPosition().getY(), spot1.getPosition().getZ()); - double distance2 = player.squaredDistanceTo(spot2.getPosition().getX(), spot2.getPosition().getY(), spot2.getPosition().getZ()); + double distance1 = player.distanceToSqr(spot1.getPosition().getX(), spot1.getPosition().getY(), spot1.getPosition().getZ()); + double distance2 = player.distanceToSqr(spot2.getPosition().getX(), spot2.getPosition().getY(), spot2.getPosition().getZ()); return compare(distance1, distance2); }); } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/GarbageManListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/GarbageManListener.java index aefd893b..c4964836 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/GarbageManListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/GarbageManListener.java @@ -5,12 +5,12 @@ import de.rettichlp.ucutils.listener.ITickListener; import lombok.AllArgsConstructor; import lombok.Getter; -import net.minecraft.client.MinecraftClient; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.ScoreboardEntry; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.text.Text; -import net.minecraft.util.math.BlockPos; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.scores.Objective; +import net.minecraft.world.scores.PlayerScoreEntry; +import net.minecraft.world.scores.Scoreboard; import java.util.Collection; import java.util.Optional; @@ -28,7 +28,7 @@ import static java.util.Objects.nonNull; import static java.util.Optional.empty; import static java.util.regex.Pattern.compile; -import static net.minecraft.scoreboard.ScoreboardDisplaySlot.SIDEBAR; +import static net.minecraft.world.scores.DisplaySlot.SIDEBAR; @UCUtilsListener public class GarbageManListener implements IMessageReceiveListener, ITickListener { @@ -41,7 +41,7 @@ public class GarbageManListener implements IMessageReceiveListener, ITickListene private long lastCommandExecution = 0; @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher garbageManDropStartMatcher = GARBAGE_MAN_DROP_START.matcher(message); if (garbageManDropStartMatcher.find()) { this.isDropStep = true; @@ -66,7 +66,7 @@ public void onTick() { // check if in drop spot range WasteDropSpot nearestWasteDropSpot = getNearestWasteDropSpot(); - if (!player.getBlockPos().isWithinDistance(nearestWasteDropSpot.getDropSpot(), 3)) { + if (!player.getOnPos().closerToCenterThan(nearestWasteDropSpot.getDropSpot(), 3)) { return; } @@ -94,45 +94,45 @@ public void onTick() { private WasteDropSpot getNearestWasteDropSpot() { return stream(WasteDropSpot.values()).min((o1, o2) -> { - BlockPos blockPos = player.getBlockPos(); - double distance1 = blockPos.getSquaredDistance(o1.getDropSpot()); - double distance2 = blockPos.getSquaredDistance(o2.getDropSpot()); + Vec3 position = player.position(); + double distance1 = position.distanceTo(o1.getDropSpot()); + double distance2 = position.distanceTo(o2.getDropSpot()); return compare(distance1, distance2); }).orElseThrow(() -> new IllegalStateException("This should never happen")); } private int getWasteLeft(WasteDropSpot wasteDropSpot) { - assert MinecraftClient.getInstance().world != null; // cannot be null at this point - Scoreboard scoreboard = MinecraftClient.getInstance().world.getScoreboard(); + assert Minecraft.getInstance().level != null; // cannot be null at this point + Scoreboard scoreboard = Minecraft.getInstance().level.getScoreboard(); - Collection scoreboardEntries = getGarbageManScoreboard() - .map(scoreboard::getScoreboardEntries) + Collection scoreboardEntries = getGarbageManScoreboard() + .map(scoreboard::listPlayerScores) .orElse(emptyList()); return scoreboardEntries.stream() - .filter(scoreboardEntry -> scoreboardEntry.name().getString().equals("§e" + wasteDropSpot.getDisplayName() + "§8:")) - .map(ScoreboardEntry::value) + .filter(playerScoreEntry -> playerScoreEntry.owner().equals("§e" + wasteDropSpot.getDisplayName() + "§8:")) + .map(PlayerScoreEntry::value) .findFirst() .orElse(0); } - private Optional getGarbageManScoreboard() { - assert MinecraftClient.getInstance().world != null; // cannot be null at this point - Scoreboard scoreboard = MinecraftClient.getInstance().world.getScoreboard(); - ScoreboardObjective scoreboardObjective = scoreboard.getObjectiveForSlot(SIDEBAR); - return nonNull(scoreboardObjective) && GARBAGE_MAN_TEXT.equals(scoreboardObjective.getName()) ? Optional.of(scoreboardObjective) : empty(); + private Optional getGarbageManScoreboard() { + assert Minecraft.getInstance().level != null; // cannot be null at this point + Scoreboard scoreboard = Minecraft.getInstance().level.getScoreboard(); + Objective displayObjective = scoreboard.getDisplayObjective(SIDEBAR); + return nonNull(displayObjective) && GARBAGE_MAN_TEXT.equals(displayObjective.getName()) ? Optional.of(displayObjective) : empty(); } @Getter @AllArgsConstructor private enum WasteDropSpot { - GLASS("Glas", new BlockPos(884, 67, 349)), - METAL("Metall", new BlockPos(900, 67, 392)), - WASTE("Abfall", new BlockPos(908, 67, 361)), - WOOD("Holz", new BlockPos(876, 69, 376)); + GLASS("Glas", new Vec3(884, 67, 349)), + METAL("Metall", new Vec3(900, 67, 392)), + WASTE("Abfall", new Vec3(908, 67, 361)), + WOOD("Holz", new Vec3(876, 69, 376)); private final String displayName; - private final BlockPos dropSpot; + private final Vec3 dropSpot; } } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java index dac213bb..10eb76bd 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java @@ -5,8 +5,8 @@ import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; import de.rettichlp.ucutils.listener.INaviSpotReachedListener; -import net.minecraft.text.Text; -import net.minecraft.util.math.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.phys.Vec3; import java.time.LocalDateTime; import java.util.Optional; @@ -39,7 +39,7 @@ public class JobListener implements IMessageReceiveListener, INaviSpotReachedLis private LocalDateTime miningBoosterExpirationTime; @Override - public boolean onMessageReceive(Text text, String message) { + public boolean onMessageReceive(Component text, String message) { Matcher transportDeliverMatcher = TRANSPORT_DELIVER_PATTERN.matcher(message); if (transportDeliverMatcher.find()) { utilService.delayedAction(() -> commandService.sendCommand("droptransport"), SECONDS.toMillis(10)); @@ -93,12 +93,12 @@ public void onNaviSpotReached() { return; } - if (storage.getCurrentJob() == PIZZA_DELIVERY && player.getBlockPos().isWithinDistance(new BlockPos(266, 69, 54), 2)) { + if (storage.getCurrentJob() == PIZZA_DELIVERY && player.position().closerThan(new Vec3(266, 69, 54), 2)) { commandService.sendCommand("getpizza"); return; } - if (storage.getCurrentJob() == TOBACCO_PLANTATION && player.getBlockPos().isWithinDistance(new BlockPos(-133, 69, -78), 3)) { + if (storage.getCurrentJob() == TOBACCO_PLANTATION && player.position().closerThan(new Vec3(-133, 69, -78), 3)) { commandService.sendCommand("droptabak"); } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java index 3453c6af..16b30aec 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ChatScreenMixin.java @@ -21,10 +21,10 @@ @Mixin(ChatScreen.class) public abstract class ChatScreenMixin { - @Inject(method = "sendMessage", at = @At("HEAD")) - private void ucutils$sendMessageHead(@NotNull String message, boolean addToHistory, CallbackInfo ci) { - String[] messageParts = message.split(" "); - if (messageParts.length >= 2 && message.startsWith("/screenshot ")) { + @Inject(method = "handleChatInput", at = @At("HEAD")) + private void ucutils$handleChatInputHead(String msg, boolean addToRecent, CallbackInfo ci) { + String[] messageParts = msg.split(" "); + if (messageParts.length >= 2 && msg.startsWith("/screenshot ")) { String screenshotTypeString = messageParts[1].toLowerCase(); ScreenshotType screenshotType = fromDisplayName(screenshotTypeString).orElse(OTHER); screenshotType.take(file -> notificationService.sendInfoNotification(translatable("ucutils.notification.info.screenshot_saved", file.getName()))); diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 085e908f..97be706d 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -5,7 +5,7 @@ "mixins": [ "EntityMixin", "ItemStackMixin", - "MinecartEntityMixin" + "MinecartMixin" ], "injectors": { "defaultRequire": 1 @@ -14,14 +14,14 @@ "requireAnnotations": true }, "client": [ - "AbstractMinecartEntityRendererMixin", + "AbstractContainerScreenMixin", + "AbstractMinecartRendererMixin", "ChatScreenMixin", "ClientPlayerEntityMixin", "ClientPlayNetworkHandlerMixin", + "EntityRendererMixin", "GameMenuScreenMixin", - "HandledScreenMixin", - "InGameHudMixin", - "PlayerEntityRendererMixin", - "PlayerListHudMixin" + "GuiMixin", + "PlayerTabOverlayMixin" ] } From 54fdbca784f0ef288987867735f773294a0d08ef Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 17 Jun 2026 22:35:08 +0200 Subject: [PATCH 10/64] Reformat code --- src/main/java/de/rettichlp/ucutils/common/Storage.java | 1 - .../ucutils/mixin/AbstractContainerScreenMixin.java | 4 ---- .../ucutils/mixin/AbstractMinecartRendererMixin.java | 3 ++- .../de/rettichlp/ucutils/mixin/EntityRendererMixin.java | 1 - .../de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java | 6 +++--- src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java | 8 ++++---- 6 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index 606e0bfe..02723e68 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -11,7 +11,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -import net.minecraft.core.Vec3i; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.vehicle.minecart.Minecart; import net.minecraft.world.level.saveddata.maps.MapId; diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java index 04359741..06000a8b 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java @@ -1,6 +1,5 @@ package de.rettichlp.ucutils.mixin; -import com.mojang.authlib.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; @@ -12,11 +11,8 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.component.ItemLore; -import org.jetbrains.annotations.NotNull; import org.jspecify.annotations.NonNull; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java index 7a1f6719..1c864823 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java @@ -14,7 +14,8 @@ import static de.rettichlp.ucutils.UCUtils.storage; @Mixin(AbstractMinecartRenderer.class) -public abstract class AbstractMinecartRendererMixin extends EntityRenderer { +public abstract class AbstractMinecartRendererMixin + extends EntityRenderer { protected AbstractMinecartRendererMixin(EntityRendererProvider.Context context) { super(context); diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java index ea7d5bea..6a1b5a6c 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java @@ -53,7 +53,6 @@ public abstract class EntityRendererMixin this.minecraft.setScreen(new MainOptionsScreen())) .width(204) .build(); diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java index 2d9f625b..5dd01ca8 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java @@ -84,10 +84,10 @@ public abstract class GuiMixin { value = "INVOKE", target = "Lnet/minecraft/client/gui/Gui;extractHearts(Lnet/minecraft/client/gui/GuiGraphicsExtractor;Lnet/minecraft/world/entity/player/Player;IIIIFIIIZ)V", shift = AFTER)) - private void ucutils$renderStatusBarsInvoke(GuiGraphicsExtractor graphics, - CallbackInfo ci, - @Local(name = "xRight") int xRight, - @Local(name = "yLineAir") int yLineAir) { + private void ucutils$extractPlayerHealthInvoke(GuiGraphicsExtractor graphics, + CallbackInfo ci, + @Local(name = "xRight") int xRight, + @Local(name = "yLineAir") int yLineAir) { if (!storage.isUnicaCity()) { return; } From 0b9371e3e68423cc64910a77741e60a1d0cf004b Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 17:38:44 +0200 Subject: [PATCH 11/64] Rename mixins for consistency and update mixin configuration --- .../mixin/{GameMenuScreenMixin.java => PauseScreenMixin.java} | 4 ++-- .../mixin/{ClientPlayerEntityMixin.java => PlayerMixin.java} | 2 +- src/main/resources/ucutils.mixins.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/main/java/de/rettichlp/ucutils/mixin/{GameMenuScreenMixin.java => PauseScreenMixin.java} (94%) rename src/main/java/de/rettichlp/ucutils/mixin/{ClientPlayerEntityMixin.java => PlayerMixin.java} (97%) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/PauseScreenMixin.java similarity index 94% rename from src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java rename to src/main/java/de/rettichlp/ucutils/mixin/PauseScreenMixin.java index 29141b60..6b91bb34 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/PauseScreenMixin.java @@ -16,9 +16,9 @@ import static net.minecraft.network.chat.Component.literal; @Mixin(PauseScreen.class) -public abstract class GameMenuScreenMixin extends Screen { +public abstract class PauseScreenMixin extends Screen { - protected GameMenuScreenMixin(Component title) { + protected PauseScreenMixin(Component title) { super(title); } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/PlayerMixin.java similarity index 97% rename from src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java rename to src/main/java/de/rettichlp/ucutils/mixin/PlayerMixin.java index 3c928f33..562fec44 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/PlayerMixin.java @@ -18,7 +18,7 @@ import static net.minecraft.world.item.Items.GLASS_BOTTLE; @Mixin(Player.class) -public abstract class ClientPlayerEntityMixin { +public abstract class PlayerMixin { @Unique private final static List SHOP_LOCATIONS = List.of( diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 97be706d..8ccd1b32 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -17,11 +17,11 @@ "AbstractContainerScreenMixin", "AbstractMinecartRendererMixin", "ChatScreenMixin", - "ClientPlayerEntityMixin", "ClientPlayNetworkHandlerMixin", "EntityRendererMixin", - "GameMenuScreenMixin", "GuiMixin", + "PauseScreenMixin", + "PlayerMixin", "PlayerTabOverlayMixin" ] } From fd7d4ac20c55b703de91d5b2c7b14c4cd41b6094 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 17:41:07 +0200 Subject: [PATCH 12/64] Update Gradle build script to include ClassIndex dependency and refactor Java version constants --- build.gradle.kts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 51fb3605..d513d482 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import org.gradle.api.JavaVersion.VERSION_25 + plugins { id("net.fabricmc.fabric-loom") `maven-publish` @@ -36,6 +38,7 @@ dependencies { compileOnly("com.terraformersmc:modmenu:${providers.gradleProperty("modmenu_version").get()}") // https://github.com/atteo/classindex + include("org.atteo.classindex:classindex:3.13") implementation("org.atteo.classindex:classindex:3.13") annotationProcessor("org.atteo.classindex:classindex:3.13") } @@ -59,8 +62,8 @@ java { // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_25 - targetCompatibility = JavaVersion.VERSION_25 + sourceCompatibility = VERSION_25 + targetCompatibility = VERSION_25 } tasks.jar { From 278e60f381a39761b728f229601fa871fe3b7a4c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:46:17 +0000 Subject: [PATCH 13/64] Update actions/checkout action to v7 --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dff3f6aa..b7700415 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 76f1305f..fada23f2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 From a84c2a835f322d04148fcdab65109018954f69fa Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 20:39:18 +0200 Subject: [PATCH 14/64] Scale AFK nametags and adjust position for better readability --- .../ucutils/common/services/NameTagService.java | 3 --- .../ucutils/mixin/EntityRendererMixin.java | 13 +++++++++++-- .../rettichlp/ucutils/mixin/PauseScreenMixin.java | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java b/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java index ceac3396..0fffed70 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/NameTagService.java @@ -14,7 +14,6 @@ import static java.time.Duration.between; import static java.time.LocalDateTime.now; import static net.minecraft.ChatFormatting.BLUE; -import static net.minecraft.ChatFormatting.BOLD; import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.DARK_GREEN; import static net.minecraft.ChatFormatting.DARK_RED; @@ -29,8 +28,6 @@ public class NameTagService { - public static final Component AFK_TAG = literal("ᴀꜰᴋ").withStyle(GOLD, BOLD); - private static final Component A_DUTY_PREFIX = empty() .append(literal("[").withStyle(DARK_GRAY)) .append(literal("UC").withStyle(BLUE)) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java index 6a1b5a6c..495d98e3 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java @@ -9,6 +9,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -16,11 +17,16 @@ import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.nameTagService; import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.common.services.NameTagService.AFK_TAG; +import static net.minecraft.ChatFormatting.BOLD; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.network.chat.Component.literal; @Mixin(EntityRenderer.class) public abstract class EntityRendererMixin { + @Unique + private static final Component AFK_TAG = literal("ᴀꜰᴋ").withStyle(GOLD, BOLD); + @Inject(method = "submitNameDisplay(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/level/CameraRenderState;I)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;popPose()V")) @@ -52,7 +58,10 @@ public abstract class EntityRendererMixin this.minecraft.setScreen(new MainOptionsScreen())) + Button buttonWidget = Button.builder(literal("UCUtils Settings"), _ -> this.minecraft.setScreen(new MainOptionsScreen())) .width(204) .build(); From 416e681c1da52b694e08e51949f1e080029aa806 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 22:04:52 +0200 Subject: [PATCH 15/64] Refactor component usage to remove unnecessary `.copy()` calls and adjust message prefix type for consistency --- .../rettichlp/ucutils/common/gui/screens/OptionsScreen.java | 4 ++-- .../de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java | 2 +- .../common/gui/widgets/base/AbstractUCUtilsTextWidget.java | 2 +- .../de/rettichlp/ucutils/common/services/MessageService.java | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java index f9e61c2d..febf0ad9 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/OptionsScreen.java @@ -51,7 +51,7 @@ protected void initFooter() { LinearLayout directionalLayoutWidget = this.layout.addToFooter(horizontal().spacing(8)); directionalLayoutWidget.addChild(Button.builder(GUI_BACK, _ -> back()).width(120).build()); directionalLayoutWidget.addChild(Button.builder(GUI_DONE, _ -> onClose()).width(200).build()); - directionalLayoutWidget.addChild(Button.builder(literal("Discord").copy().withColor(DISCORD_COLOR), confirmLink(this, DISCORD_INVITE)).width(56).build()); - directionalLayoutWidget.addChild(Button.builder(literal("Modrinth").copy().withColor(MODRINTH_COLOR), confirmLink(this, MODRINTH)).width(56).build()); + directionalLayoutWidget.addChild(Button.builder(literal("Discord").withColor(DISCORD_COLOR), confirmLink(this, DISCORD_INVITE)).width(56).build()); + directionalLayoutWidget.addChild(Button.builder(literal("Modrinth").withColor(MODRINTH_COLOR), confirmLink(this, MODRINTH)).width(56).build()); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java index 16d8312a..a587149f 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java @@ -21,7 +21,7 @@ public Component text() { return configuration.getMinutesSinceLastPayDay() >= 55 && configuration.getMoneyBankAmount() > 100000 && (currentTimeMillis() / 500 % 2 == 0) ? empty() .append(keyValue("Geld", configuration.getMoneyCashAmount() + "$")).append(" ") - .append(keyValue("Bank", configuration.getMoneyBankAmount() + "$").copy().withColor(RED.getRGB())) + .append(keyValue("Bank", configuration.getMoneyBankAmount() + "$").withColor(RED.getRGB())) : empty() .append(keyValue("Geld", configuration.getMoneyCashAmount() + "$")).append(" ") .append(keyValue("Bank", configuration.getMoneyBankAmount() + "$")); diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java index 1b0e3f21..a8126125 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java @@ -44,7 +44,7 @@ public Color getBackgroundColor() { return renderService.getSecondaryColor(getBorderColor()); } - protected Component keyValue(String key, String value) { + protected MutableComponent keyValue(String key, String value) { return keyValue(key, literal(value)); } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java b/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java index f8823463..d3199844 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java @@ -1,6 +1,7 @@ package de.rettichlp.ucutils.common.services; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import org.jetbrains.annotations.NotNull; import java.time.LocalDate; @@ -23,7 +24,7 @@ public class MessageService { public static final DateTimeFormatter DATE_TIME_FORMAT = ofPattern("dd.MM.yyyy HH:mm:ss"); public static final DateTimeFormatter TIME_FORMAT = ofPattern("HH:mm:ss"); - protected static final Component modMessagePrefix = Component.empty() + protected static final MutableComponent modMessagePrefix = Component.empty() .append(literal("✦").withStyle(DARK_PURPLE)) .append(literal(" ")) .append(literal("UCU").withStyle(LIGHT_PURPLE)) @@ -36,7 +37,7 @@ public void sendModMessage(String message, boolean inActionbar) { } public void sendModMessage(Component message, boolean inActionbar) { - Component messageText = modMessagePrefix.copy().append(message); + Component messageText = modMessagePrefix.append(message); if (inActionbar) { player.sendOverlayMessage(messageText); From 29ca97406f71131e028dfcab37cb5d3ebd2aad08 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 22:07:34 +0200 Subject: [PATCH 16/64] Replace `StringWidget` with `MultiLineTextWidget` to fix text handling in `CarOptionsScreen` --- .../common/gui/screens/options/CarOptionsScreen.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java index edbd0927..eca1a4e6 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/CarOptionsScreen.java @@ -3,7 +3,7 @@ import de.rettichlp.ucutils.common.configuration.options.CarOptions; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; -import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.components.MultiLineTextWidget; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.layouts.GridLayout; import net.minecraft.client.gui.layouts.LayoutSettings; @@ -58,8 +58,9 @@ public void initBody() { toggleButton3.setTooltip(Tooltip.create(CAR_AUTOMATION_CHECK_KFZ_TOOLTIP)); gridLayoutRowHelper.addChild(toggleButton3); - StringWidget stringWidget = gridLayoutRowHelper.addChild(new StringWidget(CAR_PREMIUM_INFO.copy().withStyle(GOLD), this.font), 2, LayoutSettings.defaults().alignHorizontallyCenter().paddingTop(16)); - stringWidget.setMaxWidth(308); + MultiLineTextWidget multiLineTextWidget = gridLayoutRowHelper.addChild(new MultiLineTextWidget(CAR_PREMIUM_INFO.copy().withStyle(GOLD), this.font), 2, LayoutSettings.defaults().alignHorizontallyCenter().paddingTop(16)); + multiLineTextWidget.setMaxWidth(308); + multiLineTextWidget.setCentered(true); ToggleButtonWidget toggleButton4 = new ToggleButtonWidget(CAR_GENERAL_FAST_LOCK_NAME, carOptions::fastLock, carOptions.fastLock()); toggleButton4.setWidth(150); From d993a262f560cb3ac7561c3002bc6949bb1bf546 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 22:19:09 +0200 Subject: [PATCH 17/64] Fix alignment of header in `UCUtilsScreen` --- .../rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java index 50a53928..4e6ccbcd 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/UCUtilsScreen.java @@ -4,6 +4,7 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.StringWidget; import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; +import net.minecraft.client.gui.layouts.LayoutSettings; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; @@ -102,8 +103,8 @@ public void back() { protected void initHeader() { LinearLayout linearLayout = this.layout.addToHeader(vertical().spacing(4)); linearLayout.newCellSettings().alignHorizontallyCenter(); - linearLayout.addChild(new StringWidget(this.title, this.font)); - linearLayout.addChild(new StringWidget(this.subTitle, this.font)); + linearLayout.addChild(new StringWidget(this.title, this.font), LayoutSettings::alignHorizontallyCenter); + linearLayout.addChild(new StringWidget(this.subTitle, this.font), LayoutSettings::alignHorizontallyCenter); } protected void initFooter() {} From d75f1915add46424f6e0304d9c663775cf43957d Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 18 Jun 2026 22:29:58 +0200 Subject: [PATCH 18/64] Remove `EntityMixin`, refactor minecart highlighting logic, and clean up unused fields --- .../de/rettichlp/ucutils/common/Storage.java | 7 -- .../mixin/AbstractMinecartRendererMixin.java | 16 ++++- .../rettichlp/ucutils/mixin/EntityMixin.java | 64 ------------------- src/main/resources/ucutils.mixins.json | 1 - 4 files changed, 15 insertions(+), 73 deletions(-) delete mode 100644 src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index 02723e68..b5181b36 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -12,7 +12,6 @@ import lombok.Getter; import lombok.Setter; import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.vehicle.minecart.Minecart; import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; @@ -94,10 +93,6 @@ public class Storage { @Setter private long joinTimestamp = 0; - @Getter - @Setter - private Minecart minecartEntityToHighlight; - @Getter @Setter private boolean premium = false; @@ -147,8 +142,6 @@ public void print() { LOGGER.info("hydration: {}", this.hydration); // joinTimestamp LOGGER.info("joinTimestamp: {}", this.joinTimestamp); - // minecartEntityToHighlight - LOGGER.info("minecartEntityToHighlight: {}", this.minecartEntityToHighlight); // premium LOGGER.info("premium: {}", this.premium); // team diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java index 1c864823..393c928e 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java @@ -5,18 +5,24 @@ import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.state.MinecartRenderState; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; +import net.minecraft.world.entity.vehicle.minecart.Minecart; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; @Mixin(AbstractMinecartRenderer.class) public abstract class AbstractMinecartRendererMixin extends EntityRenderer { + @Unique + private Minecart minecart; + protected AbstractMinecartRendererMixin(EntityRendererProvider.Context context) { super(context); } @@ -32,7 +38,15 @@ protected AbstractMinecartRendererMixin(EntityRendererProvider.Context context) return; } - if (storage.getMinecartEntityToHighlight() != null && storage.getMinecartEntityToHighlight().getUUID().equals(entity.getUUID())) { + boolean playerIsInMinecart = entity.getPassengers().stream() + .anyMatch(passenger -> passenger.getUUID().equals(player.getUUID())); + + if (playerIsInMinecart) { + this.minecart = (Minecart) entity; + return; + } + + if (entity.equals(this.minecart)) { state.outlineColor = 0xFFFFAA00; } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java deleted file mode 100644 index b868a9ba..00000000 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java +++ /dev/null @@ -1,64 +0,0 @@ -package de.rettichlp.ucutils.mixin; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.vehicle.minecart.Minecart; -import net.minecraft.world.level.entity.UniquelyIdentifyable; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import static de.rettichlp.ucutils.UCUtils.commandService; -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.player; -import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.UCUtils.utilService; - -@Mixin(Entity.class) -public abstract class EntityMixin { - - @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;ZZ)Z", at = @At("RETURN")) - private void ucutils$startRidingReturn(Entity entityToRide, - boolean force, - boolean sendEventAndTriggers, - @NotNull CallbackInfoReturnable cir) { - if (!storage.isUnicaCity()) { - return; - } - - // only for successful start riding - if (!cir.getReturnValue()) { - return; - } - - UniquelyIdentifyable self = (Entity) (Object) this; - if (self.getUUID().equals(player.getUUID()) && entityToRide instanceof Minecart) { - storage.setMinecartEntityToHighlight(null); - - if (configuration.getOptions().car().automatedStart() && !storage.isPremium()) { - // start the car with a small delay to ensure the player is fully in the vehicle - utilService.delayedAction(() -> commandService.sendCommand("car start"), 500); - } - - // lock the car after 1 second and the small delay if not already locked - if (!storage.isCarLocked() && configuration.getOptions().car().automatedLock() && !storage.isPremium()) { - utilService.delayedAction(() -> commandService.sendCommand("car lock"), 1500); - } - } - } - - @Inject(method = "stopRiding", at = @At("HEAD")) - private void ucutils$stopRidingHead(CallbackInfo ci) { - if (!storage.isUnicaCity()) { - return; - } - - Entity self = (Entity) (Object) this; - if (self instanceof Player && self.isPassenger() && self.getVehicle() instanceof Minecart minecart) { - storage.setMinecartEntityToHighlight(minecart); - } - } -} diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 8ccd1b32..afaca6c6 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -3,7 +3,6 @@ "package": "de.rettichlp.ucutils.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "EntityMixin", "ItemStackMixin", "MinecartMixin" ], From 588fc4f3c9293bd6f4607bd49c7823d0128f06ff Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 19 Jun 2026 09:39:28 +0200 Subject: [PATCH 19/64] Remove `RenderListener` and `IHudRenderListener`, integrate notification and widget rendering directly into `GuiMixin` --- .../ucutils/listener/IHudRenderListener.java | 9 --- .../ucutils/listener/impl/RenderListener.java | 62 ------------------- .../de/rettichlp/ucutils/mixin/GuiMixin.java | 46 ++++++++++++++ 3 files changed, 46 insertions(+), 71 deletions(-) delete mode 100644 src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java delete mode 100644 src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java diff --git a/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java b/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java deleted file mode 100644 index 5501ee58..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import net.minecraft.client.DeltaTracker; -import net.minecraft.client.gui.GuiGraphicsExtractor; - -public interface IHudRenderListener extends IUCUtilsListener { - - void onHudRender(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java deleted file mode 100644 index 2b5a3710..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.rettichlp.ucutils.listener.impl; - -import de.rettichlp.ucutils.common.gui.widgets.CountdownWidget; -import de.rettichlp.ucutils.common.gui.widgets.NotificationWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; -import de.rettichlp.ucutils.common.models.Countdown; -import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.common.services.NotificationService; -import de.rettichlp.ucutils.listener.IHudRenderListener; -import net.minecraft.client.DeltaTracker; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Unmodifiable; - -import java.util.ArrayList; -import java.util.List; - -import static de.rettichlp.ucutils.UCUtils.notificationService; -import static de.rettichlp.ucutils.UCUtils.renderService; -import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; - -@UCUtilsListener -public class RenderListener implements IHudRenderListener { - - @Override - public void onHudRender(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker) { - renderNotifications(graphics); - renderWidgets(graphics); - } - - private void renderNotifications(GuiGraphicsExtractor graphics) { - ArrayList> widgets = new ArrayList<>(); - widgets.addAll(getCountdownWidgets()); - widgets.addAll(getNotificationWidgets()); - - for (int i = 0; i < widgets.size(); i++) { - AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); - int x = Minecraft.getInstance().getWindow().getGuiScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; - int y = 19 * i + 4; - abstractUCUtilsProgressTextWidget.draw(graphics, x, y, RIGHT); - } - } - - private @NotNull @Unmodifiable List getCountdownWidgets() { - return storage.getCountdowns().stream() - .filter(Countdown::isActive) - .map(Countdown::toWidget) - .toList(); - } - - private @NotNull @Unmodifiable List getNotificationWidgets() { - return notificationService.getActiveNotifications().stream() - .map(NotificationService.Notification::toWidget) - .toList(); - } - - private void renderWidgets(GuiGraphicsExtractor graphics) { - renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(graphics)); - } -} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java index 5dd01ca8..838ba2ba 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java @@ -2,6 +2,9 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.platform.NativeImage; +import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; +import de.rettichlp.ucutils.common.models.Countdown; +import de.rettichlp.ucutils.common.services.NotificationService; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; @@ -21,13 +24,17 @@ import java.io.InputStream; import java.nio.file.Path; +import java.util.ArrayList; import static com.mojang.blaze3d.platform.NativeImage.read; import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.MOD_ID; import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.player; +import static de.rettichlp.ucutils.UCUtils.renderService; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; import static java.lang.Math.ceil; import static java.lang.Math.clamp; import static java.lang.Math.round; @@ -79,6 +86,21 @@ public abstract class GuiMixin { graphics.blit(GUI_TEXTURED, CAPTCHA_IDENTIFIER, x, y, 0, 0, side, side, side, side); } + @Inject(method = "extractHotbarAndDecorations", at = @At("TAIL")) + private void ucutils$extractHotbarAndDecorationsTail(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) { + Profiler.get().popPush("notification"); + extractNotifications(graphics); + Profiler.get().pop(); + + if (!storage.isUnicaCity()) { + return; + } + + Profiler.get().popPush("widget"); + extractWidgets(graphics); + Profiler.get().pop(); + } + @Inject(method = "extractPlayerHealth", at = @At( value = "INVOKE", @@ -101,6 +123,30 @@ public abstract class GuiMixin { Profiler.get().pop(); } + @Unique + private void extractNotifications(GuiGraphicsExtractor graphics) { + ArrayList> widgets = new ArrayList<>(); + widgets.addAll(storage.getCountdowns().stream() + .filter(Countdown::isActive) + .map(Countdown::toWidget) + .toList()); + widgets.addAll(notificationService.getActiveNotifications().stream() + .map(NotificationService.Notification::toWidget) + .toList()); + + for (int i = 0; i < widgets.size(); i++) { + AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); + int x = Minecraft.getInstance().getWindow().getGuiScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; + int y = 19 * i + 4; + abstractUCUtilsProgressTextWidget.draw(graphics, x, y, RIGHT); + } + } + + @Unique + private void extractWidgets(GuiGraphicsExtractor graphics) { + renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(graphics)); + } + @Unique private void renderHydration(GuiGraphicsExtractor context, int yLineAir, int xRight) { double maxHydrated = 20; From e5bdd410ac5540326f5131ba38f6e1bdaa600340 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 07:51:07 +0000 Subject: [PATCH 20/64] Update Gradle to v9.6.0 --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 ++-- gradlew.bat | 35 ++++++++---------------- 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df6a6ad7..eb84db68 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/gradlew b/gradlew index 739907df..249efbb0 100644 --- a/gradlew +++ b/gradlew @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/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/. diff --git a/gradlew.bat b/gradlew.bat index c4bdd3ab..a51ec4f5 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ 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 +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,29 +65,18 @@ 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 +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -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! -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 +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From a5b50e202343e1d193f837874b1c4d4d58b1f904 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 19 Jun 2026 10:34:29 +0200 Subject: [PATCH 21/64] Scale medical information nametags and adjust positions for consistency with AFK nametags --- .../de/rettichlp/ucutils/mixin/EntityRendererMixin.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java index 495d98e3..cb2fe220 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityRendererMixin.java @@ -53,14 +53,17 @@ public abstract class EntityRendererMixin Date: Fri, 19 Jun 2026 11:46:42 +0200 Subject: [PATCH 22/64] Add `EntityMixin` to improve minecart highlighting logic and automate vehicle actions --- .../de/rettichlp/ucutils/common/Storage.java | 7 +++ .../mixin/AbstractMinecartRendererMixin.java | 17 +----- .../rettichlp/ucutils/mixin/EntityMixin.java | 53 +++++++++++++++++++ src/main/resources/ucutils.mixins.json | 1 + 4 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index b5181b36..02723e68 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -12,6 +12,7 @@ import lombok.Getter; import lombok.Setter; import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.vehicle.minecart.Minecart; import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; @@ -93,6 +94,10 @@ public class Storage { @Setter private long joinTimestamp = 0; + @Getter + @Setter + private Minecart minecartEntityToHighlight; + @Getter @Setter private boolean premium = false; @@ -142,6 +147,8 @@ public void print() { LOGGER.info("hydration: {}", this.hydration); // joinTimestamp LOGGER.info("joinTimestamp: {}", this.joinTimestamp); + // minecartEntityToHighlight + LOGGER.info("minecartEntityToHighlight: {}", this.minecartEntityToHighlight); // premium LOGGER.info("premium: {}", this.premium); // team diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java index 393c928e..0585b96e 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractMinecartRendererMixin.java @@ -5,9 +5,7 @@ import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.state.MinecartRenderState; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; -import net.minecraft.world.entity.vehicle.minecart.Minecart; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -20,16 +18,13 @@ public abstract class AbstractMinecartRendererMixin extends EntityRenderer { - @Unique - private Minecart minecart; - protected AbstractMinecartRendererMixin(EntityRendererProvider.Context context) { super(context); } @Inject(method = "extractRenderState(Lnet/minecraft/world/entity/vehicle/minecart/AbstractMinecart;Lnet/minecraft/client/renderer/entity/state/MinecartRenderState;F)V", at = @At("TAIL")) - private void ucutils$updateRenderStateTail(T entity, S state, float partialTicks, CallbackInfo ci) { + private void ucutils$extractRenderStateTail(T entity, S state, float partialTicks, CallbackInfo ci) { if (!storage.isUnicaCity()) { return; } @@ -38,15 +33,7 @@ protected AbstractMinecartRendererMixin(EntityRendererProvider.Context context) return; } - boolean playerIsInMinecart = entity.getPassengers().stream() - .anyMatch(passenger -> passenger.getUUID().equals(player.getUUID())); - - if (playerIsInMinecart) { - this.minecart = (Minecart) entity; - return; - } - - if (entity.equals(this.minecart)) { + if (!entity.getPassengers().contains(player) && entity.equals(storage.getMinecartEntityToHighlight())) { state.outlineColor = 0xFFFFAA00; } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java new file mode 100644 index 00000000..2ad8176a --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java @@ -0,0 +1,53 @@ +package de.rettichlp.ucutils.mixin; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.minecart.Minecart; +import net.minecraft.world.level.entity.UniquelyIdentifyable; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import static de.rettichlp.ucutils.UCUtils.commandService; +import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.player; +import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.UCUtils.utilService; + +@Mixin(Entity.class) +public abstract class EntityMixin { + + @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;ZZ)Z", at = @At("RETURN")) + private void ucutils$startRidingReturn(Entity entityToRide, + boolean force, + boolean sendEventAndTriggers, + @NotNull CallbackInfoReturnable cir) { + if (!storage.isUnicaCity()) { + return; + } + + // only for successful start riding + if (!cir.getReturnValue()) { + return; + } + + Entity self = (Entity) (Object) this; + if (self.equals(player) && entityToRide instanceof Minecart minecart) { + System.out.println("startRiding: " + self + " -> " + minecart); + storage.setMinecartEntityToHighlight(minecart); + + if (configuration.getOptions().car().automatedStart() && !storage.isPremium()) { + // start the car with a small delay to ensure the player is fully in the vehicle + utilService.delayedAction(() -> commandService.sendCommand("car start"), 500); + } + + // lock the car after 1 second and the small delay if not already locked + if (!storage.isCarLocked() && configuration.getOptions().car().automatedLock() && !storage.isPremium()) { + utilService.delayedAction(() -> commandService.sendCommand("car lock"), 1500); + } + } + } +} diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index afaca6c6..8ccd1b32 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -3,6 +3,7 @@ "package": "de.rettichlp.ucutils.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ + "EntityMixin", "ItemStackMixin", "MinecartMixin" ], From 7928cc7b9ff66d41ff2ba3b63ea78c2672fb05dc Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 19 Jun 2026 11:46:51 +0200 Subject: [PATCH 23/64] Expand car lock/unlock patterns to support new automated locking and unlocking messages --- .../java/de/rettichlp/ucutils/listener/impl/CarListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java index 664a6d7f..f09a888d 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java @@ -16,8 +16,8 @@ @UCUtilsListener public class CarListener implements IMessageReceiveListener { - private static final Pattern CAR_UNLOCK_PATTERN = compile("^\\[Car] Du hast deinen .+ aufgeschlossen\\.$"); - private static final Pattern CAR_LOCK_PATTERN = compile("^\\[Car] Du hast deinen .+ abgeschlossen\\.$"); + private static final Pattern CAR_UNLOCK_PATTERN = compile("^\\[Car] Du hast deinen .+ aufgeschlossen\\.$|^\\[Car] Dein .+ wurde automatisch aufgeschlossen\\.$"); + private static final Pattern CAR_LOCK_PATTERN = compile("^\\[Car] Du hast deinen .+ abgeschlossen\\.$|^\\[Car] Motor automatisch gestartet · Türen verriegelt\\.$"); private static final Pattern CAR_LOCKED_OWN_PATTERN = compile("^\\[Car] Dein Fahrzeug ist abgeschlossen\\.$"); private static final Pattern CAR_FIND_PATTERN = compile("^\\[Car] Das Fahrzeug befindet sich bei » X: (?-?\\d+) \\| Y: (?-?\\d+) \\| Z: (?-?\\d+)$"); From 065e19075c6d78d02e7489a66429c64c689b600d Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 19 Jun 2026 16:05:40 +0200 Subject: [PATCH 24/64] Remove debug println from `EntityMixin` during minecart ride logic cleanup --- src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java index 2ad8176a..3d9f89dc 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java @@ -1,14 +1,11 @@ package de.rettichlp.ucutils.mixin; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.minecart.Minecart; -import net.minecraft.world.level.entity.UniquelyIdentifyable; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import static de.rettichlp.ucutils.UCUtils.commandService; @@ -36,7 +33,6 @@ public abstract class EntityMixin { Entity self = (Entity) (Object) this; if (self.equals(player) && entityToRide instanceof Minecart minecart) { - System.out.println("startRiding: " + self + " -> " + minecart); storage.setMinecartEntityToHighlight(minecart); if (configuration.getOptions().car().automatedStart() && !storage.isPremium()) { From 7d25a5364f94933f6b63bd254b0f395f594d94a9 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sat, 20 Jun 2026 14:54:41 +0200 Subject: [PATCH 25/64] Add `ResyncableTimer` to synchronize periodic tasks and integrate with economy payday logic --- .../java/de/rettichlp/ucutils/UCUtils.java | 3 ++ .../common/services/ResyncableTimer.java | 54 +++++++++++++++++++ .../listener/impl/EconomyListener.java | 2 + 3 files changed, 59 insertions(+) create mode 100644 src/main/java/de/rettichlp/ucutils/common/services/ResyncableTimer.java diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index 93a29700..479016b4 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -9,6 +9,7 @@ import de.rettichlp.ucutils.common.services.NameTagService; import de.rettichlp.ucutils.common.services.NotificationService; import de.rettichlp.ucutils.common.services.RenderService; +import de.rettichlp.ucutils.common.services.ResyncableTimer; import de.rettichlp.ucutils.common.services.SyncService; import de.rettichlp.ucutils.common.services.UtilService; import net.fabricmc.api.ModInitializer; @@ -23,6 +24,7 @@ import static java.lang.Boolean.getBoolean; import static java.lang.System.currentTimeMillis; import static java.util.Objects.isNull; +import static java.util.concurrent.TimeUnit.MINUTES; public class UCUtils implements ModInitializer { @@ -44,6 +46,7 @@ public class UCUtils implements ModInitializer { public static final Api api = new Api(); public static final Storage storage = new Storage(); public static final Configuration configuration = new Configuration().loadFromFile(); + public static final ResyncableTimer synchronisedMinuteTimer = new ResyncableTimer(0, 1, MINUTES); public static LocalPlayer player; public static ClientPacketListener networkHandler; diff --git a/src/main/java/de/rettichlp/ucutils/common/services/ResyncableTimer.java b/src/main/java/de/rettichlp/ucutils/common/services/ResyncableTimer.java new file mode 100644 index 00000000..c79d6eda --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/common/services/ResyncableTimer.java @@ -0,0 +1,54 @@ +package de.rettichlp.ucutils.common.services; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import static de.rettichlp.ucutils.UCUtils.LOGGER; +import static java.time.LocalDateTime.now; +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; + +public class ResyncableTimer { + + private final ScheduledExecutorService scheduler = newSingleThreadScheduledExecutor(); + private final Collection> onTick = new ArrayList<>(); + private final long initialDelay; + private final long period; + private final TimeUnit unit; + + private int currentTick = 0; + private ScheduledFuture currentTask; + + public ResyncableTimer(long initialDelay, long period, TimeUnit unit) { + this.initialDelay = initialDelay; + this.period = period; + this.unit = unit; + } + + public void start() { + schedule(); + } + + public void synchronize() { + schedule(); + LOGGER.info("Synchronized timer to {}", now()); + } + + public void add(Consumer onTick) { + this.onTick.add(onTick); + } + + private void schedule() { + if (this.currentTask != null) { + this.currentTask.cancel(false); + } + + this.currentTask = this.scheduler.scheduleAtFixedRate(() -> { + this.currentTick++; + this.onTick.forEach(onTick -> onTick.accept(this.currentTick)); + }, this.initialDelay, this.period, this.unit); + } +} diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java index be26f400..6d98dc54 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java @@ -18,6 +18,7 @@ import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.UCUtils.synchronisedMinuteTimer; import static de.rettichlp.ucutils.UCUtils.utilService; import static java.lang.Integer.parseInt; import static java.lang.Math.max; @@ -249,6 +250,7 @@ public boolean onMessageReceive(Component text, String message) { if (paydayCountdownMatcher.find()) { int minutes = parseInt(paydayCountdownMatcher.group("minutes")); int minutesSinceLastPayDay = 60 - minutes; + synchronisedMinuteTimer.synchronize(); configuration.setMinutesSinceLastPayDay(minutesSinceLastPayDay); utilService.delayedAction(() -> { From c6c680c20534d94970ab46e6a6c72602702e6dc3 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sat, 20 Jun 2026 14:55:40 +0200 Subject: [PATCH 26/64] Refactor periodic task handling by replacing `startRepeatingSync` and `onTick` logic with `synchronisedMinuteTimer` integration --- .../java/de/rettichlp/ucutils/UCUtils.java | 29 ++++++++++++++++++- .../common/configuration/Configuration.java | 8 ----- .../ucutils/common/services/SyncService.java | 17 ----------- .../ucutils/listener/impl/PlayerListener.java | 12 +------- 4 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index 479016b4..021de2f2 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -64,7 +64,34 @@ public void onInitialize() { this.registry.registerSounds(); - syncService.startRepeatingSync(); + // add payday minute + synchronisedMinuteTimer.add(_ -> { + if (storage.isUnicaCity() && !nameTagService.isAfk(player.getPlainTextName())) { + configuration.setMinutesSinceLastPayDay(configuration.getMinutesSinceLastPayDay() + 1); + } + }); + + // show health for hydration bar sync + synchronisedMinuteTimer.add(currentTick -> { + // every 3 minutes + if (currentTick % 3 != 0) { + return; + } + + if (storage.isUnicaCity() && !nameTagService.isAfk(player.getPlainTextName()) && configuration.getOptions().showHydration()) { + commandService.sendCommandWithHiddenOutput("health"); + } + }); + + // asynchronously save every 10 minutes + synchronisedMinuteTimer.add(currentTick -> { + // every 10 minutes + if (currentTick % 10 != 0) { + return; + } + + new Thread(configuration::saveToFile).start(); + }); ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { player = client.player; diff --git a/src/main/java/de/rettichlp/ucutils/common/configuration/Configuration.java b/src/main/java/de/rettichlp/ucutils/common/configuration/Configuration.java index 1cd7db8f..8b9a3311 100644 --- a/src/main/java/de/rettichlp/ucutils/common/configuration/Configuration.java +++ b/src/main/java/de/rettichlp/ucutils/common/configuration/Configuration.java @@ -30,14 +30,6 @@ public class Configuration { private int predictedPayDaySalary = 0; private int predictedPayDayExp = 0; - public void addMinutesSinceLastPayDay(int minutes) { - this.minutesSinceLastPayDay += minutes; - - if (this.minutesSinceLastPayDay % 10 == 0) { - new Thread(this::saveToFile).start(); // asynchronously save every active 10 minutes - } - } - public void addPredictedPayDaySalary(int salary) { this.predictedPayDaySalary += salary; } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java index 788023e6..89d5b684 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java @@ -8,18 +8,14 @@ import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.api; import static de.rettichlp.ucutils.UCUtils.commandService; -import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.UCUtils.utilService; import static de.rettichlp.ucutils.common.models.Faction.NULL; -import static de.rettichlp.ucutils.common.services.CommandService.COMMAND_COOLDOWN_MILLIS; import static java.awt.Color.MAGENTA; import static java.util.Objects.nonNull; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; import static java.util.concurrent.TimeUnit.MINUTES; -import static java.util.concurrent.TimeUnit.SECONDS; import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.GRAY; import static net.minecraft.ChatFormatting.GREEN; @@ -30,19 +26,6 @@ public class SyncService { - public void startRepeatingSync() { - newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { - if (!storage.isUnicaCity()) { - return; - } - - // show health for hydration bar sync - if (configuration.getOptions().showHydration()) { - utilService.delayedAction(() -> commandService.sendCommandWithHiddenOutput("health"), COMMAND_COOLDOWN_MILLIS); - } - }, 20, 180, SECONDS); - } - public void syncFactionMembers() { for (Faction faction : Faction.values()) { if (faction == NULL) { diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java index 7aa6b372..3dc86dde 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java @@ -3,7 +3,6 @@ import de.rettichlp.ucutils.common.models.Countdown; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import de.rettichlp.ucutils.listener.ITickListener; import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; @@ -15,8 +14,6 @@ import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.commandService; -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.nameTagService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.common.models.ShutdownReason.CEMETERY; @@ -33,7 +30,7 @@ import static net.minecraft.network.chat.Component.literal; @UCUtilsListener -public class PlayerListener implements IMessageReceiveListener, ITickListener { +public class PlayerListener implements IMessageReceiveListener { private static final String SHUTDOWN_TIMEOUT = "5"; @@ -153,13 +150,6 @@ public boolean onMessageReceive(Component text, String message) { return true; } - @Override - public void onTick() { - if (player.tickCount % 1200 == 0 && !nameTagService.isAfk(player.getPlainTextName())) { - configuration.addMinutesSinceLastPayDay(1); - } - } - private void shutdownPC() { String os = getProperty("os.name").toLowerCase(); String[] command = new String[0]; From 85039feaf0809cc8d7ff715589fedd8b187b7d80 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 21 Jun 2026 15:29:12 +0200 Subject: [PATCH 27/64] Adjust `synchronisedMinuteTimer` initialization and start timer during client initialization --- src/main/java/de/rettichlp/ucutils/UCUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index 021de2f2..ac467c24 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -46,7 +46,7 @@ public class UCUtils implements ModInitializer { public static final Api api = new Api(); public static final Storage storage = new Storage(); public static final Configuration configuration = new Configuration().loadFromFile(); - public static final ResyncableTimer synchronisedMinuteTimer = new ResyncableTimer(0, 1, MINUTES); + public static final ResyncableTimer synchronisedMinuteTimer = new ResyncableTimer(1, 1, MINUTES); public static LocalPlayer player; public static ClientPacketListener networkHandler; @@ -58,6 +58,7 @@ public class UCUtils implements ModInitializer { @Override public void onInitialize() { // This entrypoint is suitable for setting up client-specific logic, such as rendering. + synchronisedMinuteTimer.start(); syncService.syncFactionMembers(); syncService.syncTeamMembers(); From 1b0ae0c1c6f9be54c913d1dcbc730478eedde604 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 21 Jun 2026 21:51:16 +0200 Subject: [PATCH 28/64] Fix `sendModMessage` to use `.copy()` for `modMessagePrefix` to ensure message consistency --- .../de/rettichlp/ucutils/common/services/MessageService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java b/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java index d3199844..5a0ad01b 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/MessageService.java @@ -37,7 +37,7 @@ public void sendModMessage(String message, boolean inActionbar) { } public void sendModMessage(Component message, boolean inActionbar) { - Component messageText = modMessagePrefix.append(message); + Component messageText = modMessagePrefix.copy().append(message); if (inActionbar) { player.sendOverlayMessage(messageText); From eedec7aefd397fed41910b2e762c54e309378677 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 21 Jun 2026 21:55:34 +0200 Subject: [PATCH 29/64] Move villager data handling to `ClientPacketListenerMixin` and remove logic from `ClientPlayNetworkHandlerMixin` --- .../mixin/ClientPacketListenerMixin.java | 74 +++++++++++++++++++ .../mixin/ClientPlayNetworkHandlerMixin.java | 56 -------------- src/main/resources/ucutils.mixins.json | 1 + 3 files changed, 75 insertions(+), 56 deletions(-) create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java new file mode 100644 index 00000000..761ac30a --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java @@ -0,0 +1,74 @@ +package de.rettichlp.ucutils.mixin; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.villager.Villager; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static de.rettichlp.ucutils.UCUtils.player; +import static de.rettichlp.ucutils.UCUtils.storage; +import static java.util.Objects.requireNonNull; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; +import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; + +@Mixin(ClientPacketListener.class) +public class ClientPacketListenerMixin { + + @Inject(method = "handleSetEntityData", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/network/syncher/SynchedEntityData;assignValues(Ljava/util/List;)V", + shift = AFTER)) + private void ucutils$handleSetEntityDataInvoke(ClientboundSetEntityDataPacket packet, CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + Level world = Minecraft.getInstance().level; + if (world == null) { + return; + } + + Entity entity = world.getEntity(packet.id()); + if (!(entity instanceof Villager villager) || !villager.hasCustomName()) { + return; + } + + String customNameString = requireNonNull(villager.getCustomName()).getString(); + Vec3 entityPos = villager.position(); + + // already notified check + if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition())) { + return; + } + + switch (customNameString) { + case "Dealer" -> { + storage.setBlackMarketPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Dealer").withStyle(RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Dealer ist in der Nähe!").withStyle(GRAY))); + } + case "Schwarzmarkt" -> { + storage.setDealerPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Schwarzmarkt").withStyle(RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Schwarzmarkt ist in der Nähe!").withStyle(GRAY))); + } + } + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java index 6d291a3c..a299691c 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -4,16 +4,10 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NonNull; -import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; -import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.villager.Villager; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -26,15 +20,11 @@ import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.notificationService; -import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static java.awt.Color.WHITE; -import static java.util.Objects.requireNonNull; import static net.minecraft.ChatFormatting.BLUE; import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.GOLD; -import static net.minecraft.ChatFormatting.GRAY; -import static net.minecraft.ChatFormatting.RED; import static net.minecraft.ChatFormatting.YELLOW; import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; @@ -65,52 +55,6 @@ public abstract class ClientPlayNetworkHandlerMixin { @Unique private final Collection enrichedGameProfiles = new HashSet<>(); - @Inject(method = "handlePlayerInfoUpdate", at = @At("TAIL")) - private void ucutils$handlePlayerInfoUpdateTail(ClientboundPlayerInfoUpdatePacket packet, CallbackInfo ci) { - if (!storage.isUnicaCity()) { - return; - } - - Level world = Minecraft.getInstance().level; - if (world == null) { - return; - } - - packet.entries().forEach(entry -> { - Entity entity = world.getEntity(entry.profileId()); - if (!(entity instanceof Villager villager) || !villager.hasCustomName()) { - return; - } - - String customNameString = requireNonNull(villager.getCustomName()).getString(); - Vec3 entityPos = villager.position(); - - // already notified check - if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition())) { - return; - } - - switch (customNameString) { - case "Dealer" -> { - storage.setBlackMarketPosition(entityPos); - player.sendSystemMessage(empty() - .append(literal("[").withStyle(DARK_GRAY)) - .append(literal("Dealer").withStyle(RED)) - .append(literal("] ").withStyle(DARK_GRAY)) - .append(literal("Der Dealer ist in der Nähe!").withStyle(GRAY))); - } - case "Schwarzmarkt" -> { - storage.setDealerPosition(entityPos); - player.sendSystemMessage(empty() - .append(literal("[").withStyle(DARK_GRAY)) - .append(literal("Schwarzmarkt").withStyle(RED)) - .append(literal("] ").withStyle(DARK_GRAY)) - .append(literal("Der Schwarzmarkt ist in der Nähe!").withStyle(GRAY))); - } - } - }); - } - @Inject(method = "handlePlayerInfoRemove", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 8ccd1b32..86f758f5 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -17,6 +17,7 @@ "AbstractContainerScreenMixin", "AbstractMinecartRendererMixin", "ChatScreenMixin", + "ClientPacketListenerMixin", "ClientPlayNetworkHandlerMixin", "EntityRendererMixin", "GuiMixin", From 1b9c9ef400fe4ded4c0854c0fcb142fb0a407a52 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 21 Jun 2026 23:14:39 +0200 Subject: [PATCH 30/64] Replace deprecated `CyclingButtonWidget` with `CycleButton` in `RenderService` --- .../ucutils/common/services/RenderService.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java index 2add00aa..36ba3963 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java @@ -6,6 +6,7 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import lombok.Getter; +import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.network.chat.Component; @@ -56,15 +57,13 @@ public void addCyclingButton(@NotNull LinearLayou BiConsumer onValueChange, @NotNull Function currentValue, int width) { -// FIXME CyclingButtonWidget cyclingButton = CyclingButtonWidget.builder(displayNameFunction) -// .values(values) -// .initially(currentValue.apply(configuration.getOptions())) -// .tooltip(CyclingButtonEntry::getTooltip) -// .build(name, (button, value) -> onValueChange.accept(configuration.getOptions(), value)); -// -// cyclingButton.setWidth(width); -// -// widget.addChild(cyclingButton); + CycleButton cycleButton = CycleButton.builder(displayNameFunction, currentValue.apply(configuration.getOptions())) + .withValues(values) + .withTooltip(CyclingButtonEntry::getTooltip) + .create(name, (_, value) -> onValueChange.accept(configuration.getOptions(), value)); + + cycleButton.setWidth(width); + widget.addChild(cycleButton); } public void addToggleButton(@NotNull LinearLayout widget, From 760352777f209bd148a8bf51d9ccfde9032e7288 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 24 Jun 2026 00:19:03 +0200 Subject: [PATCH 31/64] Add `BATTLEPASS_REWARD_PATTERN` to handle battle pass reward messages in economy logic --- .../rettichlp/ucutils/listener/impl/EconomyListener.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java index 6d98dc54..5383efab 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java @@ -67,6 +67,7 @@ public class EconomyListener implements IMessageReceiveListener { private static final Pattern BUSINESS_CASH_PATTERN = compile("^Kasse: (\\d+)\\$$"); private static final Pattern EXP_PATTERN = compile("(?[+-]\\d+) Exp!( \\(x(?\\d)\\))?"); private static final Pattern LOTTO_WIN_PATTERN = compile("^\\[Lotto] Du hast im Lotto gewonnen! \\((?\\d+)\\$\\)$"); + private static final Pattern BATTLEPASS_REWARD_PATTERN = compile("\\[Battle Pass] \\+(?\\d+)\\$ erhalten\\.$"); private static final Pattern MEDIC_DESPAWNED_PATTERN = compile("^Verdammt\\.\\.\\. mein Kopf dröhnt so\\.\\.\\.$"); private static final Pattern MEDIC_REVIVE_PATTERN = compile("^Du wirst von (?:\\[UC])?(?[a-zA-Z0-9_]+) wiederbelebt\\.$"); private static final Pattern REVIVE_ADMIN_PATTERN = compile("^Du wurdest von \\[UC](?[a-zA-Z0-9_]+) wiederbelebt\\.$"); @@ -315,6 +316,13 @@ public boolean onMessageReceive(Component text, String message) { return true; } + Matcher battlepassRewardMatcher = BATTLEPASS_REWARD_PATTERN.matcher(message); + if (battlepassRewardMatcher.find()) { + int amount = parseInt(battlepassRewardMatcher.group("amount")); + configuration.setMoneyBankAmount(configuration.getMoneyBankAmount() + amount); + return true; + } + Matcher medicDespawnedMatcher = MEDIC_DESPAWNED_PATTERN.matcher(message); if (medicDespawnedMatcher.find()) { configuration.setMoneyCashAmount(0); From 44a26029fb1b5b209824a9a0b7ee3d2210a734ab Mon Sep 17 00:00:00 2001 From: RettichLP Date: Wed, 24 Jun 2026 00:36:03 +0200 Subject: [PATCH 32/64] Refactor `PlayerMixin` to `LivingEntityMixin`, update shop location logic, and adjust item drop behavior --- ...layerMixin.java => LivingEntityMixin.java} | 21 +++++++++++-------- src/main/resources/ucutils.mixins.json | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) rename src/main/java/de/rettichlp/ucutils/mixin/{PlayerMixin.java => LivingEntityMixin.java} (67%) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/PlayerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java similarity index 67% rename from src/main/java/de/rettichlp/ucutils/mixin/PlayerMixin.java rename to src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java index 562fec44..53c56e3a 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/PlayerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java @@ -1,7 +1,7 @@ package de.rettichlp.ucutils.mixin; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; @@ -17,21 +17,25 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static net.minecraft.world.item.Items.GLASS_BOTTLE; -@Mixin(Player.class) -public abstract class PlayerMixin { +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin { @Unique private final static List SHOP_LOCATIONS = List.of( - new Vec3(45, 69, 200), - new Vec3(1049, 69, -189) + new Vec3(47, 69, 203), + new Vec3(1027, 69, 275) ); - @Inject(method = "drop", at = @At("HEAD"), cancellable = true) - private void ucutils$dropHead(ItemStack itemStack, boolean thrownFromHand, CallbackInfoReturnable cir) { + @Inject(method = "drop", at = @At("RETURN"), cancellable = true) + private void ucutils$dropHead(ItemStack itemStack, boolean randomly, boolean thrownFromHand, CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; } + if (cir.getReturnValue() == null) { + return; + } + if (player.getMainHandItem().is(GLASS_BOTTLE) && isNearShop()) { // cancel drop cir.setReturnValue(null); @@ -44,7 +48,6 @@ public abstract class PlayerMixin { @Unique private boolean isNearShop() { Vec3 position = player.position(); - return SHOP_LOCATIONS.stream() - .anyMatch(blockPos -> position.closerThan(blockPos, 10)); + return SHOP_LOCATIONS.stream().anyMatch(blockPos -> position.closerThan(blockPos, 3)); } } diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 86f758f5..00812859 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -21,8 +21,8 @@ "ClientPlayNetworkHandlerMixin", "EntityRendererMixin", "GuiMixin", + "LivingEntityMixin", "PauseScreenMixin", - "PlayerMixin", "PlayerTabOverlayMixin" ] } From 57415489180c75c9ada9fe3b43f3d76f7acf2c6f Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 21 Jun 2026 23:13:27 +0200 Subject: [PATCH 33/64] Refactor player info handling in `ClientPacketListenerMixin` to optimize display name updates and join/quit notifications --- .../mixin/ClientPlayNetworkHandlerMixin.java | 213 ++++++++---------- 1 file changed, 91 insertions(+), 122 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java index a299691c..d75acba5 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,27 +1,28 @@ package de.rettichlp.ucutils.mixin; -import com.mojang.authlib.GameProfile; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NonNull; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Collection; -import java.util.HashSet; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.UUID; import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.storage; import static java.awt.Color.WHITE; +import static java.lang.System.currentTimeMillis; +import static java.util.Optional.ofNullable; import static net.minecraft.ChatFormatting.BLUE; import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.GOLD; @@ -29,6 +30,8 @@ import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; import static net.minecraft.network.chat.Component.translatable; +import static net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER; +import static net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME; import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; @Mixin(ClientPacketListener.class) @@ -53,7 +56,7 @@ public abstract class ClientPlayNetworkHandlerMixin { .append(literal("]").withStyle(DARK_GRAY))); @Unique - private final Collection enrichedGameProfiles = new HashSet<>(); + private final Map displayNames = new HashMap<>(); @Inject(method = "handlePlayerInfoRemove", at = @At(value = "INVOKE", @@ -69,128 +72,94 @@ public abstract class ClientPlayNetworkHandlerMixin { } for (UUID uuid : packet.profileIds()) { - this.enrichedGameProfiles.stream() - .filter(egp -> egp.getProfile().id().equals(uuid)) - .findFirst() - .ifPresent(egp -> sendChangeNotification(egp, "ucutils.notification.player_quit")); + ofNullable(this.displayNames.get(uuid)).ifPresent(displayName -> sendChangeNotification(displayName, "ucutils.notification.player_quit")); } } -// @Inject(method = "", at = @At("HEAD")) -// private void ucutils$handlePlayerListActionHead(PlayerListS2CPacket.Action action, -// PlayerListS2CPacket.Entry receivedEntry, -// PlayerListEntry currentEntry, -// CallbackInfo ci) { -// if (!storage.isUnicaCity()) { -// return; -// } -// -// -// -// GameProfile profile = receivedEntry.profile(); -// UUID profileId = receivedEntry.profileId(); -// Component currentDisplayName = receivedEntry.displayName(); -// -// if (currentDisplayName == null) { -// return; -// } -// -// switch (action) { -// case ADD_PLAYER -> { -// if (!configuration.getOptions().notification().joinQuit()) { -// return; -// } -// -// EnrichedGameProfile enrichedGameProfile = new EnrichedGameProfile(profile, currentDisplayName, currentDisplayName); -// this.enrichedGameProfiles.removeIf(egp -> egp.getProfile().id().equals(profileId)); -// this.enrichedGameProfiles.add(enrichedGameProfile); -// -// // if the client joined the server few moments ago, hide notifications due to initial sync of player list -// if (currentTimeMillis() - storage.getJoinTimestamp() < 1000) { -// return; -// } -// -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_join"); -// } -// case UPDATE_DISPLAY_NAME -> { -// EnrichedGameProfile enrichedGameProfile = this.enrichedGameProfiles.stream() -// .filter(egp -> egp.getProfile().id().equals(profileId)) -// .findFirst() -// .orElseGet(() -> { -// EnrichedGameProfile egp = new EnrichedGameProfile(profile, currentDisplayName, currentDisplayName); -// this.enrichedGameProfiles.add(egp); -// return egp; -// }); -// -// Component previousDisplayName = enrichedGameProfile.getPreviousDisplayName(); -// -// // handle report change -// if (configuration.getOptions().notification().report()) { -// if (!previousDisplayName.contains(REPORT_PREFIX) && currentDisplayName.contains(REPORT_PREFIX)) { -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_report"); -// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); -// return; -// } -// -// if (previousDisplayName.contains(REPORT_PREFIX) && !currentDisplayName.contains(REPORT_PREFIX)) { -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_report"); -// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); -// return; -// } -// } -// -// // handle build mode change -// if (configuration.getOptions().notification().buildMode()) { -// if (!previousDisplayName.contains(BUILD_MODE_PREFIX) && currentDisplayName.contains(BUILD_MODE_PREFIX)) { -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_buildmode"); -// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); -// return; -// } -// -// if (previousDisplayName.contains(BUILD_MODE_PREFIX) && !currentDisplayName.contains(BUILD_MODE_PREFIX)) { -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_buildmode"); -// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); -// return; -// } -// } -// -// // handle admin-duty change -// if (configuration.getOptions().notification().aDuty()) { -// if (!previousDisplayName.contains(A_DUTY_PREFIX) && currentDisplayName.contains(A_DUTY_PREFIX)) { -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_enter_a_duty"); -// } -// -// if (previousDisplayName.contains(A_DUTY_PREFIX) && !currentDisplayName.contains(A_DUTY_PREFIX)) { -// sendChangeNotification(enrichedGameProfile, "ucutils.notification.player_leave_a_duty"); -// } -// } -// -// enrichedGameProfile.setPreviousDisplayName(currentDisplayName); -// } -// } -// } - - @Unique - private void sendChangeNotification(@NonNull EnrichedGameProfile enrichedGameProfile, String translationKey) { - Component currentDisplayName = enrichedGameProfile.getCurrentDisplayName(); - if (currentDisplayName.equals(empty())) { + @Inject(method = "handlePlayerInfoUpdate", at = @At("HEAD")) + private void ucutils$handlePlayerListActionHead(ClientboundPlayerInfoUpdatePacket packet, CallbackInfo ci) { + if (!storage.isUnicaCity()) { return; } - MutableComponent text = translatable(translationKey, currentDisplayName); - notificationService.sendNotification(text, WHITE, 5000); + EnumSet actions = packet.actions(); + List entries = packet.entries(); + + for (ClientboundPlayerInfoUpdatePacket.Entry entry : entries) { + UUID profileId = entry.profileId(); + Component displayName = entry.displayName(); + + if (displayName == null) { + continue; + } + + if (actions.contains(ADD_PLAYER)) { + if (!configuration.getOptions().notification().joinQuit()) { + return; + } + + // if the client joined the server few moments ago, hide notifications due to initial sync of player list + if (currentTimeMillis() - storage.getJoinTimestamp() < 1000) { + return; + } + + sendChangeNotification(displayName, "ucutils.notification.player_join"); + } else if (actions.contains(UPDATE_DISPLAY_NAME)) { + Component previousDisplayName = this.displayNames.get(profileId); + + // handle report change + if (configuration.getOptions().notification().report()) { + if (!previousDisplayName.contains(REPORT_PREFIX) && displayName.contains(REPORT_PREFIX)) { + sendChangeNotification(displayName, "ucutils.notification.player_enter_report"); + this.displayNames.put(profileId, displayName); + continue; + } + + if (previousDisplayName.contains(REPORT_PREFIX) && !displayName.contains(REPORT_PREFIX)) { + sendChangeNotification(displayName, "ucutils.notification.player_leave_report"); + this.displayNames.put(profileId, displayName); + continue; + } + } + + // handle build mode change + if (configuration.getOptions().notification().buildMode()) { + if (!previousDisplayName.contains(BUILD_MODE_PREFIX) && displayName.contains(BUILD_MODE_PREFIX)) { + sendChangeNotification(displayName, "ucutils.notification.player_enter_buildmode"); + this.displayNames.put(profileId, displayName); + continue; + } + + if (previousDisplayName.contains(BUILD_MODE_PREFIX) && !displayName.contains(BUILD_MODE_PREFIX)) { + sendChangeNotification(displayName, "ucutils.notification.player_leave_buildmode"); + this.displayNames.put(profileId, displayName); + continue; + } + } + + // handle admin-duty change + if (configuration.getOptions().notification().aDuty()) { + if (!previousDisplayName.contains(A_DUTY_PREFIX) && displayName.contains(A_DUTY_PREFIX)) { + sendChangeNotification(displayName, "ucutils.notification.player_enter_a_duty"); + this.displayNames.put(profileId, displayName); + continue; + } + + if (previousDisplayName.contains(A_DUTY_PREFIX) && !displayName.contains(A_DUTY_PREFIX)) { + sendChangeNotification(displayName, "ucutils.notification.player_leave_a_duty"); + this.displayNames.put(profileId, displayName); + continue; + } + } + } + + this.displayNames.put(profileId, displayName); + } } - @Data - @AllArgsConstructor - public static class EnrichedGameProfile { - - private final GameProfile profile; - private Component previousDisplayName; - private Component currentDisplayName; - - public boolean isTeamMember() { - return storage.getTeam().ucTeam().stream().anyMatch(teamMember -> teamMember.uuid().equals(this.profile.id())); - } + @Unique + private void sendChangeNotification(Component displayName, String translationKey) { + MutableComponent text = translatable(translationKey, displayName); + notificationService.sendNotification(text, WHITE, 5000); } } From a028a556f19c1ff98a4a065b28b3ae2f94900317 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 21 Jun 2026 23:13:55 +0200 Subject: [PATCH 34/64] Pathfinding: Add `@NonNull` annotation to `extractBackground` method in `WidgetOptionsScreen` to enforce parameter null-safety --- .../common/gui/screens/options/WidgetOptionsScreen.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java index f77aa9c5..3d13b7c3 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java @@ -13,6 +13,7 @@ import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; import static de.rettichlp.ucutils.UCUtils.renderService; import static net.minecraft.client.gui.layouts.LinearLayout.vertical; @@ -78,5 +79,5 @@ public void initBody() { // disable background rendering to see overlay better @Override - public void extractBackground(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {} + public void extractBackground(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {} } From bf64e461ff54ffeaf78fbfd8ea391c612d86d152 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 00:48:02 +0200 Subject: [PATCH 35/64] Refactor `ClientPlayNetworkHandlerMixin` to streamline player information updates and notifications handling --- .../mixin/ClientPlayNetworkHandlerMixin.java | 166 +++++++++--------- 1 file changed, 81 insertions(+), 85 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java index d75acba5..b4de10cc 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,27 +1,23 @@ package de.rettichlp.ucutils.mixin; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.PlayerInfo; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import org.jspecify.annotations.NonNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.storage; import static java.awt.Color.WHITE; -import static java.lang.System.currentTimeMillis; import static java.util.Optional.ofNullable; import static net.minecraft.ChatFormatting.BLUE; import static net.minecraft.ChatFormatting.DARK_GRAY; @@ -30,8 +26,6 @@ import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; import static net.minecraft.network.chat.Component.translatable; -import static net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER; -import static net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME; import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; @Mixin(ClientPacketListener.class) @@ -55,14 +49,13 @@ public abstract class ClientPlayNetworkHandlerMixin { .append(literal("R").withStyle(GOLD)) .append(literal("]").withStyle(DARK_GRAY))); - @Unique - private final Map displayNames = new HashMap<>(); - @Inject(method = "handlePlayerInfoRemove", at = @At(value = "INVOKE", - target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", + target = "Ljava/util/Set;remove(Ljava/lang/Object;)Z", shift = AFTER)) - private void ucutils$handlePlayerInfoRemoveInvoke(ClientboundPlayerInfoRemovePacket packet, CallbackInfo ci) { + private void ucutils$handlePlayerInfoRemoveInvoke(ClientboundPlayerInfoRemovePacket packet, + CallbackInfo ci, + @Local(name = "info") PlayerInfo info) { if (!storage.isUnicaCity()) { return; } @@ -71,94 +64,97 @@ public abstract class ClientPlayNetworkHandlerMixin { return; } - for (UUID uuid : packet.profileIds()) { - ofNullable(this.displayNames.get(uuid)).ifPresent(displayName -> sendChangeNotification(displayName, "ucutils.notification.player_quit")); + sendChangeNotification(ofNullable(info.getTabListDisplayName()).orElseGet(() -> literal(info.getProfile().name())), "ucutils.notification.player_quit"); + } + + @Inject(method = "handlePlayerInfoUpdate", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/gui/screens/social/PlayerSocialManager;addPlayer(Lnet/minecraft/client/multiplayer/PlayerInfo;)V", + shift = AFTER)) + private void ucutils$handlePlayerInfoUpdateInvoke(ClientboundPlayerInfoUpdatePacket packet, + CallbackInfo ci, + @Local(name = "entry") ClientboundPlayerInfoUpdatePacket.Entry entry, + @Local(name = "playerInfo") @NonNull PlayerInfo playerInfo) { + if (!storage.isUnicaCity()) { + return; } + + if (!configuration.getOptions().notification().joinQuit()) { + return; + } + + sendChangeNotification(ofNullable(entry.displayName()).orElseGet(() -> literal(playerInfo.getProfile().name())), "ucutils.notification.player_join"); } - @Inject(method = "handlePlayerInfoUpdate", at = @At("HEAD")) - private void ucutils$handlePlayerListActionHead(ClientboundPlayerInfoUpdatePacket packet, CallbackInfo ci) { + @Inject(method = "applyPlayerInfoUpdate", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/multiplayer/PlayerInfo;setTabListDisplayName(Lnet/minecraft/network/chat/Component;)V")) + private void ucutils$applyPlayerInfoUpdateInvoke(ClientboundPlayerInfoUpdatePacket.Action action, + ClientboundPlayerInfoUpdatePacket.Entry entry, + PlayerInfo info, + CallbackInfo ci) { if (!storage.isUnicaCity()) { return; } - EnumSet actions = packet.actions(); - List entries = packet.entries(); + if (!configuration.getOptions().notification().joinQuit()) { + return; + } + + Component previousDisplayName = info.getTabListDisplayName(); + Component currentDisplayName = entry.displayName(); + + if (previousDisplayName == null || currentDisplayName == null) { + return; + } + + // handle report change + if (configuration.getOptions().notification().report()) { + if (!previousDisplayName.contains(REPORT_PREFIX) && currentDisplayName.contains(REPORT_PREFIX)) { + sendChangeNotification(currentDisplayName, "ucutils.notification.player_enter_report"); + return; + } + + if (previousDisplayName.contains(REPORT_PREFIX) && !currentDisplayName.contains(REPORT_PREFIX)) { + sendChangeNotification(currentDisplayName, "ucutils.notification.player_leave_report"); + return; + } + } - for (ClientboundPlayerInfoUpdatePacket.Entry entry : entries) { - UUID profileId = entry.profileId(); - Component displayName = entry.displayName(); + // handle build mode change + if (configuration.getOptions().notification().buildMode()) { + if (!previousDisplayName.contains(BUILD_MODE_PREFIX) && currentDisplayName.contains(BUILD_MODE_PREFIX)) { + sendChangeNotification(currentDisplayName, "ucutils.notification.player_enter_buildmode"); + return; + } - if (displayName == null) { - continue; + if (previousDisplayName.contains(BUILD_MODE_PREFIX) && !currentDisplayName.contains(BUILD_MODE_PREFIX)) { + sendChangeNotification(currentDisplayName, "ucutils.notification.player_leave_buildmode"); + return; } + } - if (actions.contains(ADD_PLAYER)) { - if (!configuration.getOptions().notification().joinQuit()) { - return; - } - - // if the client joined the server few moments ago, hide notifications due to initial sync of player list - if (currentTimeMillis() - storage.getJoinTimestamp() < 1000) { - return; - } - - sendChangeNotification(displayName, "ucutils.notification.player_join"); - } else if (actions.contains(UPDATE_DISPLAY_NAME)) { - Component previousDisplayName = this.displayNames.get(profileId); - - // handle report change - if (configuration.getOptions().notification().report()) { - if (!previousDisplayName.contains(REPORT_PREFIX) && displayName.contains(REPORT_PREFIX)) { - sendChangeNotification(displayName, "ucutils.notification.player_enter_report"); - this.displayNames.put(profileId, displayName); - continue; - } - - if (previousDisplayName.contains(REPORT_PREFIX) && !displayName.contains(REPORT_PREFIX)) { - sendChangeNotification(displayName, "ucutils.notification.player_leave_report"); - this.displayNames.put(profileId, displayName); - continue; - } - } - - // handle build mode change - if (configuration.getOptions().notification().buildMode()) { - if (!previousDisplayName.contains(BUILD_MODE_PREFIX) && displayName.contains(BUILD_MODE_PREFIX)) { - sendChangeNotification(displayName, "ucutils.notification.player_enter_buildmode"); - this.displayNames.put(profileId, displayName); - continue; - } - - if (previousDisplayName.contains(BUILD_MODE_PREFIX) && !displayName.contains(BUILD_MODE_PREFIX)) { - sendChangeNotification(displayName, "ucutils.notification.player_leave_buildmode"); - this.displayNames.put(profileId, displayName); - continue; - } - } - - // handle admin-duty change - if (configuration.getOptions().notification().aDuty()) { - if (!previousDisplayName.contains(A_DUTY_PREFIX) && displayName.contains(A_DUTY_PREFIX)) { - sendChangeNotification(displayName, "ucutils.notification.player_enter_a_duty"); - this.displayNames.put(profileId, displayName); - continue; - } - - if (previousDisplayName.contains(A_DUTY_PREFIX) && !displayName.contains(A_DUTY_PREFIX)) { - sendChangeNotification(displayName, "ucutils.notification.player_leave_a_duty"); - this.displayNames.put(profileId, displayName); - continue; - } - } + // handle admin-duty change + if (configuration.getOptions().notification().aDuty()) { + if (!previousDisplayName.contains(A_DUTY_PREFIX) && currentDisplayName.contains(A_DUTY_PREFIX)) { + sendChangeNotification(currentDisplayName, "ucutils.notification.player_enter_a_duty"); + return; } - this.displayNames.put(profileId, displayName); + if (previousDisplayName.contains(A_DUTY_PREFIX) && !currentDisplayName.contains(A_DUTY_PREFIX)) { + sendChangeNotification(currentDisplayName, "ucutils.notification.player_leave_a_duty"); + return; + } } } @Unique - private void sendChangeNotification(Component displayName, String translationKey) { + private void sendChangeNotification(@NonNull Component displayName, String translationKey) { + // skip NPC names + if (displayName.getString().isEmpty()) { + return; + } + MutableComponent text = translatable(translationKey, displayName); notificationService.sendNotification(text, WHITE, 5000); } From 571a0e94e93b620816239f55da22386252ea7c9f Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 01:06:16 +0200 Subject: [PATCH 36/64] Enable `devauth` property for the run client task in Loom configuration --- build.gradle.kts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index d513d482..819c8fee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -91,3 +91,11 @@ publishing { // retrieving dependencies. } } + +loom { + runs { + named("client") { + property("devauth.enabled", "1") + } + } +} From 542a3660c261a5343674573f1169f8ed46676378 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 09:40:50 +0200 Subject: [PATCH 37/64] Refactor `AbstractContainerScreenMixin` to replace deprecated texture width and height constants with shadowed `imageWidth`and `imageHeight` fields --- .../mixin/AbstractContainerScreenMixin.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java index 06000a8b..fbe27837 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java @@ -12,7 +12,9 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.component.ItemLore; import org.jspecify.annotations.NonNull; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -27,8 +29,6 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static java.lang.Integer.parseInt; import static java.util.regex.Pattern.compile; -import static net.minecraft.client.gui.screens.inventory.BookEditScreen.BACKGROUND_TEXTURE_HEIGHT; -import static net.minecraft.client.gui.screens.inventory.BookEditScreen.BACKGROUND_TEXTURE_WIDTH; import static net.minecraft.core.component.DataComponents.LORE; import static net.minecraft.network.chat.Component.literal; import static net.minecraft.world.inventory.ContainerInput.PICKUP; @@ -36,6 +36,14 @@ @Mixin(AbstractContainerScreen.class) public abstract class AbstractContainerScreenMixin extends Screen implements MenuAccess { + @Shadow + @Final + protected int imageWidth; + + @Shadow + @Final + protected int imageHeight; + protected AbstractContainerScreenMixin(Component title) { super(title); } @@ -56,9 +64,9 @@ protected AbstractContainerScreenMixin(Component title) { int ingredient2StoredAmount = getStoredAmount(this, 13); int ingredient3StoredAmount = getStoredAmount(this, 15); - int x = (this.width - BACKGROUND_TEXTURE_WIDTH) / 2; - int y = (this.height - BACKGROUND_TEXTURE_HEIGHT) / 2; - int buttonX = x + BACKGROUND_TEXTURE_WIDTH + 2; + int x = (this.width - this.imageWidth) / 2; + int y = (this.height - this.imageHeight) / 2; + int buttonX = x + this.imageWidth + 2; // render button right to the inventory Button button = new Button.Builder(literal("➤"), _ -> commandService.sendCommand("f " + ingredient1StoredAmount + "x Wirkstoff | " + ingredient2StoredAmount + "x Trägerstoff | " + ingredient3StoredAmount + "x Zusatzstoff")) From 7bd011659719b223a9eeca2f985052f264e7fcc2 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 10:40:23 +0200 Subject: [PATCH 38/64] Add `EntityHitboxDebugRendererMixin` to customize player hitbox rendering based on faction colors --- .../ucutils/common/models/Faction.java | 26 +++--------- .../mixin/EntityHitboxDebugRendererMixin.java | 40 +++++++++++++++++++ src/main/resources/ucutils.mixins.json | 1 + 3 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 src/main/java/de/rettichlp/ucutils/mixin/EntityHitboxDebugRendererMixin.java diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Faction.java b/src/main/java/de/rettichlp/ucutils/common/models/Faction.java index ae5310c9..c746bda0 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Faction.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Faction.java @@ -3,16 +3,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; -import java.util.Optional; +import java.awt.Color; -import static java.util.Arrays.stream; import static net.minecraft.ChatFormatting.BLUE; import static net.minecraft.ChatFormatting.DARK_AQUA; import static net.minecraft.ChatFormatting.DARK_BLUE; -import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.DARK_PURPLE; import static net.minecraft.ChatFormatting.DARK_RED; import static net.minecraft.ChatFormatting.GOLD; @@ -20,15 +16,14 @@ import static net.minecraft.ChatFormatting.GREEN; import static net.minecraft.ChatFormatting.LIGHT_PURPLE; import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.WHITE; import static net.minecraft.ChatFormatting.YELLOW; -import static net.minecraft.network.chat.Component.empty; -import static net.minecraft.network.chat.Component.literal; @Getter @AllArgsConstructor public enum Faction { - NULL("", "", false, GRAY, ""), + NULL("", "", false, WHITE, ""), FBI("FBI", "fbi", false, DARK_BLUE, "✯"), POLIZEI("Polizei", "police", false, BLUE, "✯"), RETTUNGSDIENST("Rettungsdienst", "medic", false, DARK_RED, "✚"), @@ -49,18 +44,7 @@ public enum Faction { private final ChatFormatting color; private final String icon; - public Component getNameTagSuffix() { - return this != NULL - ? empty() - .append(literal("⌜").withStyle(DARK_GRAY)) - .append(literal(this.icon).withStyle(this.color)) - .append(literal("⌟").withStyle(DARK_GRAY)) - : empty(); - } - - public static @NotNull Optional fromDisplayName(String displayName) { - return stream(values()) - .filter(faction -> faction.getDisplayName().equals(displayName)) - .findFirst(); + public Color getAwtColor() { + return this.color.getColor() != null ? new Color(this.color.getColor()) : Color.WHITE; } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityHitboxDebugRendererMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityHitboxDebugRendererMixin.java new file mode 100644 index 00000000..107c6a28 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityHitboxDebugRendererMixin.java @@ -0,0 +1,40 @@ +package de.rettichlp.ucutils.mixin; + +import com.llamalad7.mixinextras.sugar.Local; +import de.rettichlp.ucutils.common.models.Faction; +import net.minecraft.client.renderer.debug.EntityHitboxDebugRenderer; +import net.minecraft.gizmos.GizmoStyle; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +import static de.rettichlp.ucutils.UCUtils.storage; +import static java.util.Optional.ofNullable; +import static net.minecraft.gizmos.GizmoStyle.stroke; + +@Mixin(EntityHitboxDebugRenderer.class) +public abstract class EntityHitboxDebugRendererMixin { + + @ModifyArg(method = "showHitboxes", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/gizmos/Gizmos;cuboid(Lnet/minecraft/world/phys/AABB;Lnet/minecraft/gizmos/GizmoStyle;)Lnet/minecraft/gizmos/GizmoProperties;", + ordinal = 0), + index = 1) + private GizmoStyle ucutils$showHitboxesInvoke(GizmoStyle style, + @Local(name = "entity", argsOnly = true) Entity entity, + @Local(name = "isServerEntity", argsOnly = true) boolean isServerEntity) { + if (!storage.isUnicaCity()) { + return style; + } + + if (!(entity instanceof Player player) || isServerEntity) { + return style; + } + + String playerName = player.getPlainTextName(); + Faction faction = ofNullable(storage.getPlayerFactionCache().get(playerName)).orElseGet(() -> storage.getFaction(playerName)); + return stroke(faction.getAwtColor().getRGB()); + } +} diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 00812859..192ff260 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -19,6 +19,7 @@ "ChatScreenMixin", "ClientPacketListenerMixin", "ClientPlayNetworkHandlerMixin", + "EntityHitboxDebugRendererMixin", "EntityRendererMixin", "GuiMixin", "LivingEntityMixin", From 420afccdb421fbad24c227d00720c5f60d6a3589 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 10:40:33 +0200 Subject: [PATCH 39/64] Enable `mixin.debug.export` property for the run client task in Loom configuration --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index 819c8fee..7b3ae468 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -96,6 +96,7 @@ loom { runs { named("client") { property("devauth.enabled", "1") + property("mixin.debug.export", "true") } } } From c0eada31d09c8dd9e0a241b7b4a54db3a6522bf2 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 10:51:14 +0200 Subject: [PATCH 40/64] Add player join delay check in `ClientPlayNetworkHandlerMixin` to skip notifications for recent logins --- .../ucutils/mixin/ClientPlayNetworkHandlerMixin.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java index b4de10cc..b6639744 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -16,6 +16,7 @@ import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.notificationService; +import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static java.awt.Color.WHITE; import static java.util.Optional.ofNullable; @@ -155,6 +156,11 @@ private void sendChangeNotification(@NonNull Component displayName, String trans return; } + // skip if player joined some seconds ago + if (player.tickCount < 5 * 20) { + return; + } + MutableComponent text = translatable(translationKey, displayName); notificationService.sendNotification(text, WHITE, 5000); } From a2dbfb242492fe1def6a27b714e29aed246161f9 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 10:54:19 +0200 Subject: [PATCH 41/64] Adjust hydration bar sync logic to start from the first minute instead of the third minute --- src/main/java/de/rettichlp/ucutils/UCUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index ac467c24..d851b382 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -74,8 +74,8 @@ public void onInitialize() { // show health for hydration bar sync synchronisedMinuteTimer.add(currentTick -> { - // every 3 minutes - if (currentTick % 3 != 0) { + // every 3 minutes starting from first (not third) minute + if ((currentTick + 2) % 3 != 0) { return; } From af8659f5d1d06745064c482a8d084407c239e9d0 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 11:08:31 +0200 Subject: [PATCH 42/64] Add version validation in `SyncService` to skip notifications for testing and pre versions --- .../java/de/rettichlp/ucutils/common/services/SyncService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java index 89d5b684..7f38b129 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java @@ -71,7 +71,7 @@ public void checkForUpdates() { String latestVersion = (String) latestRelease.get("version_number"); String currentVersion = utilService.getVersion(); - if (nonNull(latestVersion) && !currentVersion.equals(latestVersion)) { + if (nonNull(latestVersion) && !currentVersion.equals(latestVersion) && !currentVersion.equals("0.0.0") && latestVersion.matches("\\d\\.\\d\\.\\d")) { notificationService.sendNotification(empty() .append(translatable("ucutils.notification.info.new_version").withStyle(GRAY)) .append(literal(":").withStyle(DARK_GRAY)).append(" ") From 2ab3dc6ae174b664c1a1fecea603fe9b5df046ba Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 11:10:05 +0200 Subject: [PATCH 43/64] Refine version regex in `SyncService` to ensure strict semantic versioning matches --- .../java/de/rettichlp/ucutils/common/services/SyncService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java index 7f38b129..3a559025 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java @@ -71,7 +71,7 @@ public void checkForUpdates() { String latestVersion = (String) latestRelease.get("version_number"); String currentVersion = utilService.getVersion(); - if (nonNull(latestVersion) && !currentVersion.equals(latestVersion) && !currentVersion.equals("0.0.0") && latestVersion.matches("\\d\\.\\d\\.\\d")) { + if (nonNull(latestVersion) && !currentVersion.equals(latestVersion) && !currentVersion.equals("0.0.0") && latestVersion.matches("^\\d+\\.\\d+\\.\\d+$")) { notificationService.sendNotification(empty() .append(translatable("ucutils.notification.info.new_version").withStyle(GRAY)) .append(literal(":").withStyle(DARK_GRAY)).append(" ") From e98dc6ba1088ea7720e18abac75222540a4a484e Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 12:17:04 +0200 Subject: [PATCH 44/64] Add support for identifying and notifying the presence of summer treasure --- .../de/rettichlp/ucutils/common/Storage.java | 7 +++ .../mixin/ClientPacketListenerMixin.java | 57 ++++++++++++------- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index 02723e68..d2757907 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -102,6 +102,11 @@ public class Storage { @Setter private boolean premium = false; + @Getter + @Setter + @Nullable + private Vec3 summerTreasurePosition; + @Getter @Setter private TeamResponse team; @@ -151,6 +156,8 @@ public void print() { LOGGER.info("minecartEntityToHighlight: {}", this.minecartEntityToHighlight); // premium LOGGER.info("premium: {}", this.premium); + // summerTreasurePosition + LOGGER.info("summerTreasurePosition: {}", this.summerTreasurePosition); // team LOGGER.info("team: {}", this.team); // toggledChat diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java index 761ac30a..fb50c780 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java @@ -4,6 +4,7 @@ import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.npc.villager.Villager; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; @@ -18,6 +19,7 @@ import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.GRAY; import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; @@ -40,34 +42,51 @@ public class ClientPacketListenerMixin { } Entity entity = world.getEntity(packet.id()); - if (!(entity instanceof Villager villager) || !villager.hasCustomName()) { + if (entity == null) { return; } - String customNameString = requireNonNull(villager.getCustomName()).getString(); - Vec3 entityPos = villager.position(); + Vec3 entityPos = entity.position(); // already notified check - if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition())) { + if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition()) || entityPos.equals(storage.getSummerTreasurePosition())) { return; } - switch (customNameString) { - case "Dealer" -> { - storage.setBlackMarketPosition(entityPos); - player.sendSystemMessage(empty() - .append(literal("[").withStyle(DARK_GRAY)) - .append(literal("Dealer").withStyle(RED)) - .append(literal("] ").withStyle(DARK_GRAY)) - .append(literal("Der Dealer ist in der Nähe!").withStyle(GRAY))); + switch (entity) { + case Villager villager when villager.hasCustomName() -> { + String customNameString = requireNonNull(villager.getCustomName()).getString(); + switch (customNameString) { + case "Dealer" -> { + storage.setBlackMarketPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Dealer").withStyle(RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Dealer ist in der Nähe!").withStyle(GRAY))); + } + case "Schwarzmarkt" -> { + storage.setDealerPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Schwarzmarkt").withStyle(RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Schwarzmarkt ist in der Nähe!").withStyle(GRAY))); + } + } } - case "Schwarzmarkt" -> { - storage.setDealerPosition(entityPos); - player.sendSystemMessage(empty() - .append(literal("[").withStyle(DARK_GRAY)) - .append(literal("Schwarzmarkt").withStyle(RED)) - .append(literal("] ").withStyle(DARK_GRAY)) - .append(literal("Der Schwarzmarkt ist in der Nähe!").withStyle(GRAY))); + case ArmorStand armorStand when armorStand.hasCustomName() -> { + String customNameString = requireNonNull(armorStand.getCustomName()).getString(); + if (customNameString.equals("Sommerschatz")) { + storage.setSummerTreasurePosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Schatzsuche").withStyle(YELLOW)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Sommerschatz ist in der Nähe!").withStyle(GRAY))); + } + } + default -> { } } } From 119bc35ab1f6e57422a849dc8d03ea1bbf36d816 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 12:19:46 +0200 Subject: [PATCH 45/64] Add support for identifying and notifying the presence of blood dealer --- .../java/de/rettichlp/ucutils/common/Storage.java | 7 +++++++ .../ucutils/mixin/ClientPacketListenerMixin.java | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index d2757907..2fe5d298 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -63,6 +63,11 @@ public class Storage { @Nullable private Vec3 blackMarketPosition; + @Getter + @Setter + @Nullable + private Vec3 bloodDealerPosition; + @Getter @Setter @Nullable @@ -124,6 +129,8 @@ public void print() { LOGGER.info("activeShutdowns[{}]: {}", this.activeShutdowns.size(), this.activeShutdowns); // blackMarketPosition LOGGER.info("blackMarketPosition: {}", this.blackMarketPosition); + // bloodDealerPosition + LOGGER.info("bloodDealerPosition: {}", this.bloodDealerPosition); // captchaMapImage LOGGER.info("captchaMap: {}", this.captchaMap); // countdowns diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java index fb50c780..96e08b3c 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPacketListenerMixin.java @@ -17,6 +17,7 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static java.util.Objects.requireNonNull; import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_RED; import static net.minecraft.ChatFormatting.GRAY; import static net.minecraft.ChatFormatting.RED; import static net.minecraft.ChatFormatting.YELLOW; @@ -49,7 +50,7 @@ public class ClientPacketListenerMixin { Vec3 entityPos = entity.position(); // already notified check - if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition()) || entityPos.equals(storage.getSummerTreasurePosition())) { + if (entityPos.equals(storage.getDealerPosition()) || entityPos.equals(storage.getBlackMarketPosition()) || entityPos.equals(storage.getBloodDealerPosition()) || entityPos.equals(storage.getSummerTreasurePosition())) { return; } @@ -73,6 +74,14 @@ public class ClientPacketListenerMixin { .append(literal("] ").withStyle(DARK_GRAY)) .append(literal("Der Schwarzmarkt ist in der Nähe!").withStyle(GRAY))); } + case "Bluthändler" -> { + storage.setBloodDealerPosition(entityPos); + player.sendSystemMessage(empty() + .append(literal("[").withStyle(DARK_GRAY)) + .append(literal("Bluthändler").withStyle(DARK_RED)) + .append(literal("] ").withStyle(DARK_GRAY)) + .append(literal("Der Bluthändler ist in der Nähe!").withStyle(GRAY))); + } } } case ArmorStand armorStand when armorStand.hasCustomName() -> { From ba160bf711389d29c7a81b8a6f1a65555129ab82 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 14:26:56 +0200 Subject: [PATCH 46/64] Add `Company` enum and `StockMarketEntry` record to model company-related data and stock entry logic --- .../ucutils/common/models/Company.java | 36 +++++ .../common/models/StockMarketEntry.java | 125 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 src/main/java/de/rettichlp/ucutils/common/models/Company.java create mode 100644 src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Company.java b/src/main/java/de/rettichlp/ucutils/common/models/Company.java new file mode 100644 index 00000000..24cdc762 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/common/models/Company.java @@ -0,0 +1,36 @@ +package de.rettichlp.ucutils.common.models; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static java.util.Arrays.stream; + +@Getter +@AllArgsConstructor +public enum Company { + + SUPERMARKET("Supermarkt", 115), + GAS_STATION("Tankstelle", 150), + WALTER_S("Walter's", 90), + GUN_SHOP("Waffenladen", 265), + FISHERMAN("Fischer", 190), + BAR("Bar", 75), + DELICATESSEN("Feinkost", 85), + INSURANCE_COMPANY("Versicherung", 135), + SHISHA_BAR("Shishabar", 70), + CAR_DEALERSHIP("Fahrzeughändler", 165), + LUIGI_S("Luigi's", 80), + DISCO("Disco", 100), + PHARMACY("Apotheke", 215), + HANKY_S("Hanky's", 105); + + private final String displayName; + private final int minValue; + + public static Company fromDisplayName(String displayName) { + return stream(values()) + .filter(company -> company.getDisplayName().equals(displayName)) + .findFirst() + .orElse(null); + } +} diff --git a/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java b/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java new file mode 100644 index 00000000..71ea7eaf --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java @@ -0,0 +1,125 @@ +package de.rettichlp.ucutils.common.models; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ItemLore; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.Color; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static de.rettichlp.ucutils.common.models.Company.fromDisplayName; +import static java.awt.Color.BLUE; +import static java.lang.Double.parseDouble; +import static java.lang.Integer.parseInt; +import static net.minecraft.ChatFormatting.DARK_GREEN; +import static net.minecraft.ChatFormatting.DARK_RED; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; +import static net.minecraft.ChatFormatting.stripFormatting; +import static net.minecraft.core.component.DataComponents.LORE; + +public record StockMarketEntry(Company company, double price, double changeMoney, double changePercentage, int ownership, double buyPrice) { + + private static final Pattern PRICE_PATTERN = Pattern.compile("Kurs: (?\\d+\\.\\d+)\\$"); + private static final Pattern CHANGE_PATTERN = Pattern.compile("Änderung: (?-?\\d+\\.\\d+)\\$ \\((?-?\\d+\\.\\d+)%\\) [▼▲]"); + private static final Pattern OWNERSHIP_PATTERN = Pattern.compile("Besitz: (?\\d+)/\\d+"); + private static final Pattern BUY_PRICE_PATTERN = Pattern.compile("EK-Preis: (?-?\\d+\\.\\d+)\\$"); + + public @Nullable Color getColor() { + double diff = this.price - this.buyPrice; + + if (this.price <= this.company.getMinValue()) { + return BLUE; + } + + Integer colorValue; + + if (diff >= 75) { + colorValue = DARK_GREEN.getColor(); + } else if (diff >= 60) { + colorValue = GREEN.getColor(); + } else if (diff >= 45) { + colorValue = YELLOW.getColor(); + } else if (diff >= 30) { + colorValue = GOLD.getColor(); + } else if (diff >= 15) { + colorValue = RED.getColor(); + } else { + colorValue = DARK_RED.getColor(); + } + + if (colorValue == null) { + return null; + } + + return new Color(colorValue); + } + + public static @Nullable StockMarketEntry fromItemStack(@NotNull ItemStack itemStack) { + if (itemStack.getCustomName() == null) { + return null; + } + + String companyName = stripFormatting(itemStack.getCustomName().getString()); + + Company company = fromDisplayName(companyName); + if (company == null) { + return null; + } + + ItemLore loreComponent = itemStack.get(LORE); + if (loreComponent == null) { + return null; + } + + double price = 0; + double changeMoney = 0; + double changePercentage = 0; + int ownership = 0; + double buyPrice = 0; + + for (Component line : loreComponent.lines()) { + String textString = stripFormatting(line.getString()); + + Matcher priceMatcher = PRICE_PATTERN.matcher(textString); + if (priceMatcher.matches()) { + String priceMatcherPriceString = priceMatcher.group("price"); + price = parseDouble(priceMatcherPriceString); + continue; + } + + Matcher changeMatcher = CHANGE_PATTERN.matcher(textString); + if (changeMatcher.matches()) { + String changeMatcherMoneyString = changeMatcher.group("money"); + String changeMatcherPercentageString = changeMatcher.group("percentage"); + changeMoney = parseDouble(changeMatcherMoneyString); + changePercentage = parseDouble(changeMatcherPercentageString); + continue; + } + + Matcher ownershipMatcher = OWNERSHIP_PATTERN.matcher(textString); + if (ownershipMatcher.matches()) { + String ownershipMatcherOwnershipString = ownershipMatcher.group("ownership"); + ownership = parseInt(ownershipMatcherOwnershipString); + continue; + } + + Matcher buyPriceMatcher = BUY_PRICE_PATTERN.matcher(textString); + if (buyPriceMatcher.matches()) { + String buyPriceMatcherPriceString = buyPriceMatcher.group("price"); + buyPrice = parseDouble(buyPriceMatcherPriceString); + } + } + + if (price == 0 || ownership == 0 || buyPrice == 0) { + return null; + } + + return new StockMarketEntry(company, price, changeMoney, changePercentage, ownership, buyPrice); + } +} From 34e6b580f3d515ec1e2a0532aae87f13f36ac21d Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 14:29:05 +0200 Subject: [PATCH 47/64] Refactor `AbstractContainerScreenMixin` to extract medic storage button logic into a dedicated method --- .../mixin/AbstractContainerScreenMixin.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java index fbe27837..3e7b7da3 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java @@ -41,8 +41,10 @@ public abstract class AbstractContainerScreenMixin { - int ingredient1StoredAmount = getStoredAmount(this, 11); - int ingredient2StoredAmount = getStoredAmount(this, 13); - int ingredient3StoredAmount = getStoredAmount(this, 15); - - int x = (this.width - this.imageWidth) / 2; - int y = (this.height - this.imageHeight) / 2; - int buttonX = x + this.imageWidth + 2; - - // render button right to the inventory - Button button = new Button.Builder(literal("➤"), _ -> commandService.sendCommand("f " + ingredient1StoredAmount + "x Wirkstoff | " + ingredient2StoredAmount + "x Trägerstoff | " + ingredient3StoredAmount + "x Zusatzstoff")) - .bounds(buttonX, y, 20, 20) - .build(); - - if (ingredient1StoredAmount != 0 && ingredient2StoredAmount != 0 && ingredient3StoredAmount != 0) { - button.extractRenderState(graphics, mouseX, mouseY, a); - addRenderableWidget(button); - } - } + case "ʟᴀɢᴇʀ" -> extractMedicStorageButton(graphics, mouseX, mouseY, a); case "ᴄᴀʀᴄᴏɴᴛʀᴏʟ" -> { if (configuration.getOptions().car().fastLock() && !storage.isPremium()) { gameMode.handleContainerInput(getMenu().containerId, 0, 0, PICKUP, player); @@ -91,6 +75,23 @@ protected AbstractContainerScreenMixin(Component title) { } } + @Unique + private void extractMedicStorageButton(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + int ingredient1StoredAmount = getStoredAmount(this, 11); + int ingredient2StoredAmount = getStoredAmount(this, 13); + int ingredient3StoredAmount = getStoredAmount(this, 15); + + // render button right to the inventory + Button button = new Button.Builder(literal("➤"), _ -> commandService.sendCommand("f " + ingredient1StoredAmount + "x Wirkstoff | " + ingredient2StoredAmount + "x Trägerstoff | " + ingredient3StoredAmount + "x Zusatzstoff")) + .bounds(this.leftPos + this.imageWidth + 2, this.topPos, 20, 20) + .build(); + + if (ingredient1StoredAmount != 0 && ingredient2StoredAmount != 0 && ingredient3StoredAmount != 0) { + button.extractRenderState(graphics, mouseX, mouseY, a); + addRenderableWidget(button); + } + } + @Unique private int getStoredAmount(@NonNull MenuAccess containerScreen, int slotId) { Slot slot = containerScreen.getMenu().getSlot(slotId); From 44fb44592065e8d1f8e71ff21c641741d9f63314 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 14:32:33 +0200 Subject: [PATCH 48/64] Add stock market legend and highlight functionality to `AbstractContainerScreenMixin` --- .../mixin/AbstractContainerScreenMixin.java | 109 ++++++++++++++++++ .../resources/assets/ucutils/lang/de_de.json | 4 + .../resources/assets/ucutils/lang/en_gb.json | 4 + .../resources/assets/ucutils/lang/en_us.json | 4 + 4 files changed, 121 insertions(+) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java index 3e7b7da3..a8335575 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/AbstractContainerScreenMixin.java @@ -1,16 +1,22 @@ package de.rettichlp.ucutils.mixin; +import de.rettichlp.ucutils.common.models.StockMarketEntry; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MenuAccess; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; import net.minecraft.client.multiplayer.MultiPlayerGameMode; import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ItemLore; +import org.joml.Vector2i; +import org.joml.Vector2ic; import org.jspecify.annotations.NonNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -20,18 +26,36 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.awt.Color; +import java.util.List; +import java.util.Optional; import java.util.regex.Matcher; +import java.util.stream.Stream; import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.models.StockMarketEntry.fromItemStack; +import static java.awt.Color.BLUE; import static java.lang.Integer.parseInt; +import static java.util.Optional.ofNullable; import static java.util.regex.Pattern.compile; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.DARK_GREEN; +import static net.minecraft.ChatFormatting.DARK_RED; +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.ChatFormatting.RED; +import static net.minecraft.ChatFormatting.YELLOW; import static net.minecraft.core.component.DataComponents.LORE; +import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; import static net.minecraft.world.inventory.ContainerInput.PICKUP; +import static net.minecraft.world.item.Items.PLAYER_HEAD; @Mixin(AbstractContainerScreen.class) public abstract class AbstractContainerScreenMixin extends Screen implements MenuAccess { @@ -67,6 +91,10 @@ protected AbstractContainerScreenMixin(Component title) { gameMode.handleContainerInput(getMenu().containerId, 0, 0, PICKUP, player); } } + case "ᴀᴋᴛɪᴇɴᴍᴀʀᴋᴛ", "Handy-Aktien" -> { + extractStockMarketHighlight(graphics, mouseX, mouseY, a); + extractStockMarketLegend(graphics, mouseX, mouseY, a); + } default -> { if (commandService.isSuperUser()) { LOGGER.info("Screen opened: {}", title); @@ -92,6 +120,79 @@ private void extractMedicStorageButton(GuiGraphicsExtractor graphics, int mouseX } } + @Unique + private void extractStockMarketHighlight(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + for (Slot slot : player.containerMenu.slots) { + ItemStack itemStack = slot.getItem(); + + if (itemStack.isEmpty() || !itemStack.is(PLAYER_HEAD) || itemStack.getCustomName() == null) { + continue; + } + + Optional optionalColor = ofNullable(fromItemStack(itemStack)) + .map(StockMarketEntry::getColor); + + if (optionalColor.isEmpty()) { + continue; + } + + int x = this.leftPos + slot.x; + int y = this.topPos + slot.y; + + Color color = optionalColor.get(); + int argb = (0x80 << 24) | (color.getRGB() & 0x00FFFFFF); + graphics.fill(x, y, x + 16, y + 16, argb); + } + } + + @Unique + private void extractStockMarketLegend(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { + Stream legendComponents = Stream.of( + empty() + .append(translatable("ucutils.legend").withStyle(GRAY)) + .append(literal(":").withStyle(DARK_GRAY)), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.minimum_price").withColor(BLUE.getRGB())), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.price_difference").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal("Δp ≥ 75$").withStyle(DARK_GREEN)), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.price_difference").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal("Δp ≥ 60$").withStyle(GREEN)), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.price_difference").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal("Δp ≥ 45$").withStyle(YELLOW)), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.price_difference").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal("Δp ≥ 30$").withStyle(GOLD)), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.price_difference").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal("Δp ≥ 15$").withStyle(RED)), + empty() + .append(literal(" • ").withStyle(DARK_GRAY)) + .append(translatable("ucutils.price_difference").withStyle(GRAY)) + .append(literal(": ").withStyle(DARK_GRAY)) + .append(literal("Δp < 15$").withStyle(DARK_RED))); + + List legendClientTooltipComponents = legendComponents + .map(Component::getVisualOrderText) + .map(ClientTooltipComponent::create) + .toList(); + + graphics.tooltip(this.minecraft.font, legendClientTooltipComponents, this.leftPos + this.imageWidth + 2, this.topPos, new CompanyShareTooltipPositioner(), null); + } + @Unique private int getStoredAmount(@NonNull MenuAccess containerScreen, int slotId) { Slot slot = containerScreen.getMenu().getSlot(slotId); @@ -105,4 +206,12 @@ private int getStoredAmount(@NonNull MenuAccess containerScreen, int slotId) Matcher matcher = compile("\\d+").matcher(amountString); return matcher.find() ? parseInt(matcher.group()) : 0; } + + private static class CompanyShareTooltipPositioner implements ClientTooltipPositioner { + + @Override + public @NonNull Vector2ic positionTooltip(int screenWidth, int screenHeight, int x, int y, int tooltipWidth, int tooltipHeight) { + return new Vector2i(x, y).add(12, 8); + } + } } diff --git a/src/main/resources/assets/ucutils/lang/de_de.json b/src/main/resources/assets/ucutils/lang/de_de.json index e7f854d5..96b67370 100644 --- a/src/main/resources/assets/ucutils/lang/de_de.json +++ b/src/main/resources/assets/ucutils/lang/de_de.json @@ -1,4 +1,8 @@ { + "ucutils.legend": "Legende", + "ucutils.minimum_price": "Mindestpreis", + "ucutils.price_difference": "Preisdifferenz", + "ucutils.color.black": "Schwarz", "ucutils.color.dark_blue": "Dunkelblau", "ucutils.color.dark_green": "Dunkelgrün", diff --git a/src/main/resources/assets/ucutils/lang/en_gb.json b/src/main/resources/assets/ucutils/lang/en_gb.json index 94837d9d..69a3dbbe 100644 --- a/src/main/resources/assets/ucutils/lang/en_gb.json +++ b/src/main/resources/assets/ucutils/lang/en_gb.json @@ -1,4 +1,8 @@ { + "ucutils.legend": "Legend", + "ucutils.minimum_price": "Minimum price", + "ucutils.price_difference": "Price difference", + "ucutils.color.black": "Black", "ucutils.color.dark_blue": "Dark Blue", "ucutils.color.dark_green": "Dark Green", diff --git a/src/main/resources/assets/ucutils/lang/en_us.json b/src/main/resources/assets/ucutils/lang/en_us.json index 94837d9d..69a3dbbe 100644 --- a/src/main/resources/assets/ucutils/lang/en_us.json +++ b/src/main/resources/assets/ucutils/lang/en_us.json @@ -1,4 +1,8 @@ { + "ucutils.legend": "Legend", + "ucutils.minimum_price": "Minimum price", + "ucutils.price_difference": "Price difference", + "ucutils.color.black": "Black", "ucutils.color.dark_blue": "Dark Blue", "ucutils.color.dark_green": "Dark Green", From 273e647e999d750bd524f27f0aaa51f122c10a1b Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 14:39:17 +0200 Subject: [PATCH 49/64] Align ShutdownScreen components horizontally to center for improved UI consistency --- .../ucutils/common/gui/screens/ShutdownScreen.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java index f0f23f46..6a7b9658 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/ShutdownScreen.java @@ -3,6 +3,7 @@ import de.rettichlp.ucutils.common.models.ShutdownReason; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.StringWidget; +import net.minecraft.client.gui.layouts.LayoutSettings; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.network.chat.Component; @@ -31,20 +32,20 @@ public void initBody() { directionalLayoutWidget.newCellSettings().alignHorizontallyCenter(); directionalLayoutWidget.addChild(new StringWidget(empty() - .append(literal("Das Spiel wird beendet und der PC heruntergefahren,").withStyle(GRAY)), this.font), positioner -> positioner.paddingTop(16)); + .append(literal("Das Spiel wird beendet und der PC heruntergefahren,").withStyle(GRAY)), this.font), positioner -> positioner.alignHorizontallyCenter().paddingTop(16)); directionalLayoutWidget.addChild(new StringWidget(empty() - .append(literal("wenn folgende Bedingung erfüllt ist:").withStyle(GRAY)), this.font), positioner -> positioner.paddingBottom(16)); + .append(literal("wenn folgende Bedingung erfüllt ist:").withStyle(GRAY)), this.font), positioner -> positioner.alignHorizontallyCenter().paddingBottom(16)); - directionalLayoutWidget.addChild(new StringWidget(literal(this.shutdownReason.getConditionString()).withStyle(GOLD), this.font)); + directionalLayoutWidget.addChild(new StringWidget(literal(this.shutdownReason.getConditionString()).withStyle(GOLD), this.font), LayoutSettings::alignHorizontallyCenter); directionalLayoutWidget.addChild(new StringWidget(empty() - .append(literal("Wenn du dieses Fenster schließt,").withStyle(GRAY)), this.font), positioner -> positioner.paddingTop(16)); + .append(literal("Wenn du dieses Fenster schließt,").withStyle(GRAY)), this.font), positioner -> positioner.alignHorizontallyCenter().paddingTop(16)); directionalLayoutWidget.addChild(new StringWidget(empty() - .append(literal("wird das automatische Herunterfahren gestoppt.").withStyle(GRAY)), this.font), positioner -> positioner.paddingBottom(16)); + .append(literal("wird das automatische Herunterfahren gestoppt.").withStyle(GRAY)), this.font), positioner -> positioner.alignHorizontallyCenter().paddingBottom(16)); - directionalLayoutWidget.addChild(Button.builder(BUTTON_SHUTDOWN_ABORT_NAME, button -> onClose()).width(150).build()); + directionalLayoutWidget.addChild(Button.builder(BUTTON_SHUTDOWN_ABORT_NAME, button -> onClose()).width(150).build(), LayoutSettings::alignHorizontallyCenter); directionalLayoutWidget.visitWidgets(this::addRenderableWidget); } From 1568e880525742276dfc22c83f8f601e4916a776 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 20:58:58 +0000 Subject: [PATCH 50/64] Update Gradle to v9.6.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index eb84db68..a9db1155 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From c12816f09ee537d081fc6b578df6d382036d234b Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 23:29:06 +0200 Subject: [PATCH 51/64] Remove redundant ownership check in `StockMarketEntry` validation logic --- .../de/rettichlp/ucutils/common/models/StockMarketEntry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java b/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java index 71ea7eaf..b1b4ec61 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/StockMarketEntry.java @@ -116,7 +116,7 @@ public record StockMarketEntry(Company company, double price, double changeMoney } } - if (price == 0 || ownership == 0 || buyPrice == 0) { + if (price == 0 || buyPrice == 0) { return null; } From 3569ad4dc8cfb40efa57c032afa9f23d1710a3f4 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 23:31:38 +0200 Subject: [PATCH 52/64] Add error handling for ingredient parsing in `MedicListener` to prevent crashes --- .../listener/impl/faction/MedicListener.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java index c9d667d3..724e110d 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java @@ -14,6 +14,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; @@ -102,9 +103,19 @@ public boolean onMessageReceive(Component text, String message) { Matcher storageIngredientShareMatcher = STORAGE_INGREDIENT_SHARE_PATTERN.matcher(message); if (storageIngredientShareMatcher.find()) { String playerName = storageIngredientShareMatcher.group("playerName"); - int ingredient1 = parseInt(storageIngredientShareMatcher.group("ingredient1")); - int ingredient2 = parseInt(storageIngredientShareMatcher.group("ingredient2")); - int ingredient3 = parseInt(storageIngredientShareMatcher.group("ingredient3")); + + int ingredient1; + int ingredient2; + int ingredient3; + + try { + ingredient1 = parseInt(storageIngredientShareMatcher.group("ingredient1")); + ingredient2 = parseInt(storageIngredientShareMatcher.group("ingredient2")); + ingredient3 = parseInt(storageIngredientShareMatcher.group("ingredient3")); + } catch (NumberFormatException e) { + LOGGER.warn("Could not parse ingredient amounts from message: {}", message); + return true; + } player.sendSystemMessage(empty()); From be9f5a653ee4a037de5453bdca1579d131faa463 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 26 Jun 2026 23:35:01 +0200 Subject: [PATCH 53/64] Update `release.yml` to use dynamic branch reference for release creation --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fada23f2..881f1cee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,7 @@ jobs: tag: ${{ inputs.version }} run: | gh release create "$tag" \ - --target main \ + --target "${{ github.ref_name }}" \ --repo="$GITHUB_REPOSITORY" \ --title="$tag" \ --generate-notes \ From 5a743122232f7cb361a95f0188988bbc6c06a4ad Mon Sep 17 00:00:00 2001 From: RettichLP Date: Sun, 28 Jun 2026 18:36:24 +0200 Subject: [PATCH 54/64] Add delay before sending hydration command to ensure accurate afk status detection --- src/main/java/de/rettichlp/ucutils/UCUtils.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index d851b382..9ede6244 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -79,9 +79,12 @@ public void onInitialize() { return; } - if (storage.isUnicaCity() && !nameTagService.isAfk(player.getPlainTextName()) && configuration.getOptions().showHydration()) { - commandService.sendCommandWithHiddenOutput("health"); - } + // delayed to wait for afk message if in same minute + utilService.delayedAction(() -> { + if (storage.isUnicaCity() && !nameTagService.isAfk(player.getPlainTextName()) && configuration.getOptions().showHydration()) { + commandService.sendCommandWithHiddenOutput("health"); + } + }, 50); }); // asynchronously save every 10 minutes From a6520800cd2ddfde50e148a828c98b3a30f7aa55 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 30 Jun 2026 22:38:23 +0200 Subject: [PATCH 55/64] Add less annoying notification for maximum experience reached and suppress repeated messages --- .../listener/impl/EconomyListener.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java index 5383efab..a6644b23 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java @@ -26,7 +26,9 @@ import static java.util.Optional.ofNullable; import static java.util.regex.Pattern.compile; import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.ChatFormatting.RED; import static net.minecraft.ChatFormatting.UNDERLINE; +import static net.minecraft.network.chat.CommonComponents.SPACE; import static net.minecraft.network.chat.Component.literal; @UCUtilsListener @@ -65,7 +67,8 @@ public class EconomyListener implements IMessageReceiveListener { // other private static final Pattern BUSINESS_CASH_PATTERN = compile("^Kasse: (\\d+)\\$$"); - private static final Pattern EXP_PATTERN = compile("(?[+-]\\d+) Exp!( \\(x(?\\d)\\))?"); + private static final Pattern EXP_PATTERN = compile("(?[+-]\\d+) Exp!( \\(x(?\\d)\\))?$"); + private static final Pattern MAX_EXP_REACHED_PATTERN = compile("^Du hast die maximale Exp erreicht! Benutze /buylevel um ein Level aufzusteigen\\.$"); private static final Pattern LOTTO_WIN_PATTERN = compile("^\\[Lotto] Du hast im Lotto gewonnen! \\((?\\d+)\\$\\)$"); private static final Pattern BATTLEPASS_REWARD_PATTERN = compile("\\[Battle Pass] \\+(?\\d+)\\$ erhalten\\.$"); private static final Pattern MEDIC_DESPAWNED_PATTERN = compile("^Verdammt\\.\\.\\. mein Kopf dröhnt so\\.\\.\\.$"); @@ -74,6 +77,7 @@ public class EconomyListener implements IMessageReceiveListener { private static final Pattern BACK_IN_LIFE_PATTERN = compile("^\\[Friedhof] Du lebst nun wieder\\.$"); private long lastMedicReviveAction = 0; + private boolean maxExperiencePerLevelReached = false; @Override public boolean onMessageReceive(Component text, String message) { @@ -306,9 +310,28 @@ public boolean onMessageReceive(Component text, String message) { int multiplier = ofNullable(multiplierString).map(Integer::parseInt).orElse(1); configuration.addPredictedPayDayExp(amount * multiplier); + + if (this.maxExperiencePerLevelReached) { + MutableComponent modifiedMessage = text.copy() + .append(SPACE) + .append(literal("↑").withStyle(style -> style + .withHoverEvent(new HoverEvent.ShowText(literal("Du hast die maximale Exp erreicht! Benutze /buylevel um ein Level aufzusteigen.").withStyle(RED))) + .withColor(RED) + .withBold(true))); + player.sendSystemMessage(modifiedMessage); + return false; + } + return true; } + Matcher maxExpReachedMatcher = MAX_EXP_REACHED_PATTERN.matcher(message); + if (maxExpReachedMatcher.find()) { + boolean sendNotification = !this.maxExperiencePerLevelReached; + this.maxExperiencePerLevelReached = true; + return sendNotification; // notify only first time, after that hide message + } + Matcher lottoWinMatcher = LOTTO_WIN_PATTERN.matcher(message); if (lottoWinMatcher.find()) { int amount = parseInt(lottoWinMatcher.group("amount")); From 8c7a8ee87be34278f7efd3c7f3bce4e3a945b411 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 7 Jul 2026 13:00:12 +0200 Subject: [PATCH 56/64] Add integration for The Rettington Companion with support for notifications and dependency declaration --- build.gradle.kts | 3 + .../gui/widgets/NotificationWidget.java | 56 ----------------- .../TheRettingtonCompanionIntegration.java | 23 +++++++ .../common/services/NotificationService.java | 63 ++++--------------- .../de/rettichlp/ucutils/mixin/GuiMixin.java | 3 - src/main/resources/fabric.mod.json | 6 +- 6 files changed, 44 insertions(+), 110 deletions(-) delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java create mode 100644 src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java diff --git a/build.gradle.kts b/build.gradle.kts index 7b3ae468..12fab13b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,6 +14,7 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + mavenLocal() maven { name = "Terraformers" @@ -41,6 +42,8 @@ dependencies { include("org.atteo.classindex:classindex:3.13") implementation("org.atteo.classindex:classindex:3.13") annotationProcessor("org.atteo.classindex:classindex:3.13") + + compileOnly("de.rettichlp:the-rettington-companion:0.0.0") } tasks.processResources { diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java deleted file mode 100644 index 8b2b3d83..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/NotificationWidget.java +++ /dev/null @@ -1,56 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import lombok.RequiredArgsConstructor; -import net.minecraft.network.chat.Component; - -import java.awt.Color; -import java.time.LocalDateTime; - -import static java.time.LocalDateTime.now; -import static java.time.temporal.ChronoUnit.MILLIS; -import static net.minecraft.network.chat.Component.empty; - -@RequiredArgsConstructor -@UCUtilsWidget(registryName = "notification") -public class NotificationWidget extends AbstractUCUtilsProgressTextWidget { - - private final Component text; - private final Color borderColor; - private final LocalDateTime creationTime; - private final long durationInMillis; - - @Override - public Component text() { - return this.text; - } - - @Override - public double progress() { - return calculateProgress(this.creationTime, this.durationInMillis); - } - - @Override - public Color getBorderColor() { - return this.borderColor; - } - - @Override - public Component getDisplayName() { - return empty(); - } - - @Override - public Component getTooltip() { - return empty(); - } - - @Override - public boolean isVisible() { - return this.creationTime.plus(this.durationInMillis, MILLIS).isAfter(now()); - } - - public static class Configuration extends UCUtilsWidgetConfiguration {} -} diff --git a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java new file mode 100644 index 00000000..53e57aaf --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java @@ -0,0 +1,23 @@ +package de.rettichlp.ucutils.common.integrations; + +import de.rettichlp.therettingtoncompanion.TheRettingtonCompanionApi; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCWidget; +import de.rettichlp.therettingtoncompanion.models.Notification; + +import java.util.List; +import java.util.Set; + +import static de.rettichlp.ucutils.UCUtils.notificationService; + +public class TheRettingtonCompanionIntegration implements TheRettingtonCompanionApi { + + @Override + public Set getNotifications() { + return notificationService.getNotifications(); + } + + @Override + public List> getWidgets() { + return List.of(); + } +} diff --git a/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java b/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java index 941c93d6..7502f956 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java @@ -1,16 +1,12 @@ package de.rettichlp.ucutils.common.services; -import de.rettichlp.ucutils.common.gui.widgets.NotificationWidget; -import lombok.Data; +import de.rettichlp.therettingtoncompanion.models.Notification; +import lombok.Getter; import net.minecraft.network.chat.Component; import java.awt.Color; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.HashSet; +import java.util.Set; import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.utilService; @@ -19,17 +15,12 @@ import static java.awt.Color.GREEN; import static java.awt.Color.ORANGE; import static java.awt.Color.RED; -import static java.awt.Color.WHITE; -import static java.time.LocalDateTime.now; -import static java.util.Comparator.comparing; -import static java.util.Objects.hash; -import static java.util.Objects.nonNull; -import static java.util.UUID.randomUUID; -import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.time.Duration.ofMillis; public class NotificationService { - private final Collection notifications = new ArrayList<>(); + @Getter + private final Set notifications = new HashSet<>(); public void sendSuccessNotification(Component text) { sendNotification(text, GREEN, 5000); @@ -48,17 +39,13 @@ public void sendErrorNotification(Component text) { } public void sendNotification(Component text, Color color, long durationInMillis) { - Notification notification = new Notification(text, durationInMillis); - notification.setColor(color); - this.notifications.add(notification); - } + Notification notification = Notification.builder() + .text(text) + .color(color) + .displayDuration(ofMillis(durationInMillis)) + .build(); - public List getActiveNotifications() { - return this.notifications.stream() - .filter(Objects::nonNull) - .filter(notification -> now().isBefore(notification.getTimestamp().plus(notification.getDurationInMillis(), MILLISECONDS.toChronoUnit()))) - .sorted(comparing(Notification::getTimestamp)) - .toList(); + this.notifications.add(notification); } public void notificationSound(int repeating) { @@ -70,28 +57,4 @@ public void notificationSound(int repeating) { utilService.delayedAction(() -> NOTIFICATION.play(1, 2), i * 150L); } } - - @Data - public static class Notification { - - private final UUID id = randomUUID(); - private final Component text; - private final long durationInMillis; - private final LocalDateTime timestamp = now(); - private Color color = WHITE; - - @Override - public int hashCode() { - return hash(this.id, this.text, this.durationInMillis, this.timestamp, this.color); - } - - @Override - public boolean equals(Object o) { - return nonNull(o) && o instanceof Notification that && Objects.equals(this.id, that.id); - } - - public NotificationWidget toWidget() { - return new NotificationWidget(this.text, this.color, this.timestamp, this.durationInMillis); - } - } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java index 838ba2ba..b3b0d4b4 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java @@ -130,9 +130,6 @@ private void extractNotifications(GuiGraphicsExtractor graphics) { .filter(Countdown::isActive) .map(Countdown::toWidget) .toList()); - widgets.addAll(notificationService.getActiveNotifications().stream() - .map(NotificationService.Notification::toWidget) - .toList()); for (int i = 0; i < widgets.size(); i++) { AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 34783bd1..65458075 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -27,6 +27,9 @@ ], "modmenu": [ "de.rettichlp.ucutils.integrations.ModMenuIntegration" + ], + "the-rettington-companion": [ + "de.rettichlp.ucutils.common.integrations.TheRettingtonCompanionIntegration" ] }, "mixins": [ @@ -39,6 +42,7 @@ "fabric-api": "*" }, "recommends": { - "modmenu": ">=18.0.0" + "modmenu": ">=18.0.0", + "the-rettington-companion": ">=2.0.0" } } From 62825bb09333363ce84c589cdf0f20c58e00c3bc Mon Sep 17 00:00:00 2001 From: RettichLP Date: Tue, 7 Jul 2026 13:35:25 +0200 Subject: [PATCH 57/64] Remove UCUtils widget system and migrate relevant widgets to The Rettington Companion widget framework --- .../java/de/rettichlp/ucutils/UCUtils.java | 1 - .../common/gui/widgets/CarLockedWidget.java | 51 ++--- .../common/gui/widgets/DateTimeWidget.java | 32 --- .../common/gui/widgets/HearthWidget.java | 59 ------ .../common/gui/widgets/MoneyWidget.java | 24 ++- .../common/gui/widgets/PayDayWidget.java | 50 +++-- .../gui/widgets/ServiceCountWidget.java | 27 +-- .../alignment/AlignHorizontalWidget.java | 47 ----- .../alignment/AlignVerticalWidget.java | 54 ----- .../gui/widgets/alignment/AlignWidget.java | 24 --- .../AbstractUCUtilsProgressTextWidget.java | 38 ---- .../base/AbstractUCUtilsTextWidget.java | 57 ------ .../widgets/base/AbstractUCUtilsWidget.java | 187 ------------------ .../gui/widgets/base/IOptionWidget.java | 8 - .../gui/widgets/base/UCUtilsWidget.java | 19 -- .../base/UCUtilsWidgetConfiguration.java | 11 -- .../TheRettingtonCompanionIntegration.java | 11 +- .../common/services/RenderService.java | 44 ++--- 18 files changed, 110 insertions(+), 634 deletions(-) delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidget.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidgetConfiguration.java diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index 9ede6244..479a3564 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -107,7 +107,6 @@ public void onInitialize() { if (isUnicaCity) { client.execute(() -> { this.registry.registerListeners(); - renderService.initializeWidgets(); utilService.delayedAction(syncService::syncFactionSpecificData, 10000); utilService.delayedAction(syncService::checkForUpdates, 15000); }); diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java index c54a0c77..f2415dea 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CarLockedWidget.java @@ -1,32 +1,32 @@ package de.rettichlp.ucutils.common.gui.widgets; -import de.rettichlp.ucutils.common.gui.screens.components.CyclingButtonEntry; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.IOptionWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; +import de.rettichlp.therettingtoncompanion.gui.ICycleButtonValue; +import de.rettichlp.therettingtoncompanion.gui.options.list.TRCOptionsList; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCTextWidget; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.WidgetConfiguration; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; -import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.Tooltip; -import net.minecraft.client.gui.layouts.LayoutElement; import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.common.gui.widgets.CarLockedWidget.Style.MINIMALISTIC; +import static java.util.Arrays.asList; import static net.minecraft.ChatFormatting.DARK_GRAY; import static net.minecraft.ChatFormatting.GOLD; import static net.minecraft.ChatFormatting.GRAY; import static net.minecraft.ChatFormatting.GREEN; +import static net.minecraft.client.gui.components.Tooltip.create; import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; import static net.minecraft.network.chat.Component.translatable; -@UCUtilsWidget(registryName = "car_locked", defaultX = 110.0, defaultY = 4.0) -public class CarLockedWidget extends AbstractUCUtilsTextWidget { +public class CarLockedWidget extends AbstractTRCTextWidget { private static final Component WIDGETS_CAR_LOCKED_OPTIONS_NAME = translatable("ucutils.options.widgets.car_locked.options.name"); private static final Component WIDGETS_CAR_LOCKED_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.car_locked.options.tooltip"); @@ -43,7 +43,12 @@ public Component text() { } @Override - public Component getDisplayName() { + public @Nullable String getRegistryName() { + return "car_locked"; + } + + @Override + public Component getLabel() { return WIDGETS_CAR_LOCKED_OPTIONS_NAME; } @@ -52,9 +57,14 @@ public Component getTooltip() { return WIDGETS_CAR_LOCKED_OPTIONS_TOOLTIP; } + @Override + public void addOptions(@NonNull TRCOptionsList optionsList) { + optionsList.addCycleButton(WIDGETS_CAR_LOCKED_OPTIONS_STYLE_NAME, create(WIDGETS_CAR_LOCKED_OPTIONS_TOOLTIP), getWidgetConfiguration().getStyle(), asList(Style.values()), (_, value) -> getWidgetConfiguration().setStyle(value)); + } + @Getter @AllArgsConstructor - public enum Style implements CyclingButtonEntry { + public enum Style implements ICycleButtonValue { DEFAULT(translatable("ucutils.options.widgets.car_locked.options.style.value.default.name"), translatable("ucutils.options.widgets.car_locked.options.style.value.default.tooltip")), MINIMALISTIC(translatable("ucutils.options.widgets.car_locked.options.style.value.minimalistic.name"), translatable("ucutils.options.widgets.car_locked.options.style.value.minimalistic.tooltip")); @@ -63,28 +73,21 @@ public enum Style implements CyclingButtonEntry { private final Component tooltip; @Override - public @NotNull Component getDisplayName() { + public Component value() { return this.name; } + @Contract(value = " -> new", pure = true) @Override - public @NotNull Tooltip getTooltip() { - return Tooltip.create(this.tooltip); + public @NonNull Tooltip tooltip() { + return create(this.tooltip); } } @Data @EqualsAndHashCode(callSuper = false) - public static class Configuration extends UCUtilsWidgetConfiguration implements IOptionWidget { + public static class Configuration extends WidgetConfiguration { private Style style = MINIMALISTIC; - - @Override - public LayoutElement optionsWidget() { - return CycleButton.builder(Style::getDisplayName, this.style) - .withValues(Style.values()) - .withTooltip(Style::getTooltip) - .create(WIDGETS_CAR_LOCKED_OPTIONS_STYLE_NAME, (_, style) -> this.style = style); - } } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java deleted file mode 100644 index 4ed2de69..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/DateTimeWidget.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.network.chat.Component; - -import static de.rettichlp.ucutils.UCUtils.messageService; -import static java.time.LocalDateTime.now; -import static net.minecraft.network.chat.Component.literal; -import static net.minecraft.network.chat.Component.translatable; - -@UCUtilsWidget(registryName = "date_time", defaultX = 4.0, defaultY = 4.0) -public class DateTimeWidget extends AbstractUCUtilsTextWidget { - - @Override - public Component text() { - return literal(messageService.dateTimeToFriendlyString(now())); - } - - @Override - public Component getDisplayName() { - return translatable("ucutils.options.widgets.date_time.options.name"); - } - - @Override - public Component getTooltip() { - return translatable("ucutils.options.widgets.date_time.options.tooltip"); - } - - public static class Configuration extends UCUtilsWidgetConfiguration {} -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java deleted file mode 100644 index 206abaca..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/HearthWidget.java +++ /dev/null @@ -1,59 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import lombok.AllArgsConstructor; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; - -import java.awt.Color; - -import static java.lang.String.format; -import static net.minecraft.ChatFormatting.GRAY; -import static net.minecraft.ChatFormatting.RED; -import static net.minecraft.ChatFormatting.YELLOW; -import static net.minecraft.network.chat.Component.literal; -import static net.minecraft.network.chat.Component.translatable; - -@UCUtilsWidget(registryName = "hearth", defaultX = 4.0, defaultY = 4.0, defaultEnabled = false) -public class HearthWidget extends AbstractUCUtilsTextWidget { - - @Override - public Component text() { - LocalPlayer player = Minecraft.getInstance().player; - assert player != null; // cannot be null at this point - - float absorptionAmount = player.getAbsorptionAmount(); - float overallAmount = player.getHealth() + absorptionAmount; - - String overallAmountString = format("%.1f", overallAmount / 2).replaceAll(",0$", ""); - MutableComponent text = literal(overallAmountString).withStyle(absorptionAmount > 0 ? YELLOW : GRAY); - return text.append(literal("❤").withStyle(RED)); - } - - @Override - public Color getBorderColor() { - return new Color(0, 0, 0, 0); - } - - @Override - public Color getBackgroundColor() { - return new Color(0, 0, 0, 0); - } - - @Override - public Component getDisplayName() { - return translatable("ucutils.options.widgets.hearth.options.name"); - } - - @Override - public Component getTooltip() { - return translatable("ucutils.options.widgets.hearth.options.tooltip"); - } - - @AllArgsConstructor - public static class Configuration extends UCUtilsWidgetConfiguration {} -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java index a587149f..0d30d91d 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/MoneyWidget.java @@ -1,19 +1,21 @@ package de.rettichlp.ucutils.common.gui.widgets; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; +import de.rettichlp.therettingtoncompanion.gui.options.list.TRCOptionsList; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCTextWidget; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.WidgetConfiguration; import lombok.AllArgsConstructor; import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.common.services.RenderService.keyValue; import static java.awt.Color.RED; import static java.lang.System.currentTimeMillis; import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.translatable; -@UCUtilsWidget(registryName = "money", defaultX = 4.0, defaultY = 23.0) -public class MoneyWidget extends AbstractUCUtilsTextWidget { +public class MoneyWidget extends AbstractTRCTextWidget { @Override public Component text() { @@ -28,7 +30,12 @@ public Component text() { } @Override - public Component getDisplayName() { + public @Nullable String getRegistryName() { + return "money"; + } + + @Override + public Component getLabel() { return translatable("ucutils.options.widgets.money.options.name"); } @@ -37,6 +44,9 @@ public Component getTooltip() { return translatable("ucutils.options.widgets.money.options.tooltip"); } + @Override + public void addOptions(@NonNull TRCOptionsList optionsList) {} + @AllArgsConstructor - public static class Configuration extends UCUtilsWidgetConfiguration {} + public static class Configuration extends WidgetConfiguration {} } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java index dbc8ef29..a20775eb 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/PayDayWidget.java @@ -1,31 +1,30 @@ package de.rettichlp.ucutils.common.gui.widgets; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.IOptionWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; +import de.rettichlp.therettingtoncompanion.gui.options.list.TRCOptionsList; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCTextWidget; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.WidgetConfiguration; import lombok.Data; import lombok.EqualsAndHashCode; -import net.minecraft.client.gui.layouts.LayoutElement; -import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import java.awt.Color; +import static de.rettichlp.therettingtoncompanion.gui.OnOffCycleButtonEntry.ON; import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.renderService; +import static de.rettichlp.ucutils.common.services.RenderService.keyValue; import static java.awt.Color.RED; import static java.lang.String.valueOf; import static java.lang.System.currentTimeMillis; import static net.minecraft.ChatFormatting.DARK_GRAY; -import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; +import static net.minecraft.client.gui.components.Tooltip.create; import static net.minecraft.network.chat.Component.empty; import static net.minecraft.network.chat.Component.literal; import static net.minecraft.network.chat.Component.translatable; -@UCUtilsWidget(registryName = "payday", defaultX = 126.0, defaultY = 4.0) -public class PayDayWidget extends AbstractUCUtilsTextWidget { +public class PayDayWidget extends AbstractTRCTextWidget { private static final Component WIDGETS_PAYDAY_OPTIONS_NAME = translatable("ucutils.options.widgets.payday.options.name"); private static final Component WIDGETS_PAYDAY_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.payday.options.tooltip"); @@ -49,19 +48,20 @@ public Component text() { payDayInfoText.append(" ").append(keyValue("Exp", valueOf(configuration.getPredictedPayDayExp()))); } - return payDayInfoText; + Color fontColor = configuration.getMinutesSinceLastPayDay() >= 55 && configuration.getMoneyBankAmount() > 100000 && (currentTimeMillis() / 500 % 2 == 0) + ? RED + : getWidgetConfiguration().getColor(); + + return payDayInfoText.withColor(fontColor.getRGB()); } @Override - public Color getBackgroundColor() { - // with over 100.000$ on bank and PayDay within next 5 minutes, animate background - return configuration.getMinutesSinceLastPayDay() >= 55 && configuration.getMoneyBankAmount() > 100000 && (currentTimeMillis() / 500 % 2 == 0) - ? RED - : super.getBackgroundColor(); + public @Nullable String getRegistryName() { + return "payday"; } @Override - public Component getDisplayName() { + public Component getLabel() { return WIDGETS_PAYDAY_OPTIONS_NAME; } @@ -70,19 +70,17 @@ public Component getTooltip() { return WIDGETS_PAYDAY_OPTIONS_TOOLTIP; } + @Override + public void addOptions(@NonNull TRCOptionsList optionsList) { + optionsList.addToggleButton(WIDGETS_PAYDAY_OPTIONS_SALARY_NAME, create(WIDGETS_PAYDAY_OPTIONS_SALARY_TOOLTIP), getWidgetConfiguration().isShowSalary(), (_, value) -> getWidgetConfiguration().setShowSalary(value == ON)); + optionsList.addToggleButton(WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_NAME, create(WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_TOOLTIP), getWidgetConfiguration().isShowExperience(), (_, value) -> getWidgetConfiguration().setShowExperience(value == ON)); + } + @Data @EqualsAndHashCode(callSuper = false) - public static class Configuration extends UCUtilsWidgetConfiguration implements IOptionWidget { + public static class Configuration extends WidgetConfiguration { private boolean showSalary = true; private boolean showExperience = true; - - @Override - public LayoutElement optionsWidget() { - LinearLayout directionalLayoutWidget = horizontal().spacing(8); - renderService.addToggleButton(directionalLayoutWidget, WIDGETS_PAYDAY_OPTIONS_SALARY_NAME, WIDGETS_PAYDAY_OPTIONS_SALARY_TOOLTIP, (options, value) -> this.showSalary = value, options -> this.showSalary, 150); - renderService.addToggleButton(directionalLayoutWidget, WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_NAME, WIDGETS_PAYDAY_OPTIONS_EXPERIENCE_TOOLTIP, (options, value) -> this.showExperience = value, options -> this.showExperience, 150); - return directionalLayoutWidget; - } } } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java index bc3ce753..7424cefb 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java @@ -1,37 +1,37 @@ package de.rettichlp.ucutils.common.gui.widgets; +import de.rettichlp.therettingtoncompanion.gui.options.list.TRCOptionsList; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCTextWidget; +import de.rettichlp.therettingtoncompanion.gui.widgets.base.WidgetConfiguration; import de.rettichlp.ucutils.common.gui.screens.options.WidgetOptionsPositionScreen; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; - -import java.awt.Color; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.services.RenderService.keyValue; import static java.awt.Color.RED; import static java.lang.String.valueOf; import static net.minecraft.network.chat.Component.translatable; -@UCUtilsWidget(registryName = "service_count", defaultX = 4.0, defaultY = 42.0) -public class ServiceCountWidget extends AbstractUCUtilsTextWidget { +public class ServiceCountWidget extends AbstractTRCTextWidget { private static final Component WIDGETS_SERVICE_COUNT_OPTIONS_NAME = translatable("ucutils.options.widgets.service_count.options.name"); private static final Component WIDGETS_SERVICE_COUNT_OPTIONS_TOOLTIP = translatable("ucutils.options.widgets.service_count.options.tooltip"); @Override public Component text() { - return keyValue("Services", valueOf(storage.getActiveServices())); + return keyValue("Services", valueOf(storage.getActiveServices())).withColor(RED.getRGB()); } @Override - public Color getBorderColor() { - return RED; + public @Nullable String getRegistryName() { + return "service_count"; } @Override - public Component getDisplayName() { + public Component getLabel() { return WIDGETS_SERVICE_COUNT_OPTIONS_NAME; } @@ -40,11 +40,14 @@ public Component getTooltip() { return WIDGETS_SERVICE_COUNT_OPTIONS_TOOLTIP; } + @Override + public void addOptions(@NonNull TRCOptionsList optionsList) {} + @Override public boolean isVisible() { // visible if in the position options screen to allow positioning return storage.getActiveServices() > 0 || Minecraft.getInstance().screen instanceof WidgetOptionsPositionScreen; } - public static class Configuration extends UCUtilsWidgetConfiguration {} + public static class Configuration extends WidgetConfiguration {} } diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java deleted file mode 100644 index 654d46e4..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignHorizontalWidget.java +++ /dev/null @@ -1,47 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.alignment; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; - -import static net.minecraft.network.chat.Component.empty; - -public class AlignHorizontalWidget extends AlignWidget> { - - @Override - public void add(AbstractUCUtilsWidget entry) { - this.ucUtilsWidgets.add(entry); - } - - @Override - public Component getDisplayName() { - return empty(); - } - - @Override - public Component getTooltip() { - return empty(); - } - - @Override - public int getWidth() { - return this.ucUtilsWidgets.stream().map(AbstractUCUtilsWidget::getWidth).reduce(0, Integer::sum); - } - - @Override - public int getHeight() { - return this.ucUtilsWidgets.stream().map(AbstractUCUtilsWidget::getHeight).max(Integer::compareTo).orElse(0); - } - - @Override - public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, AbstractUCUtilsWidget.Alignment alignment) { - int xOffset = x; - - for (AbstractUCUtilsWidget ucUtilsWidget : this.ucUtilsWidgets) { - ucUtilsWidget.draw(graphics, xOffset, y, alignment); - xOffset += ucUtilsWidget.getWidth(); - } - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java deleted file mode 100644 index 4225a760..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignVerticalWidget.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.alignment; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; - -import static net.minecraft.network.chat.Component.empty; - -public class AlignVerticalWidget extends AlignWidget> { - - @Override - public void add(AbstractUCUtilsWidget entry) { - this.ucUtilsWidgets.add(entry); - } - - @Override - public Component getDisplayName() { - return empty(); - } - - @Override - public Component getTooltip() { - return empty(); - } - - @Override - public int getWidth() { - return this.ucUtilsWidgets.stream().map(AbstractUCUtilsWidget::getWidth).max(Integer::compareTo).orElse(0); - } - - @Override - public int getHeight() { - return this.ucUtilsWidgets.stream().map(AbstractUCUtilsWidget::getHeight).reduce(0, Integer::sum); - } - - @Override - public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, AbstractUCUtilsWidget.Alignment alignment) { - int yOffset = y; - - for (AbstractUCUtilsWidget ucUtilsWidget : this.ucUtilsWidgets) { - // apply alignment - int alignmentXModifier = switch (alignment) { - case LEFT -> 0; - case CENTER -> (getWidth() - ucUtilsWidget.getWidth()) / 2; - case RIGHT -> getWidth() - ucUtilsWidget.getWidth(); - }; - - ucUtilsWidget.draw(graphics, x + alignmentXModifier, yOffset, alignment); - yOffset += ucUtilsWidget.getHeight(); - } - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignWidget.java deleted file mode 100644 index af160c1f..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/alignment/AlignWidget.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.alignment; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; - -import java.util.ArrayList; -import java.util.Collection; - -public abstract class AlignWidget extends AbstractUCUtilsWidget { - - protected final Collection> ucUtilsWidgets = new ArrayList<>(); - protected boolean disableMargin = false; - - public abstract void add(T entry); - - public void clear() { - this.ucUtilsWidgets.clear(); - } - - public AlignWidget disableMargin() { - this.disableMargin = true; - return this; - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java deleted file mode 100644 index a0d66b6a..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsProgressTextWidget.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.base; - -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; - -import java.time.temporal.Temporal; - -import static de.rettichlp.ucutils.common.services.RenderService.TEXT_BOX_PADDING; -import static java.lang.Math.clamp; -import static java.time.Duration.between; -import static java.time.LocalDateTime.now; - -public abstract class AbstractUCUtilsProgressTextWidget extends AbstractUCUtilsTextWidget { - - @Override - public abstract Component text(); - - @Override - public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, Alignment alignment) { - graphics.fill(x, y, x + getWidth(), y + getHeight(), getBackgroundColor().getRGB()); - graphics.text(getFont(), text(), x + TEXT_BOX_PADDING, y + TEXT_BOX_PADDING, 0xFFFFFFFF, false); - - int maxProgressWidth = getWidth() - TEXT_BOX_PADDING * 2; - int xProgressStart = (int) (x + TEXT_BOX_PADDING + maxProgressWidth * progress()); - int xProgressEnd = x + getWidth() - TEXT_BOX_PADDING; - - graphics.horizontalLine(xProgressStart, xProgressEnd, y + getHeight() - 3, getBorderColor().getRGB()); - } - - public abstract double progress(); - - protected double calculateProgress(Temporal creationTime, long durationInMillis) { - long elapsedMillis = between(creationTime, now()).toMillis(); - double progress = (double) elapsedMillis / durationInMillis; - return clamp(progress, 0.0, 1.0); - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java deleted file mode 100644 index a8126125..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsTextWidget.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.base; - -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import org.jetbrains.annotations.NotNull; - -import java.awt.Color; - -import static de.rettichlp.ucutils.UCUtils.renderService; -import static de.rettichlp.ucutils.common.services.RenderService.TEXT_BOX_PADDING; -import static java.awt.Color.WHITE; -import static net.minecraft.ChatFormatting.DARK_GRAY; -import static net.minecraft.ChatFormatting.GRAY; -import static net.minecraft.network.chat.Component.empty; -import static net.minecraft.network.chat.Component.literal; - -public abstract class AbstractUCUtilsTextWidget extends AbstractUCUtilsWidget { - - public abstract Component text(); - - @Override - public int getWidth() { - int fontWidth = getFont().width(text()); - return fontWidth + 2 * TEXT_BOX_PADDING; - } - - @Override - public int getHeight() { - return getFont().lineHeight + 2 * TEXT_BOX_PADDING; - } - - @Override - public void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, Alignment alignment) { - graphics.fill(x, y, x + getWidth(), y + getHeight(), getBackgroundColor().getRGB()); - graphics.text(getFont(), text(), x + TEXT_BOX_PADDING, y + TEXT_BOX_PADDING, 0xFFFFFFFF, false); - } - - public Color getBorderColor() { - return WHITE; - } - - public Color getBackgroundColor() { - return renderService.getSecondaryColor(getBorderColor()); - } - - protected MutableComponent keyValue(String key, String value) { - return keyValue(key, literal(value)); - } - - protected MutableComponent keyValue(String key, Component value) { - return empty() - .append(literal(key).withStyle(GRAY)) - .append(literal(":").withStyle(DARK_GRAY)).append(" ") - .append(value); - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java deleted file mode 100644 index 9f7b2385..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/AbstractUCUtilsWidget.java +++ /dev/null @@ -1,187 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.base; - -import com.google.common.reflect.TypeToken; -import lombok.Getter; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Map; - -import static de.rettichlp.ucutils.UCUtils.LOGGER; -import static de.rettichlp.ucutils.UCUtils.api; -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.notificationService; -import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.CENTER; -import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.LEFT; -import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; -import static java.util.Objects.isNull; -import static java.util.Optional.ofNullable; -import static net.minecraft.network.chat.Component.translatable; - -@Getter -public abstract class AbstractUCUtilsWidget { - - private static final Type MAP_TYPE = new TypeToken>() {}.getType(); - - private final Font font = Minecraft.getInstance().font; - - private C widgetConfiguration; - - public abstract Component getDisplayName(); - - public abstract Component getTooltip(); - - public abstract int getWidth(); - - public abstract int getHeight(); - - public abstract void draw(@NotNull GuiGraphicsExtractor graphics, int x, int y, Alignment alignment); - - public void init() { - loadConfiguration(); - } - - public void draw(@NotNull GuiGraphicsExtractor graphics) { - if (!isVisible() || !this.widgetConfiguration.isEnabled() || Minecraft.getInstance().options.hideGui) { - return; - } - - int x = (int) this.widgetConfiguration.getX(); - int y = (int) this.widgetConfiguration.getY(); - draw(graphics, x, y, getAlignment()); - } - - public boolean isMouseOver(double mouseX, double mouseY) { - double x = this.widgetConfiguration.getX(); - double y = this.widgetConfiguration.getY(); - boolean mouseOverX = mouseX >= x && mouseX <= x + getWidth(); - boolean mouseOverY = mouseY >= y && mouseY <= y + getHeight(); - return mouseOverX && mouseOverY; - } - - public boolean isVisible() { - return true; - } - - public String getRegistryName() { - return ofNullable(this.getClass().getAnnotation(UCUtilsWidget.class)) - .map(UCUtilsWidget::registryName) - .orElseThrow(() -> new IllegalStateException("Widget class " + this.getClass().getName() + " has no registry name")); - } - - public void loadConfiguration() { - String registryName = getRegistryName(); - - if (isNull(registryName)) { - LOGGER.warn("Widget {} is missing registry name and therefore has no configuration", this.getClass().getName()); - return; - } - - Class widgetConfigurationClass = getConfigurationClass(); - // load configuration from the configuration file - not from the cache - Object widgetConfigurationObject = configuration.loadFromFile().getWidgets().get(registryName); - - if (isNull(widgetConfigurationObject)) { - LOGGER.info("No configuration found for widget {}, using default configuration", registryName); - - try { - this.widgetConfiguration = widgetConfigurationClass.getConstructor().newInstance(); - this.widgetConfiguration.setEnabled(getDefaultEnabled()); - this.widgetConfiguration.setX(getDefaultX()); - this.widgetConfiguration.setY(getDefaultY()); - } catch (Exception e) { - notificationService.sendErrorNotification(translatable("ucutils.notification.error.configuration")); - LOGGER.error("Could not load configuration for widget {}", registryName, e); - } - - return; - } - - String widgetConfigurationJson = api.getGson().toJson(widgetConfigurationObject); - - this.widgetConfiguration = api.getGson().fromJson(widgetConfigurationJson, widgetConfigurationClass); - } - - public void saveConfiguration() { - String registryName = getRegistryName(); - - if (isNull(registryName)) { - LOGGER.warn("Widget {} is missing registry name and therefore has no configuration", this.getClass().getName()); - return; - } - - C widgetConfiguration = getWidgetConfiguration(); - widgetConfiguration.setX(roundToNearestHalf(widgetConfiguration.getX())); - widgetConfiguration.setY(roundToNearestHalf(widgetConfiguration.getY())); - - String widgetConfigurationJson = api.getGson().toJson(widgetConfiguration); - Map widgetConfigurationMap = api.getGson().fromJson(widgetConfigurationJson, MAP_TYPE); - configuration.getWidgets().put(registryName, widgetConfigurationMap); - } - - private Alignment getAlignment() { - int scaledWidth = Minecraft.getInstance().getWindow().getGuiScaledWidth(); - int widthSegment = scaledWidth / 3; - - Alignment alignment; - - double x = this.widgetConfiguration.getX(); - if (x <= widthSegment) { - alignment = LEFT; - } else if (x <= widthSegment * 2) { - alignment = CENTER; - } else { - alignment = RIGHT; - } - - return alignment; - } - - private boolean getDefaultEnabled() { - return ofNullable(this.getClass().getAnnotation(UCUtilsWidget.class)) - .map(UCUtilsWidget::defaultEnabled) - .orElse(false); - } - - private double getDefaultX() { - return ofNullable(this.getClass().getAnnotation(UCUtilsWidget.class)) - .map(UCUtilsWidget::defaultX) - .orElse(0.0); - } - - private double getDefaultY() { - return ofNullable(this.getClass().getAnnotation(UCUtilsWidget.class)) - .map(UCUtilsWidget::defaultY) - .orElse(0.0); - } - - @SuppressWarnings("unchecked") - private Class getConfigurationClass() { - Type type = getClass().getGenericSuperclass(); - - if (type instanceof ParameterizedType) { - Type[] typeArgs = ((ParameterizedType) type).getActualTypeArguments(); - if (typeArgs.length > 0 && typeArgs[0] instanceof Class) { - return (Class) typeArgs[0]; - } - } - - throw new IllegalStateException("Widget class must be generic: AbstractUCUtilsWidget"); - } - - private double roundToNearestHalf(double value) { - return Math.round(value * 2) / 2.0; - } - - public enum Alignment { - - LEFT, - CENTER, - RIGHT - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java deleted file mode 100644 index 20ba27af..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/IOptionWidget.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.base; - -import net.minecraft.client.gui.layouts.LayoutElement; - -public interface IOptionWidget { - - LayoutElement optionsWidget(); -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidget.java deleted file mode 100644 index 1c7a84f6..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidget.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.base; - -import org.atteo.classindex.IndexAnnotated; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -@IndexAnnotated -public @interface UCUtilsWidget { - - String registryName(); - - double defaultX() default 0.0; - - double defaultY() default 0.0; - - boolean defaultEnabled() default true; -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidgetConfiguration.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidgetConfiguration.java deleted file mode 100644 index 01c100c7..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/base/UCUtilsWidgetConfiguration.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets.base; - -import lombok.Data; - -@Data -public class UCUtilsWidgetConfiguration { - - private boolean enabled; - private double x; - private double y; -} diff --git a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java index 53e57aaf..11084b4f 100644 --- a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java +++ b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java @@ -3,6 +3,10 @@ import de.rettichlp.therettingtoncompanion.TheRettingtonCompanionApi; import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCWidget; import de.rettichlp.therettingtoncompanion.models.Notification; +import de.rettichlp.ucutils.common.gui.widgets.CarLockedWidget; +import de.rettichlp.ucutils.common.gui.widgets.MoneyWidget; +import de.rettichlp.ucutils.common.gui.widgets.PayDayWidget; +import de.rettichlp.ucutils.common.gui.widgets.ServiceCountWidget; import java.util.List; import java.util.Set; @@ -18,6 +22,11 @@ public Set getNotifications() { @Override public List> getWidgets() { - return List.of(); + return List.of( + new CarLockedWidget(), + new MoneyWidget(), + new PayDayWidget(), + new ServiceCountWidget() + ); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java index 36ba3963..dcf57390 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java @@ -3,53 +3,32 @@ import de.rettichlp.ucutils.common.configuration.options.Options; import de.rettichlp.ucutils.common.gui.screens.components.CyclingButtonEntry; import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import lombok.Getter; import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; import java.awt.Color; -import java.util.LinkedHashSet; -import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.Function; import static de.rettichlp.ucutils.UCUtils.configuration; -import static java.util.Comparator.comparing; -import static java.util.stream.Collectors.toCollection; -import static java.util.stream.StreamSupport.stream; -import static org.atteo.classindex.ClassIndex.getAnnotated; +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; +import static net.minecraft.network.chat.Component.empty; +import static net.minecraft.network.chat.Component.literal; public class RenderService { public static final int TEXT_BOX_PADDING = 3; - @Getter - private LinkedHashSet> widgets = new LinkedHashSet<>(); - public Color getSecondaryColor(@NotNull Color color) { return new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 100); } - public void initializeWidgets() { - this.widgets = stream(getAnnotated(UCUtilsWidget.class).spliterator(), false) - .map(ucUtilsWidgetClass -> { - try { - return (AbstractUCUtilsWidget) ucUtilsWidgetClass.getConstructor().newInstance(); - } catch (Exception e) { - return null; - } - }) - .filter(Objects::nonNull) - .peek(AbstractUCUtilsWidget::init) - .sorted(comparing(AbstractUCUtilsWidget::getRegistryName)) - .collect(toCollection(LinkedHashSet::new)); - } - public void addCyclingButton(@NotNull LinearLayout widget, Component name, E[] values, @@ -79,4 +58,15 @@ public void addToggleButton(@NotNull LinearLayout widget, widget.addChild(toggleButton); } + + public static @NonNull MutableComponent keyValue(String key, String value) { + return keyValue(key, literal(value)); + } + + public static @NonNull MutableComponent keyValue(String key, Component value) { + return empty() + .append(literal(key).withStyle(GRAY)) + .append(literal(":").withStyle(DARK_GRAY)).append(" ") + .append(value); + } } From 515c8bed83ce6fb3906637b59d1a932636c4f635 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 9 Jul 2026 22:44:40 +0200 Subject: [PATCH 58/64] Migrate widget rendering and options system to The Rettington Companion framework --- .../screens/options/MainOptionsScreen.java | 3 +- .../options/NotificationOptionsScreen.java | 8 - .../options/WidgetOptionsPositionScreen.java | 151 ------------------ .../screens/options/WidgetOptionsScreen.java | 83 ---------- .../gui/widgets/ServiceCountWidget.java | 4 +- .../de/rettichlp/ucutils/mixin/GuiMixin.java | 43 ----- 6 files changed, 3 insertions(+), 289 deletions(-) delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java index 2262efad..823c1647 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/MainOptionsScreen.java @@ -1,5 +1,6 @@ package de.rettichlp.ucutils.common.gui.screens.options; +import de.rettichlp.therettingtoncompanion.gui.screens.TRCOptionsScreen; import de.rettichlp.ucutils.common.configuration.options.Options; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import net.minecraft.client.gui.components.Button; @@ -47,7 +48,7 @@ public void initBody() { directionalLayoutWidget2.addChild(Button.builder(TEXT_SOUNDS, button -> this.minecraft.setScreen(new SoundOptionsScreen(this))).width(150).build()); LinearLayout directionalLayoutWidget3 = directionalLayoutWidget.addChild(horizontal().spacing(8)); - directionalLayoutWidget3.addChild(Button.builder(TEXT_WIDGETS, button -> this.minecraft.setScreen(new WidgetOptionsScreen(this))).width(150).build()); + directionalLayoutWidget3.addChild(Button.builder(TEXT_WIDGETS, button -> this.minecraft.setScreen(new TRCOptionsScreen("widgets", this, true))).width(150).build()); directionalLayoutWidget3.addChild(Button.builder(TEXT_NOTIFICATIONS, button -> this.minecraft.setScreen(new NotificationOptionsScreen(this))).width(150).build()); LinearLayout directionalLayoutWidget4 = directionalLayoutWidget.addChild(horizontal().spacing(8)); diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java index b9fe79c8..b01c2a19 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/NotificationOptionsScreen.java @@ -3,14 +3,12 @@ import de.rettichlp.ucutils.common.configuration.options.NotificationOptions; import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.layouts.GridLayout; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.renderService; import static net.minecraft.network.chat.Component.translatable; public class NotificationOptionsScreen extends OptionsScreen { @@ -29,12 +27,6 @@ public NotificationOptionsScreen(Screen parent) { super(parent, TEXT_NOTIFICATIONS); } - @Override - public void doOnClose() { - renderService.getWidgets().forEach(AbstractUCUtilsWidget::saveConfiguration); - super.doOnClose(); - } - @Override public void initBody() { GridLayout gridLayout = this.layout.addToContents(new GridLayout()); diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java deleted file mode 100644 index 7436183e..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsPositionScreen.java +++ /dev/null @@ -1,151 +0,0 @@ -package de.rettichlp.ucutils.common.gui.screens.options; - -import com.mojang.blaze3d.platform.Window; -import de.rettichlp.ucutils.common.gui.screens.UCUtilsScreen; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.layouts.LinearLayout; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.input.MouseButtonEvent; -import net.minecraft.network.chat.Component; -import org.jspecify.annotations.NonNull; - -import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.renderService; -import static de.rettichlp.ucutils.common.services.RenderService.TEXT_BOX_PADDING; -import static java.awt.Color.BLACK; -import static java.awt.Color.BLUE; -import static java.awt.Color.GRAY; -import static java.awt.Color.GREEN; -import static java.util.Objects.isNull; -import static java.util.Objects.nonNull; -import static net.minecraft.client.gui.layouts.LinearLayout.horizontal; -import static net.minecraft.network.chat.CommonComponents.GUI_CANCEL; -import static net.minecraft.network.chat.CommonComponents.GUI_DONE; -import static net.minecraft.network.chat.Component.empty; -import static net.minecraft.network.chat.Component.literal; - -public class WidgetOptionsPositionScreen extends UCUtilsScreen { - - private AbstractUCUtilsWidget selectedWidget; - private double oldMouseX; - private double oldMouseY; - - public WidgetOptionsPositionScreen(Screen parent) { - super(empty(), empty(), parent, false); - } - - @Override - public void initBody() { - LinearLayout directionalLayoutWidget = this.layout.addToContents(horizontal().spacing(8), positioner -> positioner.paddingTop(this.minecraft.getWindow().getGuiScaledHeight() / 4)); - - directionalLayoutWidget.addChild(Button.builder(GUI_DONE, button -> { - renderService.getWidgets().forEach(AbstractUCUtilsWidget::saveConfiguration); - back(); - }).width(150).build()); - - directionalLayoutWidget.addChild(Button.builder(GUI_CANCEL, button -> { - // restore configurations from the configuration file - renderService.getWidgets().forEach(AbstractUCUtilsWidget::loadConfiguration); - back(); - }).width(150).build()); - - directionalLayoutWidget.visitWidgets(this::addRenderableWidget); - } - - @Override - public void doOnClose() { - configuration.saveToFile(); - } - - @Override - public void extractRenderState(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) { - super.extractRenderState(graphics, mouseX, mouseY, a); - - // draw center help lines - Window window = this.minecraft.getWindow(); - int scaledWidth = window.getGuiScaledWidth(); - int scaledHeight = window.getGuiScaledHeight(); - graphics.horizontalLine(0, scaledWidth, scaledHeight / 2 - 1, GREEN.getRGB()); - graphics.verticalLine(scaledWidth / 2 - 1, 0, scaledHeight, GREEN.getRGB()); - - // draw widget help lines - renderService.getWidgets().forEach(abstractUCUtilsWidget -> { - double xTopLeft = abstractUCUtilsWidget.getWidgetConfiguration().getX(); - double yTopLeft = abstractUCUtilsWidget.getWidgetConfiguration().getY(); - double xBottomRight = xTopLeft + abstractUCUtilsWidget.getWidth(); - double yBottomRight = yTopLeft + abstractUCUtilsWidget.getHeight(); - - graphics.horizontalLine(0, scaledWidth, (int) yTopLeft, GRAY.getRGB()); - graphics.horizontalLine(0, scaledWidth, (int) yBottomRight - 1, GRAY.getRGB()); - graphics.verticalLine((int) xTopLeft, 0, scaledHeight, GRAY.getRGB()); - graphics.verticalLine((int) xBottomRight - 1, 0, scaledHeight, GRAY.getRGB()); - }); - - if (isNull(this.selectedWidget)) { - return; - } - - int textX = mouseX + 10; - int textY = mouseY + 10; - - UCUtilsWidgetConfiguration widgetConfiguration = this.selectedWidget.getWidgetConfiguration(); - - // draw border around the selected widget - double x = widgetConfiguration.getX(); - double y = widgetConfiguration.getY(); - - // draw widget location text box - Component widgetLocationText = literal("X: " + x + " Y: " + y + " (W: " + this.selectedWidget.getWidth() + " H: " + this.selectedWidget.getHeight() + ")"); - graphics.fill(textX - TEXT_BOX_PADDING, textY - TEXT_BOX_PADDING, textX + this.font.width(widgetLocationText) + TEXT_BOX_PADDING, textY + this.font.lineHeight + TEXT_BOX_PADDING, renderService.getSecondaryColor(BLACK).getRGB()); - graphics.text(this.font, widgetLocationText, textX, textY, 0xFFFFFFFF, false); - - // draw widget center lines - double centerX = x + (this.selectedWidget.getWidth() / 2.0); - double centerY = y + (this.selectedWidget.getHeight() / 2.0); - graphics.horizontalLine(0, scaledWidth, (int) centerY, BLUE.getRGB()); - graphics.verticalLine((int) centerX, 0, scaledHeight, BLUE.getRGB()); - } - - // disable background rendering to see overlay better - @Override - public void extractBackground(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {} - - @Override - public void mouseMoved(double mouseX, double mouseY) { - super.mouseMoved(mouseX, mouseY); - - double deltaX = mouseX - this.oldMouseX; - double deltaY = mouseY - this.oldMouseY; - - this.oldMouseX = mouseX; - this.oldMouseY = mouseY; - - if (nonNull(this.selectedWidget)) { - UCUtilsWidgetConfiguration widgetConfiguration = this.selectedWidget.getWidgetConfiguration(); - widgetConfiguration.setX(widgetConfiguration.getX() + deltaX); - widgetConfiguration.setY(widgetConfiguration.getY() + deltaY); - } - } - - @Override - public boolean mouseClicked(@NonNull MouseButtonEvent event, boolean doubleClick) { - boolean mouseClicked = super.mouseClicked(event, doubleClick); - - renderService.getWidgets().stream() - .filter(abstractUCUtilsWidget -> abstractUCUtilsWidget.isMouseOver(event.x(), event.y())) - .findFirst() - .ifPresent(abstractUCUtilsWidget -> this.selectedWidget = abstractUCUtilsWidget); - - return mouseClicked; - } - - @Override - public boolean mouseReleased(@NonNull MouseButtonEvent event) { - boolean mouseReleased = super.mouseReleased(event); - this.selectedWidget = null; - return mouseReleased; - } -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java b/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java deleted file mode 100644 index 3d13b7c3..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/screens/options/WidgetOptionsScreen.java +++ /dev/null @@ -1,83 +0,0 @@ -package de.rettichlp.ucutils.common.gui.screens.options; - -import de.rettichlp.ucutils.common.gui.screens.OptionsScreen; -import de.rettichlp.ucutils.common.gui.screens.components.ToggleButtonWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.IOptionWidget; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.components.StringWidget; -import net.minecraft.client.gui.components.Tooltip; -import net.minecraft.client.gui.layouts.GridLayout; -import net.minecraft.client.gui.layouts.LayoutSettings; -import net.minecraft.client.gui.layouts.LinearLayout; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.network.chat.Component; -import org.jspecify.annotations.NonNull; - -import static de.rettichlp.ucutils.UCUtils.renderService; -import static net.minecraft.client.gui.layouts.LinearLayout.vertical; -import static net.minecraft.network.chat.Component.translatable; - -public class WidgetOptionsScreen extends OptionsScreen { - - private static final Component TEXT_WIDGETS = translatable("ucutils.options.text.widgets"); - private static final Component TEXT_GENERAL = translatable("ucutils.options.text.general"); - private static final Component TEXT_POSITION = translatable("ucutils.options.text.position"); - - public WidgetOptionsScreen(Screen parent) { - super(parent, TEXT_WIDGETS, false); - } - - @Override - public void doOnClose() { - renderService.getWidgets().forEach(AbstractUCUtilsWidget::saveConfiguration); - super.doOnClose(); - } - - @Override - public void initBody() { - LinearLayout directionalLayoutWidget = this.layout.addToContents(vertical().spacing(4)); - - // general - directionalLayoutWidget.addChild(new StringWidget(TEXT_GENERAL, this.font), LayoutSettings::alignHorizontallyCenter); - - directionalLayoutWidget.addChild(Button.builder(TEXT_POSITION, button -> this.minecraft.setScreen(new WidgetOptionsPositionScreen(this))).width(308).build()); - - // general - enable status - GridLayout gridLayout = this.layout.addToContents(new GridLayout()); - gridLayout.columnSpacing(8).rowSpacing(4); - GridLayout.RowHelper gridLayoutRowHelper = gridLayout.createRowHelper(2); - - renderService.getWidgets().forEach(abstractUCUtilsWidget -> { - Component displayName = abstractUCUtilsWidget.getDisplayName(); - ToggleButtonWidget toggleButton = new ToggleButtonWidget(displayName, value -> abstractUCUtilsWidget.getWidgetConfiguration().setEnabled(value), abstractUCUtilsWidget.getWidgetConfiguration().isEnabled()); - toggleButton.setTooltip(Tooltip.create(abstractUCUtilsWidget.getTooltip())); - gridLayoutRowHelper.addChild(toggleButton); - }); - - gridLayout.arrangeElements(); - gridLayout.visitWidgets(this::addRenderableWidget); - - // options section per widget - renderService.getWidgets().stream() - .filter(abstractUCUtilsWidget -> abstractUCUtilsWidget.getWidgetConfiguration() instanceof IOptionWidget) - .forEach(abstractUCUtilsWidget -> { - IOptionWidget iOptionWidget = (IOptionWidget) abstractUCUtilsWidget.getWidgetConfiguration(); - - // section title - Component text = abstractUCUtilsWidget.getDisplayName(); - directionalLayoutWidget.addChild(new StringWidget(text, this.font), positioner -> positioner.alignHorizontallyCenter().paddingTop(16)); - - // options widget - directionalLayoutWidget.addChild(iOptionWidget.optionsWidget(), LayoutSettings::alignHorizontallyCenter); - }); - - directionalLayoutWidget.visitWidgets(this::addRenderableWidget); - } - - // disable background rendering to see overlay better - - @Override - public void extractBackground(@NonNull GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a) {} -} diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java index 7424cefb..e372dd2d 100644 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java +++ b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/ServiceCountWidget.java @@ -3,8 +3,6 @@ import de.rettichlp.therettingtoncompanion.gui.options.list.TRCOptionsList; import de.rettichlp.therettingtoncompanion.gui.widgets.base.AbstractTRCTextWidget; import de.rettichlp.therettingtoncompanion.gui.widgets.base.WidgetConfiguration; -import de.rettichlp.ucutils.common.gui.screens.options.WidgetOptionsPositionScreen; -import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; @@ -46,7 +44,7 @@ public void addOptions(@NonNull TRCOptionsList optionsList) {} @Override public boolean isVisible() { // visible if in the position options screen to allow positioning - return storage.getActiveServices() > 0 || Minecraft.getInstance().screen instanceof WidgetOptionsPositionScreen; + return super.isVisible() && (storage.getActiveServices() > 0 || isWidgetPositionScreen()); } public static class Configuration extends WidgetConfiguration {} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java index b3b0d4b4..5dd01ca8 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/GuiMixin.java @@ -2,9 +2,6 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.platform.NativeImage; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; -import de.rettichlp.ucutils.common.models.Countdown; -import de.rettichlp.ucutils.common.services.NotificationService; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; @@ -24,17 +21,13 @@ import java.io.InputStream; import java.nio.file.Path; -import java.util.ArrayList; import static com.mojang.blaze3d.platform.NativeImage.read; import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.MOD_ID; import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.player; -import static de.rettichlp.ucutils.UCUtils.renderService; import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; import static java.lang.Math.ceil; import static java.lang.Math.clamp; import static java.lang.Math.round; @@ -86,21 +79,6 @@ public abstract class GuiMixin { graphics.blit(GUI_TEXTURED, CAPTCHA_IDENTIFIER, x, y, 0, 0, side, side, side, side); } - @Inject(method = "extractHotbarAndDecorations", at = @At("TAIL")) - private void ucutils$extractHotbarAndDecorationsTail(GuiGraphicsExtractor graphics, DeltaTracker deltaTracker, CallbackInfo ci) { - Profiler.get().popPush("notification"); - extractNotifications(graphics); - Profiler.get().pop(); - - if (!storage.isUnicaCity()) { - return; - } - - Profiler.get().popPush("widget"); - extractWidgets(graphics); - Profiler.get().pop(); - } - @Inject(method = "extractPlayerHealth", at = @At( value = "INVOKE", @@ -123,27 +101,6 @@ public abstract class GuiMixin { Profiler.get().pop(); } - @Unique - private void extractNotifications(GuiGraphicsExtractor graphics) { - ArrayList> widgets = new ArrayList<>(); - widgets.addAll(storage.getCountdowns().stream() - .filter(Countdown::isActive) - .map(Countdown::toWidget) - .toList()); - - for (int i = 0; i < widgets.size(); i++) { - AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); - int x = Minecraft.getInstance().getWindow().getGuiScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; - int y = 19 * i + 4; - abstractUCUtilsProgressTextWidget.draw(graphics, x, y, RIGHT); - } - } - - @Unique - private void extractWidgets(GuiGraphicsExtractor graphics) { - renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(graphics)); - } - @Unique private void renderHydration(GuiGraphicsExtractor context, int yLineAir, int xRight) { double maxHydrated = 20; From 88af10b72eada28c7917b4d9821f790b4d0ed5fb Mon Sep 17 00:00:00 2001 From: RettichLP Date: Thu, 9 Jul 2026 23:50:18 +0200 Subject: [PATCH 59/64] Migrate countdown logic to The Rettington Companion notification system and remove `CountdownWidget` implementation --- .../common/gui/widgets/CountdownWidget.java | 49 ------------------- .../TheRettingtonCompanionIntegration.java | 7 ++- .../ucutils/common/models/Countdown.java | 31 ++++++------ .../rettichlp/ucutils/common/models/Job.java | 2 +- .../common/services/NotificationService.java | 2 +- .../ucutils/listener/impl/PlayerListener.java | 2 +- .../listener/impl/faction/MedicListener.java | 6 +-- .../listener/impl/job/JobListener.java | 2 +- 8 files changed, 29 insertions(+), 72 deletions(-) delete mode 100644 src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java diff --git a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java b/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java deleted file mode 100644 index 15fb3e45..00000000 --- a/src/main/java/de/rettichlp/ucutils/common/gui/widgets/CountdownWidget.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.rettichlp.ucutils.common.gui.widgets; - -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidgetConfiguration; -import lombok.RequiredArgsConstructor; -import net.minecraft.network.chat.Component; - -import java.time.LocalDateTime; - -import static java.time.LocalDateTime.now; -import static java.time.temporal.ChronoUnit.MILLIS; -import static net.minecraft.network.chat.Component.empty; - -@RequiredArgsConstructor -@UCUtilsWidget(registryName = "countdown") -public class CountdownWidget extends AbstractUCUtilsProgressTextWidget { - - private final Component text; - private final LocalDateTime creationTime; - private final long durationInMillis; - - @Override - public Component text() { - return this.text; - } - - @Override - public double progress() { - return calculateProgress(this.creationTime, this.durationInMillis); - } - - @Override - public Component getDisplayName() { - return empty(); - } - - @Override - public Component getTooltip() { - return empty(); - } - - @Override - public boolean isVisible() { - return this.creationTime.plus(this.durationInMillis, MILLIS).isAfter(now()); - } - - public static class Configuration extends UCUtilsWidgetConfiguration {} -} diff --git a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java index 11084b4f..554ede54 100644 --- a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java +++ b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java @@ -7,17 +7,22 @@ import de.rettichlp.ucutils.common.gui.widgets.MoneyWidget; import de.rettichlp.ucutils.common.gui.widgets.PayDayWidget; import de.rettichlp.ucutils.common.gui.widgets.ServiceCountWidget; +import de.rettichlp.ucutils.common.models.Countdown; +import java.util.HashSet; import java.util.List; import java.util.Set; import static de.rettichlp.ucutils.UCUtils.notificationService; +import static de.rettichlp.ucutils.UCUtils.storage; public class TheRettingtonCompanionIntegration implements TheRettingtonCompanionApi { @Override public Set getNotifications() { - return notificationService.getNotifications(); + Set notifications = new HashSet<>(notificationService.getNotifications()); + notifications.addAll(storage.getCountdowns().stream().map(Countdown::toWidget).toList()); + return notifications; } @Override diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java index cb046b1f..b003f189 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java @@ -1,14 +1,14 @@ package de.rettichlp.ucutils.common.models; -import de.rettichlp.ucutils.common.gui.widgets.CountdownWidget; +import de.rettichlp.therettingtoncompanion.models.Notification; import lombok.Getter; import lombok.RequiredArgsConstructor; -import net.minecraft.network.chat.Component; import java.time.Duration; import java.time.LocalDateTime; import static de.rettichlp.ucutils.UCUtils.messageService; +import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.UCUtils.utilService; import static java.time.Duration.between; import static java.time.LocalDateTime.now; @@ -29,25 +29,26 @@ public Countdown(String title, Duration duration, Runnable runAfter) { this.title = title; this.duration = duration; - utilService.delayedAction(runAfter, this.duration.toMillis()); - } + storage.getCountdowns().add(this); - public boolean isActive() { - return getRemainingDuration().isPositive(); + utilService.delayedAction(runAfter, this.duration.toMillis()); } public Duration getRemainingDuration() { return between(now(), this.startTime.plus(this.duration)); } - public CountdownWidget toWidget() { - String millisToFriendlyString = messageService.millisToFriendlyString(getRemainingDuration().toMillis()); - - Component text = empty() - .append(literal(this.title).withStyle(WHITE)) - .append(literal(":").withStyle(GRAY)).append(" ") - .append(literal(millisToFriendlyString)); - - return new CountdownWidget(text, this.startTime, this.duration.toMillis()); + public Notification toWidget() { + return Notification.builder() + .componentSupplier(() -> { + String millisToFriendlyString = messageService.millisToFriendlyString(getRemainingDuration().toMillis()); + + return empty() + .append(literal(this.title).withStyle(WHITE)) + .append(literal(":").withStyle(GRAY)).append(" ") + .append(literal(millisToFriendlyString)); + }) + .displayDuration(this.duration) + .build(); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Job.java b/src/main/java/de/rettichlp/ucutils/common/models/Job.java index cb91cccf..f3873a57 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Job.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Job.java @@ -46,6 +46,6 @@ public enum Job { } public void startCountdown() { - storage.getCountdowns().add(new Countdown(this.displayName, this.cooldown, () -> {})); + new Countdown(this.displayName, this.cooldown, () -> {}); } } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java b/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java index 7502f956..fe78357b 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/NotificationService.java @@ -40,7 +40,7 @@ public void sendErrorNotification(Component text) { public void sendNotification(Component text, Color color, long durationInMillis) { Notification notification = Notification.builder() - .text(text) + .componentSupplier(() -> text) .color(color) .displayDuration(ofMillis(durationInMillis)) .build(); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java index 3dc86dde..9e5da05d 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java @@ -105,7 +105,7 @@ public boolean onMessageReceive(Component text, String message) { Matcher jailMatcher = JAIL_PATTERN.matcher(message); if (jailMatcher.find()) { int minutes = parseInt(jailMatcher.group("minutes")); - storage.getCountdowns().add(new Countdown("Gefängnis", ofMinutes(minutes))); + new Countdown("Gefängnis", ofMinutes(minutes)); return true; } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java index 724e110d..2cf21315 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MedicListener.java @@ -63,7 +63,7 @@ public class MedicListener implements IMessageReceiveListener { public boolean onMessageReceive(Component text, String message) { Matcher medicBandageMatcher = MEDIC_BANDAGE_PATTERN.matcher(message); if (medicBandageMatcher.find()) { - storage.getCountdowns().add(new Countdown("Bandage", MEDIC_BANDAGE_DURATION)); + new Countdown("Bandage", MEDIC_BANDAGE_DURATION); return true; } @@ -76,7 +76,7 @@ public boolean onMessageReceive(Component text, String message) { Matcher medicPillMatcher = MEDIC_PILL_PATTERN.matcher(message); if (medicPillMatcher.find()) { - storage.getCountdowns().add(new Countdown("Schmerzpille", MEDIC_PILL_DURATION)); + new Countdown("Schmerzpille", MEDIC_PILL_DURATION); return true; } @@ -96,7 +96,7 @@ public boolean onMessageReceive(Component text, String message) { Matcher laborTransportStartedMatcher = LABOR_TRANSPORT_STARTED_PATTERN.matcher(message); if (laborTransportStartedMatcher.find()) { Duration duration = ofMinutes(5).plusSeconds(56); // please don't ask why it is like this - storage.getCountdowns().add(new Countdown("Labor Transport", duration, () -> {})); + new Countdown("Labor Transport", duration, () -> {}); return true; } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java index 10eb76bd..d8de1912 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java @@ -68,7 +68,7 @@ public boolean onMessageReceive(Component text, String message) { : now.plusSeconds(seconds); storage.getCountdowns().removeIf(countdown -> countdown.getTitle().equals(MINING_BOOSTER_COUNTDOWN_TITLE)); - storage.getCountdowns().add(new Countdown(MINING_BOOSTER_COUNTDOWN_TITLE, between(now, this.miningBoosterExpirationTime), () -> {})); + new Countdown(MINING_BOOSTER_COUNTDOWN_TITLE, between(now, this.miningBoosterExpirationTime), () -> {}); return true; } From 0fa1cdb12d92f1e65a0b9c0568802c829c9202cb Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 10 Jul 2026 10:04:43 +0200 Subject: [PATCH 60/64] Broaden regex for Battle Pass reward pattern to support additional pass types --- .../de/rettichlp/ucutils/listener/impl/EconomyListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java index a6644b23..df192623 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyListener.java @@ -70,7 +70,7 @@ public class EconomyListener implements IMessageReceiveListener { private static final Pattern EXP_PATTERN = compile("(?[+-]\\d+) Exp!( \\(x(?\\d)\\))?$"); private static final Pattern MAX_EXP_REACHED_PATTERN = compile("^Du hast die maximale Exp erreicht! Benutze /buylevel um ein Level aufzusteigen\\.$"); private static final Pattern LOTTO_WIN_PATTERN = compile("^\\[Lotto] Du hast im Lotto gewonnen! \\((?\\d+)\\$\\)$"); - private static final Pattern BATTLEPASS_REWARD_PATTERN = compile("\\[Battle Pass] \\+(?\\d+)\\$ erhalten\\.$"); + private static final Pattern BATTLEPASS_REWARD_PATTERN = compile("\\[.+ Pass] \\+(?\\d+)\\$ erhalten\\.$"); private static final Pattern MEDIC_DESPAWNED_PATTERN = compile("^Verdammt\\.\\.\\. mein Kopf dröhnt so\\.\\.\\.$"); private static final Pattern MEDIC_REVIVE_PATTERN = compile("^Du wirst von (?:\\[UC])?(?[a-zA-Z0-9_]+) wiederbelebt\\.$"); private static final Pattern REVIVE_ADMIN_PATTERN = compile("^Du wurdest von \\[UC](?[a-zA-Z0-9_]+) wiederbelebt\\.$"); From 4057aa5144db1d760e151c7fb0d7dcf848f27abf Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 10 Jul 2026 10:08:01 +0200 Subject: [PATCH 61/64] Update LivingEntityMixin to adjust injection timing and fix item condition check --- .../java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java index 53c56e3a..84b675bd 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java @@ -26,7 +26,7 @@ public abstract class LivingEntityMixin { new Vec3(1027, 69, 275) ); - @Inject(method = "drop", at = @At("RETURN"), cancellable = true) + @Inject(method = "drop", at = @At("HEAD"), cancellable = true) private void ucutils$dropHead(ItemStack itemStack, boolean randomly, boolean thrownFromHand, CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; @@ -36,7 +36,7 @@ public abstract class LivingEntityMixin { return; } - if (player.getMainHandItem().is(GLASS_BOTTLE) && isNearShop()) { + if (itemStack.is(GLASS_BOTTLE) && isNearShop()) { // cancel drop cir.setReturnValue(null); From 493d6d0526ee7926b8915236dc09c3a962afdc17 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 10 Jul 2026 11:01:58 +0200 Subject: [PATCH 62/64] Refactor LivingEntityMixin to LocalPlayerMixin and update drop method logic --- ...EntityMixin.java => LocalPlayerMixin.java} | 24 +++++++++++-------- src/main/resources/ucutils.mixins.json | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) rename src/main/java/de/rettichlp/ucutils/mixin/{LivingEntityMixin.java => LocalPlayerMixin.java} (66%) diff --git a/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/LocalPlayerMixin.java similarity index 66% rename from src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java rename to src/main/java/de/rettichlp/ucutils/mixin/LocalPlayerMixin.java index 84b675bd..b569f8f3 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/LocalPlayerMixin.java @@ -1,7 +1,9 @@ package de.rettichlp.ucutils.mixin; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.item.ItemEntity; +import com.mojang.authlib.GameProfile; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; @@ -17,8 +19,8 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static net.minecraft.world.item.Items.GLASS_BOTTLE; -@Mixin(LivingEntity.class) -public abstract class LivingEntityMixin { +@Mixin(LocalPlayer.class) +public class LocalPlayerMixin extends AbstractClientPlayer { @Unique private final static List SHOP_LOCATIONS = List.of( @@ -26,19 +28,21 @@ public abstract class LivingEntityMixin { new Vec3(1027, 69, 275) ); + public LocalPlayerMixin(ClientLevel level, GameProfile gameProfile) { + super(level, gameProfile); + } + @Inject(method = "drop", at = @At("HEAD"), cancellable = true) - private void ucutils$dropHead(ItemStack itemStack, boolean randomly, boolean thrownFromHand, CallbackInfoReturnable cir) { + private void ucutils$dropHead(boolean all, CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { return; } - if (cir.getReturnValue() == null) { - return; - } + ItemStack selectedItem = getInventory().getSelectedItem(); - if (itemStack.is(GLASS_BOTTLE) && isNearShop()) { + if (selectedItem.is(GLASS_BOTTLE) && isNearShop()) { // cancel drop - cir.setReturnValue(null); + cir.cancel(); // execute command commandService.sendCommand("sell pfand"); diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 192ff260..c3bc0cb1 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -22,7 +22,7 @@ "EntityHitboxDebugRendererMixin", "EntityRendererMixin", "GuiMixin", - "LivingEntityMixin", + "LocalPlayerMixin", "PauseScreenMixin", "PlayerTabOverlayMixin" ] From 88188a04f94e21686119cea599a23e40ae073c99 Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 10 Jul 2026 11:51:46 +0200 Subject: [PATCH 63/64] Refactor countdown logic to directly create notifications for The Rettington Companion integration --- .../TheRettingtonCompanionIntegration.java | 7 +----- .../ucutils/common/models/Countdown.java | 23 +++++++++---------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java index 554ede54..11084b4f 100644 --- a/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java +++ b/src/main/java/de/rettichlp/ucutils/common/integrations/TheRettingtonCompanionIntegration.java @@ -7,22 +7,17 @@ import de.rettichlp.ucutils.common.gui.widgets.MoneyWidget; import de.rettichlp.ucutils.common.gui.widgets.PayDayWidget; import de.rettichlp.ucutils.common.gui.widgets.ServiceCountWidget; -import de.rettichlp.ucutils.common.models.Countdown; -import java.util.HashSet; import java.util.List; import java.util.Set; import static de.rettichlp.ucutils.UCUtils.notificationService; -import static de.rettichlp.ucutils.UCUtils.storage; public class TheRettingtonCompanionIntegration implements TheRettingtonCompanionApi { @Override public Set getNotifications() { - Set notifications = new HashSet<>(notificationService.getNotifications()); - notifications.addAll(storage.getCountdowns().stream().map(Countdown::toWidget).toList()); - return notifications; + return notificationService.getNotifications(); } @Override diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java index b003f189..5959e824 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java @@ -8,6 +8,7 @@ import java.time.LocalDateTime; import static de.rettichlp.ucutils.UCUtils.messageService; +import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.UCUtils.utilService; import static java.time.Duration.between; @@ -29,17 +30,7 @@ public Countdown(String title, Duration duration, Runnable runAfter) { this.title = title; this.duration = duration; - storage.getCountdowns().add(this); - - utilService.delayedAction(runAfter, this.duration.toMillis()); - } - - public Duration getRemainingDuration() { - return between(now(), this.startTime.plus(this.duration)); - } - - public Notification toWidget() { - return Notification.builder() + Notification countdownNotification = Notification.builder() .componentSupplier(() -> { String millisToFriendlyString = messageService.millisToFriendlyString(getRemainingDuration().toMillis()); @@ -48,7 +39,15 @@ public Notification toWidget() { .append(literal(":").withStyle(GRAY)).append(" ") .append(literal(millisToFriendlyString)); }) - .displayDuration(this.duration) + .displayDuration(duration) .build(); + + storage.getCountdowns().add(this); + notificationService.getNotifications().add(countdownNotification); + utilService.delayedAction(runAfter, this.duration.toMillis()); + } + + public Duration getRemainingDuration() { + return between(now(), this.startTime.plus(this.duration)); } } From 091e1e9710cad9ac1977817c63b7aa5eea4c887d Mon Sep 17 00:00:00 2001 From: RettichLP Date: Fri, 10 Jul 2026 23:17:18 +0200 Subject: [PATCH 64/64] Add Modrinth repository and update The Rettington Companion dependency to version 2.0.0 --- build.gradle.kts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 12fab13b..c716f105 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,12 +14,17 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. - mavenLocal() + mavenCentral() maven { name = "Terraformers" url = uri("https://maven.terraformersmc.com/") } + + maven { + name = "Modrinth" + url = uri("https://api.modrinth.com/maven") + } } dependencies { @@ -43,7 +48,7 @@ dependencies { implementation("org.atteo.classindex:classindex:3.13") annotationProcessor("org.atteo.classindex:classindex:3.13") - compileOnly("de.rettichlp:the-rettington-companion:0.0.0") + compileOnly("maven.modrinth:the-rettington-companion:2.0.0") } tasks.processResources {