diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d16d5a1..8e6e546 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: true contact_links: - name: 💬 Support - url: https://eventalerts.gg/development + url: https://eventalerts.gg/development?utm_source=github&utm_medium=issue_template&utm_campaign=support about: "If you need help with the mod or have a question please join the Development Discord server and ask there" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index efdac01..fea3c26 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ on: - 'build.gradle.kts' - 'settings.gradle.kts' - 'stonecutter.gradle.kts' + - 'stonecutter.properties.toml' - 'gradle.properties' - 'gradlew' - 'gradlew.bat' diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index da6b6f6..95f949d 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -8,6 +8,7 @@ on: - 'build.gradle.kts' - 'settings.gradle.kts' - 'stonecutter.gradle.kts' + - 'stonecutter.properties.toml' - 'gradle.properties' - 'gradlew' - 'gradlew.bat' diff --git a/build.gradle.kts b/build.gradle.kts index b69b072..cd44ead 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,14 +1,24 @@ +import net.fabricmc.loom.task.RemapJarTask import xyz.srnyx.gradlegalaxy.utility.inGitHubPublish import xyz.srnyx.gradlegalaxy.utility.inGitHubWorkflow +import java.io.File +import java.net.URI +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.StandardCopyOption + plugins { id("dev.kikugie.loom-back-compat") - id("xyz.srnyx.gradle-galaxy") version "a8227b9" + id("xyz.srnyx.gradle-galaxy") version "56c48b7" id("com.gradleup.shadow") version "9.6.1" - id("me.modmuss50.mod-publish-plugin") version "675051c" - id("dev.kikugie.fletching-table.fabric") version "0.1.0-alpha.22" - kotlin("jvm") version "2.4.10" // For Fletching Table - id("com.google.devtools.ksp") version "2.3.10" // For Fletching Table + id("me.modmuss50.mod-publish-plugin") version "04fb4ab" + + // Fletching Table + alias(ft.plugins.default) + alias(ft.plugins.fabric) + alias(ft.plugins.mixin) + alias(ft.plugins.lang) } group = "cc.aabss" @@ -52,7 +62,7 @@ galaxy { if (javaUtilitiesVersion == "snapshot" || sdkVersion == "snapshot" || okaeriConfigsVersion == "snapshot") add(MAVEN_LOCAL) add( - "https://maven.gnomecraft.net/releases/", "https://maven.nucleoid.xyz/", + GNOMECRAFT_RELEASES, NUCLEOID, OKAERI_RELEASES, OKAERI_SNAPSHOTS, SRNYX_RELEASES, SRNYX_SNAPSHOTS, FABRIC, SHEDANIEL, ISXANDER, @@ -66,6 +76,7 @@ galaxy { "mod_id" to modId, "mod_name" to modName, "mod_version" to modVersion, + "fabric_api_id" to if (is261Plus) "fabric-api" else "fabric", "deps_minecraft" to sc.current.version, "deps_loader" to loaderVersion, "deps_fabric_api" to fabricApiVersion, @@ -74,25 +85,29 @@ galaxy { platformPublishing { modrinth("ZcRRACSs") { + file = (if (is261Plus) tasks.shadowJar else loomx.modJar) + .flatMap { it.archiveFile } + .map { it.asFile } + // Fabric API requires { - id.set("P7dR8mSH") - version.set(fabricApiVersion) + id = "P7dR8mSH" + version = fabricApiVersion } // YetAnotherConfigLib (YACL) requires { - id.set("1eAoo2KR") - version.set(yaclVersion) + id = "1eAoo2KR" + version = yaclVersion } // Text Placeholder API placeholderApiVersion?.let { requires { - id.set("eXts2L7r") - version.set(it) + id = "eXts2L7r" + version = it } } // Mod Menu optional { - id.set("mOgUt4GM") - version.set(modMenuVersion) + id = "mOgUt4GM" + version = modMenuVersion } } @@ -108,11 +123,7 @@ dependencies { minecraft("com.mojang:minecraft:${sc.current.version}") // Mappings - if (is261Plus) { - loomx.applyMojangMappings() - } else { - mappings("net.fabricmc:yarn:${property("deps.yarn_mappings").toString()}:v2") - } + loomx.applyMojangMappings() // Library: Java Utilities shadowLibrary("xyz.srnyx:java-utilities:$javaUtilitiesVersion") @@ -156,30 +167,53 @@ stonecutter { swaps["mod_name"] = "\"$modName\"" swaps["mod_version"] = "\"$modVersion\"" swaps["mod_version_full"] = "\"$version\"" + + // Replacements + replacements.string(current.parsed >= "26.1") { + replace("ClientCommandManager", "ClientCommands") + replace("GuiGraphics", "GuiGraphicsExtractor") + replace("net.minecraft.client.renderer.state.CameraRenderState", "net.minecraft.client.renderer.state.level.CameraRenderState") + } + replacements.string(current.parsed < "1.21") { + replace("GenericMessageScreen", "GenericDirtMessageScreen") + } } fletchingTable { - fabric { - entrypointMappings.put("modmenu", "com.terraformersmc.modmenu.api.ModMenuApi") + fabric.configure("main") { + entrypoint("modmenu", "com.terraformersmc.modmenu.api.ModMenuApi") } - mixins.create("main") { - mixin("default", "eventutils.mixins.json") { + mixins.configure("main") { + mixin("eventutils.mixins.json") { env("client") } } - lang.create("main") { - patterns.add("assets/$modId/lang/**") - } + lang.configure("main") {} } tasks { - jar { archiveClassifier.set("") } + if (is261Plus) { + jar { archiveClassifier = "dev" } + val includeJarsDir = layout.buildDirectory.dir("processIncludeJars").get().asFile + shadowJar { + archiveClassifier = "" + dependsOn(jar, "processIncludeJars") + doLast { JarInJarGrafter.graft(archiveFile.get().asFile, includeJarsDir) } + } + } else { + jar { archiveClassifier = "" } + shadowJar { archiveClassifier = "shadow" } + named("remapJar") { + dependsOn(shadowJar) + mustRunAfter(shadowJar) + inputFile = shadowJar.flatMap { it.archiveFile } + } + } shadowJar { - archiveClassifier.set("shadow") - configurations.set(project.configurations.named("shadow").map { listOf(it) }) + configurations = project.configurations.named("shadow").map { listOf(it) } mergeServiceFiles() val libsPackage = "${project.group}.$modId.libs" @@ -205,19 +239,13 @@ tasks { relocate("org.newsclub.net.unix", "$libsPackage.newsclub.unix") } - remapJar { - dependsOn(shadowJar) - mustRunAfter(shadowJar) - inputFile.set(shadowJar.flatMap { it.archiveFile }) - } - // Builds the version into a shared folder in `build/libs` register("buildAndCollect") { group = "build" description = "Builds the mod and copies the jar to a shared folder" // loomx.modJar returns the jar task for the applied loom variant - from(loomx.modJar.map { it.archiveFile }) + from((if (is261Plus) shadowJar else loomx.modJar).map { it.archiveFile }) into(rootProject.layout.buildDirectory.file("libs")) dependsOn("build") @@ -227,26 +255,34 @@ tasks { loom { fabricModJsonPath = rootProject.file("src/main/resources/fabric.mod.json") // Useful for interface injection - decompilerOptions.named("vineflower") { + if (!is261Plus) decompilerOptions.named("vineflower") { options.put("mark-corresponding-synthetics", "1") // Adds names to lambdas - useful for mixins } runConfigs.all { - preferGradleTask.set(true) + preferGradleTask = true jvmArguments.add("-Dmixin.debug.export=true") // Exports transformed classes for debugging - runDirectory.set(file("../../run")) // Shares the run directory between versions + runDirectory = file("../../run") // Shares the run directory between versions } } -// Register buildActive task -if (sc.current.isActive) rootProject.tasks.register("buildActive") { - group = "build" - description = "Builds the mod for the currently active Minecraft version" +// Register tasks for active version +if (sc.current.isActive) { + rootProject.tasks.register("buildActive") { + group = "build" + description = "Builds the mod for the currently active Minecraft version" + + // Build mod + copy built jar to shared folder + dependsOn(tasks.named("build"), tasks.named("buildAndCollect")) + } + + rootProject.tasks.register("runActive") { + group = "fabric" + description = "Runs the mod for the currently active Minecraft version" - // Build mod - dependsOn(tasks.named("build")) - // Copy built jar to shared folder - dependsOn(tasks.named("buildAndCollect")) + // Run mod + dependsOn(tasks.named("runClient")) + } } // Custom jijLibrary (modImplementation + include) and shadowLibrary (implementation + shadow) dependency configurations @@ -258,3 +294,26 @@ fun DependencyHandler.shadowLibrary(dependency: String) { implementation(dependency) shadow(dependency) } + +// object required for configuration cache +object JarInJarGrafter { + fun graft(targetJar: File, includeJarsDir: File) { + val includeJars = includeJarsDir.listFiles { file -> file.isFile && file.extension == "jar" }?.sorted().orEmpty() + + FileSystems.newFileSystem(URI.create("jar:${targetJar.toURI()}"), emptyMap()).use { fs -> + // Nested Jar-in-Jar mods + if (includeJars.isNotEmpty()) { + val jarsDir = fs.getPath("META-INF", "jars") + Files.createDirectories(jarsDir) + for (jarFile in includeJars) Files.copy(jarFile.toPath(), jarsDir.resolve(jarFile.name), StandardCopyOption.REPLACE_EXISTING) + } + + // fabric.mod.json `jars` entries + val fmjPath = fs.getPath("fabric.mod.json") + @Suppress("UNCHECKED_CAST") + val fmj = groovy.json.JsonSlurper().parse(Files.readAllBytes(fmjPath)) as MutableMap + fmj["jars"] = includeJars.map { mapOf("file" to "META-INF/jars/${it.name}") } + Files.newOutputStream(fmjPath).use { it.write(groovy.json.JsonOutput.toJson(fmj).toByteArray()) } + } + } +} diff --git a/gradle.properties b/gradle.properties index 6ebafb8..97450fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,3 +2,5 @@ # srnyx thinks it needs so much due to shadowed libraries org.gradle.jvmargs=-Xmx4G org.gradle.workers.max=4 + +org.gradle.configuration-cache=true diff --git a/settings.gradle.kts b/settings.gradle.kts index 1f8e68d..81ebce5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,11 +12,24 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } +dependencyResolutionManagement { + repositories { + maven("https://maven.kikugie.dev/releases/") + maven("https://maven.kikugie.dev/snapshots/") + } + + versionCatalogs { + create("ft") { from("dev.kikugie.fletching-table:fletching-table.catalog:0.2-SNAPSHOT") } + } +} + rootProject.name = "EventUtils" stonecutter { create(rootProject) { versions( + "26.2", + "26.1.2", "1.21.11", "1.21.6", "1.21.5", diff --git a/src/main/java/cc/aabss/eventutils/EventUtils.java b/src/main/java/cc/aabss/eventutils/EventUtils.java index c28575b..57bdf45 100644 --- a/src/main/java/cc/aabss/eventutils/EventUtils.java +++ b/src/main/java/cc/aabss/eventutils/EventUtils.java @@ -16,11 +16,12 @@ import cc.aabss.eventutils.manager.KeybindManager; import cc.aabss.eventutils.sdk.EnrichedEvent; import cc.aabss.eventutils.sdk.EventWrapper; +import cc.aabss.eventutils.stats.Stats; import cc.aabss.eventutils.versioning.VersionedGameProfile; import cc.aabss.eventutils.websocket.listener.EventCancelledListener; import cc.aabss.eventutils.websocket.listener.EventPostedListener; import cc.aabss.eventutils.websocket.listener.FamousEventPostedListener; -import dev.kikugie.fletching_table.annotation.fabric.Entrypoint; +import dev.kikugie.fletching_table.fabric.Entrypoint; import eu.okaeri.configs.json.gson.JsonGsonConfigurer; import eu.okaeri.configs.serdes.commons.SerdesCommons; import gg.eventalerts.sdk.http.EAHTTP; @@ -34,15 +35,15 @@ import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.text.MutableText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.text.TextColor; -import net.minecraft.util.Formatting; -import net.minecraft.util.Language; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.TextColor; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -67,16 +68,16 @@ public class EventUtils implements ClientModInitializer { @NotNull private static final Duration IN_EVENT_TIME = Duration.ofHours(12); @NotNull public static final String QUEUE_TEXT = "\n\n Per-server ranks get a higher priority in their respective queues. To receive such a rank, purchase one at\n store.invadedlands.net.\n\nTo leave a queue, use the command: /leavequeue.\n"; - @NotNull public static final MutableText MESSAGE_PREFIX = Text.literal(BuildProperties.MOD_NAME) - .formatted(Formatting.BOLD) - .fillStyle(Style.EMPTY.withColor(TextColor.fromRgb(0xF5AA42))) - .append(Text.literal("§r »") - .fillStyle(Style.EMPTY.withBold(false).withColor(TextColor.fromRgb(0xB57C2F)))); - @NotNull public static final MutableText ERROR_MESSAGE_PREFIX = Text.literal(BuildProperties.MOD_NAME) - .formatted(Formatting.BOLD) - .formatted(Formatting.RED) - .append(Text.literal("§r§4 »") - .fillStyle(Style.EMPTY.withBold(false))); + @NotNull public static final MutableComponent MESSAGE_PREFIX = Component.literal(BuildProperties.MOD_NAME) + .withStyle(ChatFormatting.BOLD) + .withStyle(Style.EMPTY.withColor(TextColor.fromRgb(0xF5AA42))) + .append(Component.literal("§r »") + .withStyle(Style.EMPTY.withBold(false).withColor(TextColor.fromRgb(0xB57C2F)))); + @NotNull public static final MutableComponent ERROR_MESSAGE_PREFIX = Component.literal(BuildProperties.MOD_NAME) + .withStyle(ChatFormatting.BOLD) + .withStyle(ChatFormatting.RED) + .append(Component.literal("§r§4 »") + .withStyle(Style.EMPTY.withBold(false))); /** * Only use if it is absolutely impossible to access the mod instance through other (safer) means @@ -187,19 +188,19 @@ public void onInitializeClient() { // Delay some stuff to wait for server info to be fully loaded MiscUtility.IO_SCHEDULER.schedule(() -> { // Populate players cache - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - if (networkHandler != null) cacheManager + final ClientPacketListener packetListener = client.getConnection(); + if (packetListener != null) cacheManager .players() - .get(networkHandler.getListedPlayerListEntries().stream() + .get(packetListener.getListedOnlinePlayers().stream() .map(entry -> new VersionedGameProfile(entry.getProfile()).getId()) .collect(Collectors.toSet())) .queue(); // inEvent - final ServerInfo server = client.getCurrentServerEntry(); - EventUtils.LOGGER.debug("[JOIN] server={}", server != null ? server.address : "null"); + final ServerData server = client.getCurrentServer(); + EventUtils.LOGGER.debug("[JOIN] server={}", server != null ? server.ip : "null"); if (server != null) { - final String ip = server.address.toLowerCase(); + final String ip = server.ip.toLowerCase(); LOGGER.debug("[JOIN] retrieving event ip={}", ip); http.events.retrieveMany(1, null, Map.of( "match", "any", @@ -252,18 +253,18 @@ public void onInitializeClient() { ClientReceiveMessageEvents.MODIFY_GAME.register(((text, overlay) -> { if (config.simple_queue_message && text.getString().contains(QUEUE_TEXT)) { final String original = text.getString(); - final MutableText resultText = Text.literal(""); + final MutableComponent resultComponent = Component.literal(""); final Matcher matcher = java.util.regex.Pattern .compile("([\\w -]+?Queue Position)\\s*:\\s*(\\d+)/(\\d+)") .matcher(original); while (matcher.find()) { - if (!resultText.getSiblings().isEmpty()) resultText.append("\n"); - resultText.append(Text.literal(matcher.group(1)).formatted(Formatting.GOLD).append(": ") - .append(Text.literal(matcher.group(2)).formatted(Formatting.YELLOW)) - .append(Text.literal("/").formatted(Formatting.GOLD)) - .append(Text.literal(matcher.group(3)).formatted(Formatting.YELLOW))); + if (!resultComponent.getSiblings().isEmpty()) resultComponent.append("\n"); + resultComponent.append(Component.literal(matcher.group(1)).withStyle(ChatFormatting.GOLD).append(": ") + .append(Component.literal(matcher.group(2)).withStyle(ChatFormatting.YELLOW)) + .append(Component.literal("/").withStyle(ChatFormatting.GOLD)) + .append(Component.literal(matcher.group(3)).withStyle(ChatFormatting.YELLOW))); } - if (!resultText.getSiblings().isEmpty()) return resultText; + if (!resultComponent.getSiblings().isEmpty()) return resultComponent; } // May need to manipulate later return text; @@ -311,8 +312,8 @@ public void setupSdk(@Nullable String reason) { } public static boolean isNpc(@NotNull UUID uuid) { - final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); - return networkHandler != null && networkHandler.getPlayerListEntry(uuid) == null; + final ClientPacketListener packetListener = Minecraft.getInstance().getConnection(); + return packetListener != null && packetListener.getPlayerInfo(uuid) == null; } public static boolean isNpc(@Nullable String name) { @@ -320,8 +321,8 @@ public static boolean isNpc(@Nullable String name) { if (name == null || name.isEmpty() || !name.matches("^[a-zA-Z0-9_]{3,16}$")) return true; // Check if name in player-list - final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); - return networkHandler != null && networkHandler.getPlayerList().stream() + final ClientPacketListener packetListener = Minecraft.getInstance().getConnection(); + return packetListener != null && packetListener.getListedOnlinePlayers().stream() .noneMatch(entry -> new VersionedGameProfile(entry.getProfile()).getName().equalsIgnoreCase(name)); } @@ -334,7 +335,7 @@ public static int max(int @NotNull ... values) { @NotNull public static String translate(@NotNull String key) { - return Language.getInstance().get(key); + return Language.getInstance().getOrDefault(key); } /** diff --git a/src/main/java/cc/aabss/eventutils/ModMenuImpl.java b/src/main/java/cc/aabss/eventutils/ModMenuImpl.java index db42550..f455719 100644 --- a/src/main/java/cc/aabss/eventutils/ModMenuImpl.java +++ b/src/main/java/cc/aabss/eventutils/ModMenuImpl.java @@ -3,7 +3,7 @@ import cc.aabss.eventutils.screen.config.ConfigScreen; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; -import dev.kikugie.fletching_table.annotation.fabric.Entrypoint; +import dev.kikugie.fletching_table.fabric.Entrypoint; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/cc/aabss/eventutils/NotificationToast.java b/src/main/java/cc/aabss/eventutils/NotificationToast.java index 785278f..72623e2 100644 --- a/src/main/java/cc/aabss/eventutils/NotificationToast.java +++ b/src/main/java/cc/aabss/eventutils/NotificationToast.java @@ -1,20 +1,33 @@ package cc.aabss.eventutils; +import cc.aabss.eventutils.versioning.VersionedGraphicsGui; +import cc.aabss.eventutils.versioning.VersionedIdentifier; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.toast.Toast; -import net.minecraft.client.toast.ToastManager; -import net.minecraft.text.OrderedText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -//? if >=1.21.6 -//import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.network.chat.Component; +import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +//? if >=1.21.11 { +/*import net.minecraft.resources.Identifier; +*///?} else { +import net.minecraft.resources.ResourceLocation; +//?} +//? if >=1.21.6 { +/*import net.minecraft.client.renderer.RenderPipelines; +*///?} +//? if <1.21.6 && >1.21.2 { +import net.minecraft.client.renderer.RenderType; +//?} +//? if >=1.21.2 { +import net.minecraft.client.gui.components.toasts.ToastManager; +//?} else { +/*import net.minecraft.client.gui.components.toasts.ToastComponent; +*///?} import java.awt.*; import java.util.ArrayList; @@ -22,110 +35,122 @@ public class NotificationToast implements Toast { - @NotNull private static final Identifier TEXTURE = Identifier.of(BuildProperties.MOD_ID, "toast/notification"); + //? if >=1.21.11 { + /*@NotNull private static final Identifier TEXTURE + *///?} else { + @NotNull private static final ResourceLocation TEXTURE + //?} + = VersionedIdentifier.of("toast/notification"); - @NotNull private final Text title; - @NotNull private final List lines; + @NotNull private final Component title; + @NotNull private final List lines; private final int width; private final int height; public Visibility visibility; - public NotificationToast(@NotNull Text title, @Nullable Text description, boolean displayEventInfoInstructions) { + public NotificationToast(@NotNull Component title, @Nullable Component description, boolean displayEventInfoInstructions) { this.title = title; lines = new ArrayList<>(); - if (description != null) lines.add(description.asOrderedText()); - final OrderedText eventInfoInstructions = displayEventInfoInstructions ? Text.translatable("eventutils.event.toast.info_screen_button", EventUtils.MOD.keybindManager.eventInfoKey.getBoundKeyLocalizedText()).asOrderedText() : null; + if (description != null) lines.add(description.getVisualOrderText()); + final FormattedCharSequence eventInfoInstructions = displayEventInfoInstructions ? Component.translatable("eventutils.event.toast.info_screen_button", EventUtils.MOD.keybindManager.eventInfoKey.getTranslatedKeyMessage()).getVisualOrderText() : null; if (eventInfoInstructions != null) lines.add(eventInfoInstructions); - final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + final Font textRenderer = Minecraft.getInstance().font; width = EventUtils.max( 160, - 30 + textRenderer.getWidth(title), - eventInfoInstructions != null ? 30 + textRenderer.getWidth(eventInfoInstructions) : 0, - description != null ? 30 + textRenderer.getWidth(description) : 0); + 30 + textRenderer.width(title), + eventInfoInstructions != null ? 30 + textRenderer.width(eventInfoInstructions) : 0, + description != null ? 30 + textRenderer.width(description) : 0); height = 20 + Math.max(lines.size(), 1) * 12; - visibility = Visibility.HIDE; + visibility = Toast.Visibility.HIDE; } //? if >=1.21.2 { - @Override - public Visibility getVisibility() { + @Override @NotNull + public Visibility getWantedVisibility() { return visibility; } @Override - public void update(ToastManager toastManager, long startTime) { + public void update(@NotNull ToastManager toastManager, long startTime) { visibility = startTime >= Type.DEFAULT.displayDuration ? Toast.Visibility.HIDE : Toast.Visibility.SHOW; } //?} @Override @NotNull - public NotificationToast.Type getType() { + public NotificationToast.Type getToken() { return Type.DEFAULT; } @Override - public int getWidth() { + public int width() { return width; } @Override - public int getHeight() { + public int height() { return height; } @Override - //? if <1.21.2 { - /*public Toast.Visibility draw(DrawContext drawContext, ToastManager manager, long startTime) { - *///?} else { - public void draw(DrawContext drawContext, TextRenderer textRenderer, long startTime) { - //?} + //? if >=26.1 { + /*public void extractRenderState(@NotNull GuiGraphics graphics, @NotNull Font font, long fullyVisibleForMs) { + *///?} else if >1.21.2 { + public void render(@NotNull GuiGraphics graphics, @NotNull Font font, long startTime) { + //?} else { + /*@NotNull + public Toast.Visibility render(GuiGraphics graphics, ToastComponent manager, long startTime) { + *///?} + final VersionedGraphicsGui vGraphics = new VersionedGraphicsGui(graphics); + if (width == 160 && lines.size() <= 1) { - //? if <1.21.2 { - /*drawContext.drawGuiTexture(TEXTURE, 0, 0, width, height); - *///?} else if >=1.21.6 { - /*drawContext.drawGuiTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, 0, 0, width, height); // work on 1.21.4 and 1.21.5 - *///?} else { - drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURE, 0, 0, width, height); // work on 1.21.4 and 1.21.5 - //?} + //? if >=1.21.6 { + /*graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, 0, 0, width, height); + *///?} else if >1.21.2 { + graphics.blitSprite(RenderType::guiTextured, TEXTURE, 0, 0, width, height); + //?} else { + /*graphics.blitSprite(TEXTURE, 0, 0, width, height); + *///?} } else { int minHeight = Math.min(4, height - 28); - drawPart(drawContext, 0, 0, 28); - for (int i = 28; i < height - minHeight; i += 10) drawPart(drawContext, 16, i, Math.min(16, height - i - minHeight)); - drawPart(drawContext, 32 - minHeight, height - minHeight, minHeight); + drawPart(graphics, 0, 0, 28); + for (int i = 28; i < height - minHeight; i += 10) drawPart(graphics, 16, i, Math.min(16, height - i - minHeight)); + drawPart(graphics, 32 - minHeight, height - minHeight, minHeight); } - //? if <1.21.2 - /*final TextRenderer textRenderer = manager.getClient().textRenderer;*/ + //? if <1.21.2 { + /*final Font font = manager.getMinecraft().font; + *///?} if (lines.isEmpty()) { - drawContext.drawText(textRenderer, title, 24, 12, Color.YELLOW.getRGB(), false); + vGraphics.drawString(font, title, 24, 12, Color.YELLOW.getRGB(), false); } else { - drawContext.drawText(textRenderer, title, 24, 7, Color.YELLOW.getRGB(), false); - for (int i = 0; i < lines.size(); ++i) drawContext.drawText(textRenderer, lines.get(i), 24, 18 + i * 12, -1, false); + vGraphics.drawString(font, title, 24, 7, Color.YELLOW.getRGB(), false); + for (int i = 0; i < lines.size(); ++i) vGraphics.drawString(font, lines.get(i), 24, 18 + i * 12, -1, false); } - //? if <1.21.2 - /*return startTime >= Type.DEFAULT.displayDuration ? Toast.Visibility.HIDE : Toast.Visibility.SHOW;*/ + //? if <1.21.2 { + /*return startTime >= Type.DEFAULT.displayDuration ? Toast.Visibility.HIDE : Toast.Visibility.SHOW; + *///?} } - private void drawPart(@NotNull DrawContext context, int j, int k, int l) { + private void drawPart(@NotNull GuiGraphics context, int j, int k, int l) { final int m = j == 0 ? 20 : 5; final int n = Math.min(60, width - m); final int widthN = width - n; - //? if <=1.21.1 { - /*context.drawGuiTexture(TEXTURE, 160, 32, 0, j, 0, k, m, l); - for (int o = m; o < widthN; o += 64) context.drawGuiTexture(TEXTURE, 160, 32, 32, j, o, k, Math.min(64, widthN - o), l); - context.drawGuiTexture(TEXTURE, 160, 32, 160 - n, j, widthN, k, n, l); - *///?} else if >=1.21.6 { - /*context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, 160, 32, 0, j, 0, k, m, l); - for (int o = m; o < widthN; o += 64) context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, 160, 32, 32, j, o, k, Math.min(64, widthN - o), l); - context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, TEXTURE, 160, 32, 160 - n, j, widthN, k, n, l); - *///?} else { - context.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURE, 160, 32, 0, j, 0, k, m, l); - for (int o = m; o < widthN; o += 64) context.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURE, 160, 32, 32, j, o, k, Math.min(64, widthN - o), l); - context.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURE, 160, 32, 160 - n, j, widthN, k, n, l); - //?} + //? if >=1.21.6 { + /*context.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, 160, 32, 0, j, 0, k, m, l); + for (int o = m; o < widthN; o += 64) context.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, 160, 32, 32, j, o, k, Math.min(64, widthN - o), l); + context.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, 160, 32, 160 - n, j, widthN, k, n, l); + *///? } else if >1.21.1 { + context.blitSprite(RenderType::guiTextured, TEXTURE, 160, 32, 0, j, 0, k, m, l); + for (int o = m; o < widthN; o += 64) context.blitSprite(RenderType::guiTextured, TEXTURE, 160, 32, 32, j, o, k, Math.min(64, widthN - o), l); + context.blitSprite(RenderType::guiTextured, TEXTURE, 160, 32, 160 - n, j, widthN, k, n, l); + //?} else { + /*context.blitSprite(TEXTURE, 160, 32, 0, j, 0, k, m, l); + for (int o = m; o < widthN; o += 64) context.blitSprite(TEXTURE, 160, 32, 32, j, o, k, Math.min(64, widthN - o), l); + context.blitSprite(TEXTURE, 160, 32, 160 - n, j, widthN, k, n, l); + *///?} } @Environment(value = EnvType.CLIENT) diff --git a/src/main/java/cc/aabss/eventutils/UpdateChecker.java b/src/main/java/cc/aabss/eventutils/UpdateChecker.java index 521aa67..454716b 100644 --- a/src/main/java/cc/aabss/eventutils/UpdateChecker.java +++ b/src/main/java/cc/aabss/eventutils/UpdateChecker.java @@ -1,14 +1,15 @@ package cc.aabss.eventutils; +import cc.aabss.eventutils.versioning.VersionedLocalPlayer; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import net.minecraft.client.MinecraftClient; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.HoverEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +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 net.minecraft.network.chat.Style; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,7 +19,7 @@ import java.net.http.HttpResponse; import java.util.concurrent.CompletableFuture; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; /** @@ -41,17 +42,17 @@ public void notifyUpdate() { if (!mod.config.update_checker) return; // Ensure client in-game - final MinecraftClient client = MinecraftClient.getInstance(); + final Minecraft client = Minecraft.getInstance(); if (client.player == null) return; fetchLatestVersion().thenAccept(version -> { // Only notify if not on latest - if (version != null) client.send(() -> { + if (version != null) client.execute(() -> { if (client.player == null) return; - final MutableText hover = translatable("eventutils.updatechecker.hover"); + final MutableComponent hover = translatable("eventutils.updatechecker.hover"); final String link = "https://modrinth.com/mod/alerts/version/" + version; final String configCommand = "/eventutils config"; - client.player.sendMessage( + new VersionedLocalPlayer(client.player).sendMessage( EventUtils.MESSAGE_PREFIX.copy().append(" §e" + EventUtils.translate("eventutils.updatechecker.new") + "§r §7(" + BuildProperties.MOD_VERSION + " -> v" + version.replace(EventUtils.MC_VERSION + "-", "") + ")" + "\n") .setStyle(EventUtils.MESSAGE_PREFIX.getStyle() //? if >=1.21.5 { @@ -61,12 +62,12 @@ public void notifyUpdate() { .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover)) .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link))) //?} - .append(Text.literal("§7§o" + EventUtils.translate("eventutils.updatechecker.config")) + .append(Component.literal("§7§o" + EventUtils.translate("eventutils.updatechecker.config")) //? if >=1.21.5 { - /*.setStyle(Style.EMPTY.withClickEvent(new ClickEvent.RunCommand(configCommand)))), + /*.setStyle(Style.EMPTY.withClickEvent(new ClickEvent.RunCommand(configCommand)))) *///?} else - .setStyle(Style.EMPTY.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, configCommand)))), - false); + .setStyle(Style.EMPTY.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, configCommand)))) + ); }); }); } diff --git a/src/main/java/cc/aabss/eventutils/cache/Cache.java b/src/main/java/cc/aabss/eventutils/cache/Cache.java index 2f866c8..88c29cf 100644 --- a/src/main/java/cc/aabss/eventutils/cache/Cache.java +++ b/src/main/java/cc/aabss/eventutils/cache/Cache.java @@ -17,29 +17,37 @@ public abstract class Cache { @NotNull protected final ConcurrentMap> cache = new ConcurrentHashMap<>(); @NotNull protected final ConcurrentMap> inFlight = new ConcurrentHashMap<>(); + /** + * @return {@link Optional#of} if cached with value, {@link Optional#empty()} if cached with no value, {@code null} if not cached + */ + @Nullable + public Optional peek(@NotNull K key) { + return cache.get(key); + } + @NotNull @CheckReturnValue - public EAAction get(@NotNull K uuid) { + public EAAction get(@NotNull K key) { // Is cached - final Optional cached = cache.get(uuid); - EventUtils.LOGGER.trace("[CACHE] hit for key {}: {}", uuid, cached); + final Optional cached = cache.get(key); + EventUtils.LOGGER.trace("[CACHE] hit for key {}: {}", key, cached); if (cached != null) return EAAction.completed(cached.orElse(null)); // Not cached yet, fetch - EventUtils.LOGGER.trace("[CACHE] miss for key {}", uuid); - return fetch(uuid); + EventUtils.LOGGER.trace("[CACHE] miss for key {}", key); + return fetch(key); } @NotNull @CheckReturnValue - public EAAction> get(@NotNull Collection uuids) { + public EAAction> get(@NotNull Collection keys) { // Get cached vs missing values final Set cached = new HashSet<>(); final Set missing = new HashSet<>(); - for (final K uuid : uuids) { - final Optional player = cache.get(uuid); + for (final K key : keys) { + final Optional player = cache.get(key); if (player != null) { player.ifPresent(cached::add); } else { - missing.add(uuid); + missing.add(key); } } EventUtils.LOGGER.trace("[CACHE] hits: {}", cached); diff --git a/src/main/java/cc/aabss/eventutils/commands/CommandRegister.java b/src/main/java/cc/aabss/eventutils/commands/CommandRegister.java index 233b8e9..6ecaa53 100644 --- a/src/main/java/cc/aabss/eventutils/commands/CommandRegister.java +++ b/src/main/java/cc/aabss/eventutils/commands/CommandRegister.java @@ -7,7 +7,7 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.text.Text; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; @@ -25,7 +25,7 @@ public static void register(@NotNull EventUtils mod, @NotNull CommandDispatcher< final LiteralCommandNode main = ClientCommandManager .literal("eventutils") .executes(context -> { - context.getSource().sendError(Text.translatable("eventutils.command.unknown")); + context.getSource().sendError(Component.translatable("eventutils.command.unknown")); return 0; }) .build(); diff --git a/src/main/java/cc/aabss/eventutils/commands/ConfigCmd.java b/src/main/java/cc/aabss/eventutils/commands/ConfigCmd.java index 25da128..b28c25f 100644 --- a/src/main/java/cc/aabss/eventutils/commands/ConfigCmd.java +++ b/src/main/java/cc/aabss/eventutils/commands/ConfigCmd.java @@ -2,11 +2,12 @@ import cc.aabss.eventutils.EventUtils; import cc.aabss.eventutils.screen.config.ConfigScreen; +import cc.aabss.eventutils.versioning.VersionedClient; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Minecraft; import org.jetbrains.annotations.NotNull; @@ -27,7 +28,10 @@ public LiteralCommandNode build() { } private static void execute(@NotNull CommandContext context) { - final MinecraftClient client = context.getSource().getClient(); - client.send(() -> client.setScreen(ConfigScreen.getConfigScreen(client.currentScreen))); + final Minecraft client = context.getSource().getClient(); + client.execute(() -> { + final VersionedClient vClient = new VersionedClient(client); + vClient.setScreen(ConfigScreen.getConfigScreen(vClient.screen())); + }); } } diff --git a/src/main/java/cc/aabss/eventutils/commands/CountNameCmd.java b/src/main/java/cc/aabss/eventutils/commands/CountNameCmd.java index 91109ca..f28683d 100644 --- a/src/main/java/cc/aabss/eventutils/commands/CountNameCmd.java +++ b/src/main/java/cc/aabss/eventutils/commands/CountNameCmd.java @@ -7,10 +7,10 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -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.MutableComponent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,15 +46,15 @@ public LiteralCommandNode build() { } @Nullable - private static List getFilteredNames(@NotNull CommandContext context, @NotNull MinecraftClient client, @NotNull String filter) { + private static List getFilteredNames(@NotNull CommandContext context, @NotNull Minecraft client, @NotNull String filter) { // No players available - if (client.world == null || client.player == null || client.getNetworkHandler() == null) { - context.getSource().sendFeedback(Text.translatable("eventutils.command.countname.noplayers", EventUtils.ERROR_MESSAGE_PREFIX, Text.literal(filter).formatted(Formatting.DARK_RED))); + if (client.level == null || client.player == null || client.getConnection() == null) { + context.getSource().sendFeedback(Component.translatable("eventutils.command.countname.noplayers", EventUtils.ERROR_MESSAGE_PREFIX, Component.literal(filter).withStyle(ChatFormatting.DARK_RED))); return null; } // Filter names based on config and "isNPC" - final List namesFiltered = client.getNetworkHandler().getPlayerList().stream() + final List namesFiltered = client.getConnection().getListedOnlinePlayers().stream() .map(entry -> new VersionedGameProfile(entry.getProfile())) .filter(profile -> !EventUtils.isNpc(profile.getId())) .map(VersionedGameProfile::getName) @@ -63,7 +63,7 @@ private static List getFilteredNames(@NotNull CommandContext getFilteredNames(@NotNull CommandContext context, @NotNull String filter) { - final MinecraftClient client = context.getSource().getClient(); - client.send(() -> { + final Minecraft client = context.getSource().getClient(); + client.execute(() -> { // Get names final List namesFiltered = getFilteredNames(context, client, filter); if (namesFiltered == null) return; // Reply - context.getSource().sendFeedback(Text.translatable("eventutils.command.countname.count", EventUtils.MESSAGE_PREFIX, "§6" + namesFiltered.size(), namesFiltered.size() != 1 ? Text.translatable("eventutils.word.plural").formatted(Formatting.YELLOW) : "", Text.literal(filter).formatted(Formatting.GOLD))); + context.getSource().sendFeedback(Component.translatable("eventutils.command.countname.count", EventUtils.MESSAGE_PREFIX, "§6" + namesFiltered.size(), namesFiltered.size() != 1 ? Component.translatable("eventutils.word.plural").withStyle(ChatFormatting.YELLOW) : "", Component.literal(filter).withStyle(ChatFormatting.GOLD))); }); } private static void list(@NotNull CommandContext context, @NotNull String filter) { - final MinecraftClient client = context.getSource().getClient(); - client.send(() -> { + final Minecraft client = context.getSource().getClient(); + client.execute(() -> { // Get names final List namesFiltered = getFilteredNames(context, client, filter); if (namesFiltered == null) return; // Build player list - final MutableText playerList = Text.literal(""); + final MutableComponent playerList = Component.literal(""); for (int i = 0; i < namesFiltered.size(); i++) { - playerList.append(Text.literal(namesFiltered.get(i)).formatted(Formatting.GOLD)); + playerList.append(Component.literal(namesFiltered.get(i)).withStyle(ChatFormatting.GOLD)); // Add comma if not last - if (i < namesFiltered.size() - 1) playerList.append(Text.literal(", ").formatted(Formatting.YELLOW)); + if (i < namesFiltered.size() - 1) playerList.append(Component.literal(", ").withStyle(ChatFormatting.YELLOW)); } // Reply - context.getSource().sendFeedback(Text.translatable("eventutils.command.countname.list", EventUtils.MESSAGE_PREFIX, "§6" + namesFiltered.size(), namesFiltered.size() != 1 ? Text.translatable("eventutils.word.plural").formatted(Formatting.YELLOW) : "", Text.literal(filter).formatted(Formatting.GOLD), playerList)); + context.getSource().sendFeedback(Component.translatable("eventutils.command.countname.list", EventUtils.MESSAGE_PREFIX, "§6" + namesFiltered.size(), namesFiltered.size() != 1 ? Component.translatable("eventutils.word.plural").withStyle(ChatFormatting.YELLOW) : "", Component.literal(filter).withStyle(ChatFormatting.GOLD), playerList)); }); } } \ No newline at end of file diff --git a/src/main/java/cc/aabss/eventutils/commands/GroupMsgCmd.java b/src/main/java/cc/aabss/eventutils/commands/GroupMsgCmd.java index 01e2a71..9c363ce 100644 --- a/src/main/java/cc/aabss/eventutils/commands/GroupMsgCmd.java +++ b/src/main/java/cc/aabss/eventutils/commands/GroupMsgCmd.java @@ -7,11 +7,11 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.command.CommandSource; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.commands.SharedSuggestionProvider; import org.jetbrains.annotations.NotNull; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class GroupMsgCmd extends EUCommand { @@ -25,7 +25,7 @@ public LiteralCommandNode build() { .literal("groupmsg") .then(ClientCommandManager.argument("group", StringArgumentType.word()) .suggests((context, builder) -> - CommandSource.suggestMatching(() -> mod.config.getGroupNames().iterator(), builder)) + SharedSuggestionProvider.suggest(() -> mod.config.getGroupNames().iterator(), builder)) .then(ClientCommandManager.argument("message", StringArgumentType.greedyString()) .executes(context -> execute( context, @@ -37,9 +37,6 @@ public LiteralCommandNode build() { private int execute(@NotNull CommandContext context, @NotNull String groupName, @NotNull String message) { if (message.isEmpty()) return 0; - final ClientPlayerEntity sender = context.getSource().getPlayer(); - if (sender.networkHandler == null) return 0; - // Get group final Group group = mod.config.getGroupByName(groupName); if (group == null) { @@ -54,8 +51,9 @@ private int execute(@NotNull CommandContext context, } // Message recipients + final ClientPacketListener connection = context.getSource().getPlayer().connection; for (final String recipient : group.getPlayers()) { - sender.networkHandler.sendChatCommand("msg " + recipient + " [" + group.getName() + "] " + message); + connection.sendCommand("msg " + recipient + " [" + group.getName() + "] " + message); } return 1; } diff --git a/src/main/java/cc/aabss/eventutils/commands/TeleportCmd.java b/src/main/java/cc/aabss/eventutils/commands/TeleportCmd.java index e9c365f..de8eef8 100644 --- a/src/main/java/cc/aabss/eventutils/commands/TeleportCmd.java +++ b/src/main/java/cc/aabss/eventutils/commands/TeleportCmd.java @@ -11,7 +11,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class TeleportCmd extends EUCommand { @@ -48,7 +48,7 @@ private void execute(@NotNull CommandContext context, // Get last event of type final EventWrapper lastEvent = mod.lastEvents.get(type); if (lastEvent == null || lastEvent.ip == null) { - source.sendError(translatable("eventutils.command.no_event_found", type.name().toLowerCase())); + source.sendError(translatable("eventutils.command.no_event_found", type.nameTranslation)); return; } diff --git a/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCmd.java b/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCmd.java index 4c71a4b..fb7aeec 100644 --- a/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCmd.java +++ b/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCmd.java @@ -8,11 +8,11 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.PlayerInfo; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -29,8 +29,8 @@ public LiteralCommandNode build() { .literal("priority") .then(ClientCommandManager.argument("player", StringArgumentType.word()) .suggests((context, builder) -> { - final ClientPlayNetworkHandler networkHandler = context.getSource().getClient().getNetworkHandler(); - if (networkHandler != null) for (final PlayerListEntry player : networkHandler.getPlayerList()) { + final ClientPacketListener packetListener = context.getSource().getClient().getConnection(); + if (packetListener != null) for (final PlayerInfo player : packetListener.getListedOnlinePlayers()) { final VersionedGameProfile profile = new VersionedGameProfile(player.getProfile()); if (!EventUtils.isNpc(profile.getId())) builder.suggest(profile.getName()); } @@ -48,26 +48,26 @@ public LiteralCommandNode build() { } private static void execute(@NotNull CommandContext context, String name) { - final MinecraftClient client = context.getSource().getClient(); - client.send(() -> { + final Minecraft client = context.getSource().getClient(); + client.execute(() -> { // Get names final List namesSorted = PriorityCommon.getNamesSorted(client); if (namesSorted == null || client.player == null) { - context.getSource().sendFeedback(Text.translatable("eventutils.command.priority.noplayer", EventUtils.ERROR_MESSAGE_PREFIX)); + context.getSource().sendFeedback(Component.translatable("eventutils.command.priority.noplayer", EventUtils.ERROR_MESSAGE_PREFIX)); return; } final String nameLower = name.toLowerCase(); for (final String playerName : namesSorted) if (nameLower.equals(playerName.toLowerCase())) { if (playerName.equalsIgnoreCase(client.player.getName().getString())) { - context.getSource().sendFeedback(Text.translatable("eventutils.command.priority.self", EventUtils.MESSAGE_PREFIX, "§6#" + (namesSorted.indexOf(playerName) + 1))); + context.getSource().sendFeedback(Component.translatable("eventutils.command.priority.self", EventUtils.MESSAGE_PREFIX, "§6#" + (namesSorted.indexOf(playerName) + 1))); } else { - context.getSource().sendFeedback(Text.translatable("eventutils.command.priority.player", EventUtils.MESSAGE_PREFIX, Text.literal(playerName).formatted(Formatting.YELLOW), "§6#" + (namesSorted.indexOf(playerName) + 1))); + context.getSource().sendFeedback(Component.translatable("eventutils.command.priority.player", EventUtils.MESSAGE_PREFIX, Component.literal(playerName).withStyle(ChatFormatting.YELLOW), "§6#" + (namesSorted.indexOf(playerName) + 1))); } return; } - context.getSource().sendFeedback(Text.translatable("eventutils.command.priority.noplayer", EventUtils.ERROR_MESSAGE_PREFIX)); + context.getSource().sendFeedback(Component.translatable("eventutils.command.priority.noplayer", EventUtils.ERROR_MESSAGE_PREFIX)); }); } } diff --git a/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCommon.java b/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCommon.java index 1fecd65..cc03063 100644 --- a/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCommon.java +++ b/src/main/java/cc/aabss/eventutils/commands/priority/PriorityCommon.java @@ -1,8 +1,8 @@ package cc.aabss.eventutils.commands.priority; import cc.aabss.eventutils.EventUtils; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.AbstractClientPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; @@ -13,11 +13,11 @@ public class PriorityCommon { @Nullable @Unmodifiable - public static List getNamesSorted(@NotNull MinecraftClient client) { - if (client.world == null || client.player == null) return null; - return client.world.getPlayers().stream() - .filter(player -> !EventUtils.isNpc(player.getUuid())) - .sorted(Comparator.comparingInt(AbstractClientPlayerEntity::getId)) + public static List getNamesSorted(@NotNull Minecraft client) { + if (client.level == null || client.player == null) return null; + return client.level.players().stream() + .filter(player -> !EventUtils.isNpc(player.getUUID())) + .sorted(Comparator.comparingInt(AbstractClientPlayer::getId)) .map(player -> player.getName().getString()) .toList(); } diff --git a/src/main/java/cc/aabss/eventutils/commands/priority/PriorityTopCmd.java b/src/main/java/cc/aabss/eventutils/commands/priority/PriorityTopCmd.java index 5c24f85..9b1f9bc 100644 --- a/src/main/java/cc/aabss/eventutils/commands/priority/PriorityTopCmd.java +++ b/src/main/java/cc/aabss/eventutils/commands/priority/PriorityTopCmd.java @@ -7,13 +7,13 @@ import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.MutableText; -import net.minecraft.text.Style; -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.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.TextColor; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -44,12 +44,12 @@ public LiteralCommandNode build() { private static void execute(@NotNull CommandContext context, int page) { final FabricClientCommandSource source = context.getSource(); - final MinecraftClient client = source.getClient(); - client.send(() -> { + final Minecraft client = source.getClient(); + client.execute(() -> { // Get names final List namesSorted = PriorityCommon.getNamesSorted(client); if (namesSorted == null || client.player == null) { - source.sendFeedback(Text.translatable("eventutils.command.prioritytop.emptypage")); + source.sendFeedback(Component.translatable("eventutils.command.prioritytop.emptypage")); return; } @@ -57,7 +57,7 @@ private static void execute(@NotNull CommandContext c final int totalPlayers = namesSorted.size(); final int totalPages = (int) Math.ceil((double) totalPlayers / PLAYERS_PER_PAGE); if (page > totalPages || page < 1) { - source.sendFeedback(Text.translatable("eventutils.command.prioritytop.notapage", EventUtils.ERROR_MESSAGE_PREFIX, "§f" + totalPages)); + source.sendFeedback(Component.translatable("eventutils.command.prioritytop.notapage", EventUtils.ERROR_MESSAGE_PREFIX, "§f" + totalPages)); return; } @@ -66,7 +66,7 @@ private static void execute(@NotNull CommandContext c final int start = pageIndex * PLAYERS_PER_PAGE; final int end = Math.min(start + PLAYERS_PER_PAGE, totalPlayers); final String clientName = client.player.getName().getString().toLowerCase(); - final MutableText text = Text.translatable("eventutils.command.prioritytop.page", EventUtils.MESSAGE_PREFIX, "§6" + page, "§6" + totalPages); + final MutableComponent text = Component.translatable("eventutils.command.prioritytop.page", EventUtils.MESSAGE_PREFIX, "§6" + page, "§6" + totalPages); for (int i = start; i < end; i++) { final String name = namesSorted.get(i); final boolean isLocalPlayer = name.equalsIgnoreCase(clientName); @@ -82,21 +82,21 @@ private static void execute(@NotNull CommandContext c if (isLocalPlayer) { yield Style.EMPTY.withColor(TextColor.fromRgb(0x9AED47)); } - yield Style.EMPTY.withColor(TextColor.fromFormatting(Formatting.WHITE)); + yield Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.WHITE)); } }; - final MutableText item = Text.literal(String.format("%s%d - %s\n", boldModifier, placement, isLocalPlayer ? name + " (You)" : name)).fillStyle(colorModifier); + final MutableComponent item = Component.literal(String.format("%s%d - %s\n", boldModifier, placement, isLocalPlayer ? name + " (You)" : name)).withStyle(colorModifier); text.append(item); } source.sendFeedback(text); - MutableText lastpage = Text.literal(""); - MutableText nextpage = Text.literal(""); + MutableComponent lastpage = Component.literal(""); + MutableComponent nextpage = Component.literal(""); if (page > 1) { final String command = "/eventutils prioritytop " + (page - 1); - lastpage = Text.translatable("eventutils.command.prioritytop.lastpage", page - 1).setStyle(Style.EMPTY.withClickEvent( + lastpage = Component.translatable("eventutils.command.prioritytop.lastpage", page - 1).setStyle(Style.EMPTY.withClickEvent( //? if <=1.21.4 { new ClickEvent(ClickEvent.Action.RUN_COMMAND, command) //?} else { @@ -106,7 +106,7 @@ private static void execute(@NotNull CommandContext c } if (page + 1 <= totalPages) { - nextpage = Text.translatable( + nextpage = Component.translatable( "eventutils.command.prioritytop.nextpage", page + 1 ).setStyle( @@ -119,7 +119,7 @@ private static void execute(@NotNull CommandContext c } if (!lastpage.getString().isEmpty() || !nextpage.getString().isEmpty()) { - source.sendFeedback(Text.translatable("eventutils.command.prioritytop.pagebutton", EventUtils.MESSAGE_PREFIX, lastpage, nextpage)); + source.sendFeedback(Component.translatable("eventutils.command.prioritytop.pagebutton", EventUtils.MESSAGE_PREFIX, lastpage, nextpage)); } }); } diff --git a/src/main/java/cc/aabss/eventutils/config/EUConfig.java b/src/main/java/cc/aabss/eventutils/config/EUConfig.java index 9e13c40..e83fd4d 100644 --- a/src/main/java/cc/aabss/eventutils/config/EUConfig.java +++ b/src/main/java/cc/aabss/eventutils/config/EUConfig.java @@ -1,5 +1,6 @@ package cc.aabss.eventutils.config; +import cc.aabss.eventutils.stats.Stat; import eu.okaeri.configs.OkaeriConfig; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.spi.StandardLevel; @@ -15,19 +16,44 @@ public class EUConfig extends OkaeriConfig { public static final int MIN_EVENT_SERVER_DISPLAY_MINUTES = 1; public static final int MAX_EVENT_SERVER_DISPLAY_MINUTES = 15; + + @Stat public boolean discord_rpc = Defaults.DISCORD_RPC; + + @Stat public boolean simple_queue_message = Defaults.SIMPLE_QUEUE_MESSAGE; + + @Stat public boolean update_checker = Defaults.UPDATE_CHECKER; + + @Stat public boolean confirm_window_close = Defaults.CONFIRM_WINDOW_CLOSE; + + @Stat public boolean confirm_disconnect = Defaults.CONFIRM_DISCONNECT; + + @Stat @NotNull public String default_famous_ip = Defaults.DEFAULT_FAMOUS_IP; + + @Stat public boolean bee_icons = Defaults.BEE_ICONS; - @Range(from = MIN_EVENT_SERVER_DISPLAY_MINUTES, to = MAX_EVENT_SERVER_DISPLAY_MINUTES) public int event_server_display_minutes = Defaults.EVENT_SERVER_DISPLAY_MINUTES; + + @Range(from = MIN_EVENT_SERVER_DISPLAY_MINUTES, to = MAX_EVENT_SERVER_DISPLAY_MINUTES) @Stat + public int event_server_display_minutes = Defaults.EVENT_SERVER_DISPLAY_MINUTES; + + @Stat @NotNull public Map groups = Defaults.groups(); + + @Stat @NotNull public Map event_settings = Defaults.eventSettings(); + + @Stat public boolean developer_mode = Defaults.DEVELOPER_MODE; + + @Stat @NotNull public StandardLevel log_level = Defaults.LOG_LEVEL; + @NotNull public List getGroupNames() { return groups.values().stream() diff --git a/src/main/java/cc/aabss/eventutils/config/EventType.java b/src/main/java/cc/aabss/eventutils/config/EventType.java index 288bad0..6822eb1 100644 --- a/src/main/java/cc/aabss/eventutils/config/EventType.java +++ b/src/main/java/cc/aabss/eventutils/config/EventType.java @@ -1,16 +1,15 @@ package cc.aabss.eventutils.config; -import cc.aabss.eventutils.BuildProperties; import cc.aabss.eventutils.screen.config.ConfigScreen; +import cc.aabss.eventutils.versioning.VersionedIdentifier; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.OptionDescription; import dev.isxander.yacl3.api.OptionGroup; import dev.isxander.yacl3.api.controller.EnumDropdownControllerBuilder; import gg.eventalerts.sdk.object.EAEvent; import gg.eventalerts.sdk.object.EAFamousEvent; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.Identifier; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,52 +19,52 @@ */ public enum EventType { // EAFamousEvent - SKEPPY(EAFamousEvent.Type.SKEPPY, Formatting.AQUA), - FAMOUS(EAFamousEvent.Type.FAMOUS, Formatting.AQUA), - POTENTIAL_FAMOUS(EAFamousEvent.Type.POTENTIAL_FAMOUS, Formatting.DARK_AQUA), - SIGHTING(EAFamousEvent.Type.SIGHTING, Formatting.DARK_RED), + SKEPPY(EAFamousEvent.Type.SKEPPY, ChatFormatting.AQUA), + FAMOUS(EAFamousEvent.Type.FAMOUS, ChatFormatting.AQUA), + POTENTIAL_FAMOUS(EAFamousEvent.Type.POTENTIAL_FAMOUS, ChatFormatting.DARK_AQUA), + SIGHTING(EAFamousEvent.Type.SIGHTING, ChatFormatting.DARK_RED), // EAEvent - BIG_MONEY(EAEvent.PingRole.BIG_MONEY, Formatting.DARK_GREEN), - MONEY(EAEvent.PingRole.MONEY, Formatting.GREEN), - CIVILIZATION(EAEvent.PingRole.CIVILIZATION, Formatting.BLUE), - HOUSING(EAEvent.PingRole.HOUSING, Formatting.GOLD), - FUN(EAEvent.PingRole.FUN, Formatting.RED), - PARTNER(EAEvent.PingRole.PARTNER, Formatting.LIGHT_PURPLE), - COMMUNITY(EAEvent.PingRole.COMMUNITY, Formatting.GRAY); + BIG_MONEY(EAEvent.PingRole.BIG_MONEY, ChatFormatting.DARK_GREEN), + MONEY(EAEvent.PingRole.MONEY, ChatFormatting.GREEN), + CIVILIZATION(EAEvent.PingRole.CIVILIZATION, ChatFormatting.BLUE), + HOUSING(EAEvent.PingRole.HOUSING, ChatFormatting.GOLD), + FUN(EAEvent.PingRole.FUN, ChatFormatting.RED), + PARTNER(EAEvent.PingRole.PARTNER, ChatFormatting.LIGHT_PURPLE), + COMMUNITY(EAEvent.PingRole.COMMUNITY, ChatFormatting.GRAY); @Nullable public final EAEvent.PingRole pingRole; @Nullable public final EAFamousEvent.Type famousEventType; - @NotNull public final Formatting color; - @NotNull public final Text nameTranslation = Text.translatable("eventutils.event.type." + name()); - @NotNull public final Text descriptionTranslation = Text.translatable("eventutils.event.description." + name()); + @NotNull public final ChatFormatting color; + @NotNull public final Component nameTranslation = Component.translatable("eventutils.event.type." + name()); + @NotNull public final Component descriptionTranslation = Component.translatable("eventutils.event.description." + name()); - EventType(@Nullable EAEvent.PingRole pingRole, @Nullable EAFamousEvent.Type famousEventType, @NotNull Formatting color) { + EventType(@Nullable EAEvent.PingRole pingRole, @Nullable EAFamousEvent.Type famousEventType, @NotNull ChatFormatting color) { this.pingRole = pingRole; this.famousEventType = famousEventType; this.color = color; } - EventType(@NotNull EAEvent.PingRole pingRole, @NotNull Formatting color) { + EventType(@NotNull EAEvent.PingRole pingRole, @NotNull ChatFormatting color) { this(pingRole, null, color); } - EventType(@NotNull EAFamousEvent.Type famousEventType, @NotNull Formatting color) { + EventType(@NotNull EAFamousEvent.Type famousEventType, @NotNull ChatFormatting color) { this(null, famousEventType, color); } @NotNull public OptionGroup getOptionGroup(@NotNull EUConfig config) { return OptionGroup.createBuilder() - .name(Text.translatable("eventutils.config.event_settings.title", nameTranslation).formatted(color)) - .description(OptionDescription.of(Text.translatable("eventutils.config.event_settings.description", descriptionTranslation))) + .name(Component.translatable("eventutils.config.event_settings.title", nameTranslation).withStyle(color)) + .description(OptionDescription.of(Component.translatable("eventutils.config.event_settings.description", descriptionTranslation))) .collapsed(true) .option(Option.createBuilder() - .name(Text.translatable("eventutils.config.event_settings.toasts.label")) + .name(Component.translatable("eventutils.config.event_settings.toasts.label")) .description(OptionDescription.createBuilder() - .text(Text.translatable("eventutils.config.event_settings.toasts.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/toast.png"), 767, 128) + .text(Component.translatable("eventutils.config.event_settings.toasts.description")) + .image(VersionedIdentifier.of("textures/config/toast.png"), 767, 128) .build()) .binding(EventSettings.Defaults.TOASTS, () -> config.getEventSettings(this).toasts, newValue -> { config.getEventSettingsOrCreate(this).toasts = newValue; @@ -74,8 +73,8 @@ public OptionGroup getOptionGroup(@NotNull EUConfig config) { .controller(ConfigScreen::getBooleanBuilder) .build()) .option(Option.createBuilder() - .name(Text.translatable("eventutils.config.event_settings.sound.label")) - .description(OptionDescription.of(Text.translatable("eventutils.config.event_settings.sound.description"))) + .name(Component.translatable("eventutils.config.event_settings.sound.label")) + .description(OptionDescription.of(Component.translatable("eventutils.config.event_settings.sound.description"))) .binding(EventSettings.Defaults.SOUND, () -> config.getEventSettings(this).sound, newValue -> { config.getEventSettingsOrCreate(this).sound = newValue; config.save(); @@ -84,10 +83,10 @@ public OptionGroup getOptionGroup(@NotNull EUConfig config) { .formatValue(NotificationSound::getDisplayName)) .build()) .option(Option.createBuilder() - .name(Text.translatable("eventutils.config.event_settings.info_screen.label")) + .name(Component.translatable("eventutils.config.event_settings.info_screen.label")) .description(OptionDescription.createBuilder() - .text(Text.translatable("eventutils.config.event_settings.info_screen.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/info_screen.png"), 1106, 898) + .text(Component.translatable("eventutils.config.event_settings.info_screen.description")) + .image(VersionedIdentifier.of("textures/config/info_screen.png"), 1106, 898) .build()) .binding(EventSettings.Defaults.INFO_SCREEN, () -> config.getEventSettings(this).infoScreen, newValue -> { config.getEventSettingsOrCreate(this).infoScreen = newValue; @@ -96,8 +95,8 @@ public OptionGroup getOptionGroup(@NotNull EUConfig config) { .controller(ConfigScreen::getBooleanBuilder) .build()) .option(Option.createBuilder() - .name(Text.translatable("eventutils.config.event_settings.auto_tp.label")) - .description(OptionDescription.of(Text.translatable("eventutils.config.event_settings.auto_tp.description"))) + .name(Component.translatable("eventutils.config.event_settings.auto_tp.label")) + .description(OptionDescription.of(Component.translatable("eventutils.config.event_settings.auto_tp.description"))) .binding(EventSettings.Defaults.AUTO_TP, () -> config.getEventSettings(this).autoTp, newValue -> { config.getEventSettingsOrCreate(this).autoTp = newValue; config.save(); @@ -105,10 +104,10 @@ public OptionGroup getOptionGroup(@NotNull EUConfig config) { .controller(ConfigScreen::getBooleanBuilder) .build()) .option(Option.createBuilder() - .name(Text.translatable("eventutils.config.event_settings.server_list.label")) + .name(Component.translatable("eventutils.config.event_settings.server_list.label")) .description(OptionDescription.createBuilder() - .text(Text.translatable("eventutils.config.event_settings.server_list.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/server_listing.png"), 975, 415) + .text(Component.translatable("eventutils.config.event_settings.server_list.description")) + .image(VersionedIdentifier.of("textures/config/server_listing.png"), 975, 415) .build()) .binding(EventSettings.Defaults.SERVER_LIST, () -> config.getEventSettings(this).serverList, newValue -> { config.getEventSettingsOrCreate(this).serverList = newValue; diff --git a/src/main/java/cc/aabss/eventutils/config/Group.java b/src/main/java/cc/aabss/eventutils/config/Group.java index 52ff984..19706f6 100644 --- a/src/main/java/cc/aabss/eventutils/config/Group.java +++ b/src/main/java/cc/aabss/eventutils/config/Group.java @@ -1,19 +1,24 @@ package cc.aabss.eventutils.config; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.EntityType; -import net.minecraft.util.Formatting; -import net.minecraft.util.math.Vec3d; +import cc.aabss.eventutils.stats.Statable; +import cc.aabss.eventutils.versioning.VersionedEntityType; +import com.google.gson.JsonObject; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Range; import xyz.srnyx.javautilities.parents.Stringable; +//? if >=26.2 { +//?} import java.util.*; import java.util.stream.Collectors; -public class Group extends Stringable { +public class Group extends Stringable implements Statable { public static final int MAX_RADIUS = 100; @NotNull private transient UUID uuid; @@ -75,7 +80,7 @@ public Set> getEntities() { @NotNull public Set getEntityIds() { return entities.stream() - .map(entityType -> EntityType.getId(entityType).toString()) + .map(entityType -> EntityType.getKey(entityType).toString()) .collect(Collectors.toCollection(LinkedHashSet::new)); } @@ -88,7 +93,7 @@ public Group setEntities(@NotNull Collection> entities) { @NotNull public Group setEntitiesByIds(@NotNull Collection entities) { return setEntities(entities.stream() - .map(name -> EntityType.get(name).orElse(null)) + .map(VersionedEntityType::getEntityTypeByIdentifier) .filter(Objects::nonNull) .collect(Collectors.toList())); } @@ -146,43 +151,56 @@ public Group setRadius(@Nullable Integer radius) { return this; } - public boolean outsideRadius(@Nullable Vec3d position) { + public boolean outsideRadius(@Nullable Vec3 position) { if (radius == null || position == null) return false; - final MinecraftClient client = MinecraftClient.getInstance(); + final Minecraft client = Minecraft.getInstance(); if (client.player == null) return true; //? if >=1.21.11 { - /*final Vec3d clientPosition = client.player.getSyncedPos(); + /*final Vec3 clientPosition = client.player.trackingPosition(); *///?} else { - final Vec3d clientPosition = client.player.getPos(); + final Vec3 clientPosition = client.player.position(); //?} return clientPosition.distanceTo(position) > radius; } - public boolean isPlayerVisible(@NotNull String name, @Nullable Vec3d position) { + public boolean isPlayerVisible(@NotNull String name, @Nullable Vec3 position) { final boolean show = (playerMode == Mode.SHOW) == players.contains(name.toLowerCase()); return show || outsideRadius(position); } - public boolean isEntityVisible(@NotNull EntityType entityType, @Nullable Vec3d position) { + public boolean isEntityVisible(@NotNull EntityType entityType, @Nullable Vec3 position) { final boolean show = (entityMode == Mode.SHOW) == entities.contains(entityType); return show || outsideRadius(position); } - public boolean isNpcVisible(@Nullable Vec3d position) { + public boolean isNpcVisible(@Nullable Vec3 position) { return npcMode == Mode.SHOW || outsideRadius(position); } public enum Mode { - SHOW(Formatting.GREEN), - HIDE(Formatting.RED); + SHOW(ChatFormatting.GREEN), + HIDE(ChatFormatting.RED); - @NotNull public final Formatting formatting; + @NotNull public final ChatFormatting formatting; - Mode(@NotNull Formatting formatting) { + Mode(@NotNull ChatFormatting formatting) { this.formatting = formatting; } } + @Override @Nullable + public JsonObject toStat() { + final JsonObject json = new JsonObject(); + json.addProperty("name", getName()); + json.addProperty("players_size", players.size()); + json.addProperty("entities_size", entities.size()); + json.addProperty("player_mode", playerMode.name()); + json.addProperty("entity_mode", entityMode.name()); + json.addProperty("npc_mode", npcMode.name()); + json.addProperty("radius", radius); + return json; + } + // Collections/Maps need to have methods to create new instances of the collection! public static class Defaults { @NotNull private static final List PLAYERS = List.of(); @@ -203,7 +221,7 @@ public static Set> entities() { @NotNull public static Set entityIds() { return ENTITIES.stream() - .map(entityType -> EntityType.getId(entityType).toString()) + .map(entityType -> EntityType.getKey(entityType).toString()) .collect(Collectors.toCollection(LinkedHashSet::new)); } } diff --git a/src/main/java/cc/aabss/eventutils/config/NotificationSound.java b/src/main/java/cc/aabss/eventutils/config/NotificationSound.java index 30fcf09..520efe0 100644 --- a/src/main/java/cc/aabss/eventutils/config/NotificationSound.java +++ b/src/main/java/cc/aabss/eventutils/config/NotificationSound.java @@ -1,16 +1,15 @@ package cc.aabss.eventutils.config; -import cc.aabss.eventutils.BuildProperties; +import cc.aabss.eventutils.versioning.VersionedIdentifier; import dev.isxander.yacl3.api.NameableEnum; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.sound.SoundEvent; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvent; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public enum NotificationSound implements NameableEnum { @@ -27,11 +26,11 @@ public enum NotificationSound implements NameableEnum { TIME_OF_WAR; public void play() { - MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvent.of(Identifier.of(BuildProperties.MOD_ID, "notification." + name().toLowerCase())), 1, 1)); + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvent.createVariableRangeEvent(VersionedIdentifier.of("notification." + name().toLowerCase())), 1, 1)); } @Override @NotNull @Contract(" -> new") - public Text getDisplayName() { + public Component getDisplayName() { return translatable("eventutils.sound." + name().toLowerCase()); } } diff --git a/src/main/java/cc/aabss/eventutils/config/migrations/C0004_Flat_hiding_to_Groups.java b/src/main/java/cc/aabss/eventutils/config/migrations/C0004_Flat_hiding_to_Groups.java index 7193a1a..b8ba04b 100644 --- a/src/main/java/cc/aabss/eventutils/config/migrations/C0004_Flat_hiding_to_Groups.java +++ b/src/main/java/cc/aabss/eventutils/config/migrations/C0004_Flat_hiding_to_Groups.java @@ -3,7 +3,7 @@ import cc.aabss.eventutils.config.Group; import eu.okaeri.configs.migrate.builtin.NamedMigration; import eu.okaeri.configs.schema.GenericsDeclaration; -import net.minecraft.entity.EntityType; +import net.minecraft.world.entity.EntityType; import java.util.List; import java.util.UUID; diff --git a/src/main/java/cc/aabss/eventutils/config/serdes/EntityTypeSerializer.java b/src/main/java/cc/aabss/eventutils/config/serdes/EntityTypeSerializer.java index 8859476..9124bbb 100644 --- a/src/main/java/cc/aabss/eventutils/config/serdes/EntityTypeSerializer.java +++ b/src/main/java/cc/aabss/eventutils/config/serdes/EntityTypeSerializer.java @@ -1,9 +1,10 @@ package cc.aabss.eventutils.config.serdes; +import cc.aabss.eventutils.versioning.VersionedEntityType; import eu.okaeri.configs.schema.GenericsPair; import eu.okaeri.configs.serdes.BidirectionalTransformer; import eu.okaeri.configs.serdes.SerdesContext; -import net.minecraft.entity.EntityType; +import net.minecraft.world.entity.EntityType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,11 +17,11 @@ public GenericsPair getPair() { @Override @Nullable public EntityType leftToRight(@NotNull String data, @NotNull SerdesContext serdesContext) { - return EntityType.get(data).orElse(null); + return VersionedEntityType.getEntityTypeByIdentifier(data); } @Override @NotNull public String rightToLeft(@NotNull EntityType data, @NotNull SerdesContext serdesContext) { - return EntityType.getId(data).toString(); + return EntityType.getKey(data).toString(); } } diff --git a/src/main/java/cc/aabss/eventutils/config/serdes/GroupSerializer.java b/src/main/java/cc/aabss/eventutils/config/serdes/GroupSerializer.java index 9fa3c4a..202682a 100644 --- a/src/main/java/cc/aabss/eventutils/config/serdes/GroupSerializer.java +++ b/src/main/java/cc/aabss/eventutils/config/serdes/GroupSerializer.java @@ -5,7 +5,7 @@ import eu.okaeri.configs.serdes.DeserializationData; import eu.okaeri.configs.serdes.ObjectSerializer; import eu.okaeri.configs.serdes.SerializationData; -import net.minecraft.entity.EntityType; +import net.minecraft.world.entity.EntityType; import org.jetbrains.annotations.NotNull; import java.util.List; diff --git a/src/main/java/cc/aabss/eventutils/discordrpc/DiscordRPC.java b/src/main/java/cc/aabss/eventutils/discordrpc/DiscordRPC.java index 1aaa357..96981de 100644 --- a/src/main/java/cc/aabss/eventutils/discordrpc/DiscordRPC.java +++ b/src/main/java/cc/aabss/eventutils/discordrpc/DiscordRPC.java @@ -7,10 +7,10 @@ import com.jagrosh.discordipc.entities.pipe.PipeStatus; import com.jagrosh.discordipc.exceptions.NoDiscordClientException; import gg.eventalerts.sdk.http.action.EAAction; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.client.session.Session; -import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.User; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.server.IntegratedServer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import xyz.srnyx.javautilities.MiscUtility; @@ -44,8 +44,8 @@ public DiscordRPC(@NotNull EventUtils mod) { this.mod = mod; this.client.setListener(new CustomIPCListener(this)); this.playerUrl = mod.authManager.player != null && mod.authManager.player.player.discord != null && mod.authManager.player.player.discord.id != null - ? "https://eventalerts.gg/players/" + mod.authManager.player.player.discord.id - : "https://namemc.com/profile/" + MinecraftClient.getInstance().getSession().getUuidOrNull(); + ? utm("https://eventalerts.gg/players/" + mod.authManager.player.player.discord.id, "player") + : "https://namemc.com/profile/" + Minecraft.getInstance().getUser().getProfileId(); refreshConnection(); } @@ -98,9 +98,9 @@ public void refresh() { private EAAction getNewPresence() { final Presence newPresence = new Presence(); - final MinecraftClient client = MinecraftClient.getInstance(); - final IntegratedServer clientServer = client.getServer(); - final ServerInfo multiplayerServer = client.getCurrentServerEntry(); + final Minecraft client = Minecraft.getInstance(); + final IntegratedServer clientServer = client.getSingleplayerServer(); + final ServerData multiplayerServer = client.getCurrentServer(); if (clientServer != null && clientServer.isRunning()) { // Singleplayer @@ -111,8 +111,8 @@ private EAAction getNewPresence() { } else if (multiplayerServer != null) { // Multiplayer + Event newPresence - .largeImage("https://api.mcstatus.io/v2/icon/" + multiplayerServer.address) - .largeImageUrl("https://eventalerts.gg"); + .largeImage("https://api.mcstatus.io/v2/icon/" + multiplayerServer.ip) + .largeImageUrl(utm("https://eventalerts.gg", "large_image")); if (mod.inEvent != null) { // Event @@ -120,7 +120,7 @@ private EAAction getNewPresence() { status = Status.EVENT; // Event info (details) - final String eventUrl = "https://eventalerts.gg/events/" + (mod.inEvent.event.id != null ? mod.inEvent.event.id : ""); + final String eventUrl = utm("https://eventalerts.gg/events/" + (mod.inEvent.event.id != null ? mod.inEvent.event.id : ""), "event"); newPresence .details("Playing in " + Objects.requireNonNullElse(mod.inEvent.event.title, "an event")) .detailsUrl(eventUrl) @@ -138,7 +138,7 @@ private EAAction getNewPresence() { if (hostName == null && host.discord != null) hostName = host.discord.username; // EA players URL (Discord ID) -> NameMC Minecraft UUID -> event URL - String hostUrl = host.discord != null && host.discord.id != null ? "https://eventalerts.gg/players/" + host.discord.id : null; + String hostUrl = host.discord != null && host.discord.id != null ? utm("https://eventalerts.gg/players/" + host.discord.id, "host") : null; if (hostUrl == null && host.minecraft != null && host.minecraft.uuid != null) hostUrl = "https://namemc.com/profile/" + host.minecraft.uuid; if (hostUrl == null) hostUrl = eventUrl; @@ -177,7 +177,7 @@ private enum Status { */ private class Presence { @NotNull public String details = "Waiting for an event..."; - @NotNull public String detailsUrl = "https://eventalerts.gg"; + @NotNull public String detailsUrl = utm("https://eventalerts.gg", "details"); @NotNull public String state; @NotNull public String stateUrl = playerUrl; @NotNull public String largeImage; @@ -185,12 +185,12 @@ private class Presence { @NotNull public String largeImageUrl = stateUrl; @NotNull public String smallImage = "logo"; @NotNull public String smallImageText = "EventUtils " + BuildProperties.MOD_VERSION; - @NotNull public String smallImageUrl = "https://eventalerts.gg/eventutils"; + @NotNull public String smallImageUrl = utm("https://eventalerts.gg/eventutils", "small_image"); public Presence() { - final Session session = MinecraftClient.getInstance().getSession(); - this.state = "Playing as " + session.getUsername(); - this.largeImage = "https://mc-heads.net/avatar/" + session.getUuidOrNull(); + final User session = Minecraft.getInstance().getUser(); + this.state = "Playing as " + session.getName(); + this.largeImage = "https://mc-heads.net/avatar/" + session.getProfileId(); } public void apply(@NotNull RichPresence.Builder builder) { @@ -273,4 +273,8 @@ public DiscordRPC.Presence smallImageUrl(@NotNull String smallImageUrl) { return this; } } + + private static String utm(@NotNull String url, @NotNull String content) { + return url + (url.contains("?") ? "&" : "?") + "utm_source=discord&utm_medium=rpc&utm_campaign=eventutils&utm_content=" + content; + } } diff --git a/src/main/java/cc/aabss/eventutils/manager/AuthManager.java b/src/main/java/cc/aabss/eventutils/manager/AuthManager.java index 73178d8..5f137ee 100644 --- a/src/main/java/cc/aabss/eventutils/manager/AuthManager.java +++ b/src/main/java/cc/aabss/eventutils/manager/AuthManager.java @@ -8,8 +8,8 @@ import gg.eventalerts.sdk.http.object.body.EUOnlineAuthBody; import gg.eventalerts.sdk.http.object.body.EUOnlineAuthUpdateBody; import gg.eventalerts.sdk.http.object.response.EUOnlineAuthResponse; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.session.Session; +import net.minecraft.client.Minecraft; +import net.minecraft.client.User; import org.jetbrains.annotations.CheckReturnValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,9 +40,9 @@ public EAAction authenticate() { if (heartbeat != null) heartbeat.cancel(false); // Get session and access token - final Session session = MinecraftClient.getInstance().getSession(); + final User session = Minecraft.getInstance().getUser(); final String accessToken = session.getAccessToken(); - if (accessToken == null || accessToken.equals("FabricMC")) { // Development/offline environment + if (accessToken.equals("FabricMC")) { // Development/offline environment player = null; return EAAction.completed(null); } @@ -50,8 +50,8 @@ public EAAction authenticate() { // POST auth final EUOnlineAuthBody body = new EUOnlineAuthBody( session.getAccessToken(), - session.getUuidOrNull(), - session.getUsername(), + session.getProfileId(), + session.getName(), BuildProperties.MOD_VERSION, Objects.requireNonNullElse(EventUtils.MC_VERSION, "unknown")); return mod.http.players.eventUtils.postOnlineAuth(body) diff --git a/src/main/java/cc/aabss/eventutils/manager/EventServerManager.java b/src/main/java/cc/aabss/eventutils/manager/EventServerManager.java index 102156e..11a564d 100644 --- a/src/main/java/cc/aabss/eventutils/manager/EventServerManager.java +++ b/src/main/java/cc/aabss/eventutils/manager/EventServerManager.java @@ -4,9 +4,9 @@ import cc.aabss.eventutils.mixin.ServerListAccessor; import cc.aabss.eventutils.sdk.EventWrapper; import gg.eventalerts.sdk.object.EAEvent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.client.option.ServerList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.multiplayer.ServerList; import org.bson.types.ObjectId; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +37,7 @@ public EventServerManager(@NotNull EventUtils mod) { public boolean isActiveEventServer(@NotNull String ip) { final String ipLower = ip.toLowerCase(); - return activeEventServers.values().stream().anyMatch(info -> info.serverInfo.address.toLowerCase().equals(ipLower)); + return activeEventServers.values().stream().anyMatch(info -> info.serverData.ip.toLowerCase().equals(ipLower)); } public void addEventServer(@NotNull EventWrapper wrapper) { @@ -45,8 +45,6 @@ public void addEventServer(@NotNull EventWrapper wrapper) { EventUtils.LOGGER.debug("Cannot add event server because IP is null: {}", wrapper); return; } - final MinecraftClient client = MinecraftClient.getInstance(); - if (client == null) return; // Don't add if already exists if (activeEventServers.containsKey(wrapper.id)) return; @@ -54,7 +52,7 @@ public void addEventServer(@NotNull EventWrapper wrapper) { // Get time in milliseconds final long timeMillis = wrapper.event instanceof EAEvent eaEvent && eaEvent.time != null ? eaEvent.time.getTime() : System.currentTimeMillis(); - client.execute(() -> { + Minecraft.getInstance().execute(() -> { final ServerList serverList = getServerList(); if (serverList == null) { EventUtils.LOGGER.warn("Server list not available, cannot add event server"); @@ -64,15 +62,15 @@ public void addEventServer(@NotNull EventWrapper wrapper) { final String serverName = EVENT_SERVER_PREFIX + wrapper.title; // Check if server already exists in list - final ServerInfo existing = serverList.get(wrapper.ip); + final ServerData existing = serverList.get(wrapper.ip); if (existing != null) { EventUtils.LOGGER.debug("Event server already present in server list: '{}' -> '{}'", serverName, wrapper.ip); return; } // Create server info - final ServerInfo serverInfo = new ServerInfo(serverName, wrapper.ip, ServerInfo.ServerType.OTHER); - serverInfo.setResourcePackPolicy(ServerInfo.ResourcePackPolicy.PROMPT); + final ServerData serverInfo = new ServerData(serverName, wrapper.ip, ServerData.Type.OTHER); + serverInfo.setResourcePackStatus(ServerData.ServerPackStatus.PROMPT); // Did event start too long ago? final long graceMs = TimeUnit.MINUTES.toMillis(mod.config.event_server_display_minutes); @@ -92,13 +90,13 @@ public void addEventServer(@NotNull EventWrapper wrapper) { removalTasks.put(wrapper.id, MiscUtility.IO_SCHEDULER.schedule(() -> removeEventServer(wrapper.id), removalDelay, TimeUnit.MILLISECONDS)); // Persist changes to disk - serverList.saveFile(); + serverList.save(); EventUtils.LOGGER.debug("Added event server '{}' with IP '{}' to server list, will be removed in {} ms", serverName, wrapper.ip, removalDelay); }); } public void removeEventServer(@NotNull ObjectId eventId) { - final MinecraftClient client = MinecraftClient.getInstance(); + final Minecraft client = Minecraft.getInstance(); if (client != null) client.execute(() -> { // Cancel removal task final ScheduledFuture removalTask = removalTasks.remove(eventId); @@ -116,11 +114,11 @@ public void removeEventServer(@NotNull ObjectId eventId) { } // Remove from server list - serverList.remove(eventServerInfo.serverInfo); + serverList.remove(eventServerInfo.serverData); // Persist removal - serverList.saveFile(); - EventUtils.LOGGER.debug("Removed event server from server list: {}", eventServerInfo.serverInfo.name); + serverList.save(); + EventUtils.LOGGER.debug("Removed event server from server list: {}", eventServerInfo.serverData.name); }); } @@ -136,16 +134,14 @@ public void removeAllEventServers() { @Nullable private ServerList getServerList() { if (gotServerList != null) return gotServerList; - final MinecraftClient client = MinecraftClient.getInstance(); - if (client == null) return null; - gotServerList = new ServerList(client); + gotServerList = new ServerList(Minecraft.getInstance()); try { - gotServerList.loadFile(); + gotServerList.load(); } catch (final Exception e) { EventUtils.LOGGER.error("Failed to load server list from file", e); } return gotServerList; } - private record EventServerInfo(@NotNull ObjectId eventId, @NotNull ServerInfo serverInfo, long eventTime) {} + private record EventServerInfo(@NotNull ObjectId eventId, @NotNull ServerData serverData, long eventTime) {} } diff --git a/src/main/java/cc/aabss/eventutils/manager/GroupManager.java b/src/main/java/cc/aabss/eventutils/manager/GroupManager.java index 8b42a3b..d585885 100644 --- a/src/main/java/cc/aabss/eventutils/manager/GroupManager.java +++ b/src/main/java/cc/aabss/eventutils/manager/GroupManager.java @@ -4,9 +4,9 @@ import cc.aabss.eventutils.config.Group; import cc.aabss.eventutils.versioning.VersionedGameProfile; import com.mojang.authlib.GameProfile; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.EntityType; -import net.minecraft.util.math.Vec3d; +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,11 +52,11 @@ public void cycle() { } private boolean isSelf(@NotNull String name) { - final MinecraftClient client = MinecraftClient.getInstance(); - return client != null && client.player != null && client.player.getName().getString().equalsIgnoreCase(name); + final Minecraft client = Minecraft.getInstance(); + return client.player != null && client.player.getName().getString().equalsIgnoreCase(name); } - public boolean isPlayerVisible(@NotNull GameProfile profile, @Nullable Vec3d position) { + public boolean isPlayerVisible(@NotNull GameProfile profile, @Nullable Vec3 position) { // All visible final Group group = getSelectedGroup(); if (group == null) return true; @@ -72,7 +72,7 @@ public boolean isPlayerVisible(@NotNull GameProfile profile, @Nullable Vec3d pos return group.isPlayerVisible(versionedProfile.getName(), position); } - public boolean isPlayerVisible(@Nullable String name, @Nullable Vec3d position) { + public boolean isPlayerVisible(@Nullable String name, @Nullable Vec3 position) { // All visible final Group group = getSelectedGroup(); if (group == null) return true; @@ -87,7 +87,7 @@ public boolean isPlayerVisible(@Nullable String name, @Nullable Vec3d position) return group.isPlayerVisible(name, position); } - public boolean isEntityVisible(@NotNull EntityType entityType, @Nullable Vec3d position) { + public boolean isEntityVisible(@NotNull EntityType entityType, @Nullable Vec3 position) { // All visible final Group group = getSelectedGroup(); if (group == null) return true; diff --git a/src/main/java/cc/aabss/eventutils/manager/KeybindManager.java b/src/main/java/cc/aabss/eventutils/manager/KeybindManager.java index 7d02c68..47463a9 100644 --- a/src/main/java/cc/aabss/eventutils/manager/KeybindManager.java +++ b/src/main/java/cc/aabss/eventutils/manager/KeybindManager.java @@ -2,96 +2,111 @@ import cc.aabss.eventutils.EventUtils; import cc.aabss.eventutils.config.Group; -import cc.aabss.eventutils.mixin.KeyBindingAccessor; +import cc.aabss.eventutils.mixin.KeyMappingAccessor; import cc.aabss.eventutils.screen.EventInfoScreen; import cc.aabss.eventutils.sdk.EventWrapper; +import cc.aabss.eventutils.versioning.VersionedClient; +import cc.aabss.eventutils.versioning.VersionedLocalPlayer; +import com.mojang.blaze3d.platform.InputConstants; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.network.chat.MutableComponent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; +//? if >= 26.1 { +/*import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper; +*///?} else { +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +//?} //? if >=1.21.11 { /*import cc.aabss.eventutils.BuildProperties; -import net.minecraft.util.Identifier; +import net.minecraft.resources.Identifier; *///?} import java.util.HashMap; import java.util.Map; -import static net.minecraft.text.Text.literal; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; public class KeybindManager { private static final long DEFAULT_COOLDOWN_TIME_MS = 500; //? if >=1.21.11 { - /*@NotNull private static final KeyBinding.Category CATEGORY = KeyBinding.Category.create(Identifier.of(BuildProperties.MOD_ID, BuildProperties.MOD_ID)); - *///? } else { - @NotNull private static final String CATEGORY = "key.category.eventutils"; + /*@NotNull private static final KeyMapping.Category CATEGORY = KeyMapping.Category.register(Identifier.fromNamespaceAndPath(BuildProperties.MOD_ID, BuildProperties.MOD_ID)); + *///?} else { + @NotNull private static final String CATEGORY = "key.category.eventutils.eventutils"; //?} @Nullable private Long windowHandle; - @NotNull public KeyBinding eventInfoKey; + @NotNull public KeyMapping eventInfoKey; @NotNull private final Map lastKeyPresses = new HashMap<>(); @Nullable public EventWrapper lastEventForInfoScreen; public KeybindManager(@NotNull EventUtils mod) { // Keybindings - eventInfoKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + eventInfoKey = register(new KeyMapping( "key.eventutils.eventinfo", - InputUtil.Type.KEYSYM, + InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_F9, CATEGORY)); - final KeyBinding hidePlayersKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + final KeyMapping hidePlayersKey = register(new KeyMapping( "key.eventutils.hideplayers", - InputUtil.Type.KEYSYM, + InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_F10, CATEGORY)); - final KeyBinding testEventKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( + final KeyMapping testEventKey = register(new KeyMapping( "key.eventutils.testevent", - InputUtil.Type.KEYSYM, + InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_SEMICOLON, CATEGORY)); ClientTickEvents.END_CLIENT_TICK.register(client -> { + final VersionedClient vClient = new VersionedClient(client); + // Only allow if no screen or TitleScreen - if (client.currentScreen != null && (!(client.currentScreen instanceof TitleScreen))) return; + if (vClient.screen() != null && (!(vClient.screen() instanceof TitleScreen))) return; // Store Minecraft's window - if (windowHandle == null) windowHandle = client.getWindow().getHandle(); + if (windowHandle == null) { + //? if >=1.21.11 { + /*windowHandle = client.getWindow().handle(); + *///?} else { + windowHandle = client.getWindow().getWindow(); + //?} + } // Event info key if (!eventInfoKey.isUnbound()) { - if (GLFW.glfwGetKey(windowHandle, ((KeyBindingAccessor) eventInfoKey).getBoundKey().getCode()) == GLFW.GLFW_PRESS) { + if (GLFW.glfwGetKey(windowHandle, ((KeyMappingAccessor) eventInfoKey).getKey().getValue()) == GLFW.GLFW_PRESS) { if (canNotPress(eventInfoKey, DEFAULT_COOLDOWN_TIME_MS)) return; EventUtils.LOGGER.debug("Event info key pressed"); // If screen already open, close it - if (client.currentScreen instanceof EventInfoScreen) { - client.setScreen(null); + if (vClient.screen() instanceof EventInfoScreen) { + vClient.setScreen(null); return; } // Open screen if (lastEventForInfoScreen != null) { - client.setScreen(new EventInfoScreen(mod, lastEventForInfoScreen)); + vClient.setScreen(new EventInfoScreen(mod, lastEventForInfoScreen)); return; } // Action bar - if (client.player != null) client.player.sendMessage(Text.translatable("eventutils.no_recent_event.message").formatted(Formatting.RED), true); + if (client.player != null) { + new VersionedLocalPlayer(client.player).sendActionBar(translatable("eventutils.no_recent_event.message").withStyle(ChatFormatting.RED)); + } } } // Developer Mode: simulate test event if (!testEventKey.isUnbound() && mod.config.developer_mode) { - if (GLFW.glfwGetKey(windowHandle, ((KeyBindingAccessor) testEventKey).getBoundKey().getCode()) == GLFW.GLFW_PRESS) { + if (GLFW.glfwGetKey(windowHandle, ((KeyMappingAccessor) testEventKey).getKey().getValue()) == GLFW.GLFW_PRESS) { if (canNotPress(testEventKey, DEFAULT_COOLDOWN_TIME_MS)) return; EventUtils.LOGGER.debug("Test event key pressed"); @@ -103,7 +118,7 @@ public KeybindManager(@NotNull EventUtils mod) { } // Action bar - client.player.sendMessage(Text.literal("Test event simulated! Check your server list and you should see a toast notification.").formatted(Formatting.GREEN), true); + new VersionedLocalPlayer(client.player).sendActionBar(literal("Test event simulated! Check your server list and you should see a toast notification.").withStyle(ChatFormatting.GREEN)); } } @@ -111,7 +126,7 @@ public KeybindManager(@NotNull EventUtils mod) { if (client.player == null) return; // Hide players key - if (hidePlayersKey.wasPressed()) { + if (hidePlayersKey.consumeClick()) { if (canNotPress(hidePlayersKey, 100)) return; EventUtils.LOGGER.debug("Hide players key pressed"); @@ -119,28 +134,33 @@ public KeybindManager(@NotNull EventUtils mod) { mod.groupManager.cycle(); // Action bar - final MutableText message; + final MutableComponent message; final Group group = mod.groupManager.getSelectedGroup(); if (group != null) { message = literal(group.getName()); } else { message = translatable("eventutils.hideplayers.view_revealed"); } - client.player.sendMessage(translatable("eventutils.hideplayers.view_prefix").append(message.formatted(Formatting.GREEN)), true); + new VersionedLocalPlayer(client.player).sendActionBar(translatable("eventutils.hideplayers.view_prefix").append(message.withStyle(ChatFormatting.GREEN))); } }); } - private boolean canNotPress(@NotNull KeyBinding keyBinding, long cooldownTimeMs) { - //? if >=1.21.11 { - /*final String translationKey = keyBinding.getId(); + @NotNull + private KeyMapping register(@NotNull KeyMapping keyMapping) { + //? if >=26.1 { + /*return KeyMappingHelper.registerKeyMapping(keyMapping); *///?} else { - final String translationKey = keyBinding.getTranslationKey(); + return KeyBindingHelper.registerKeyBinding(keyMapping); //?} - final Long lastPressTime = lastKeyPresses.get(translationKey); + } + + private boolean canNotPress(@NotNull KeyMapping keyBinding, long cooldownTimeMs) { + final String name = keyBinding.getName(); + final Long lastPressTime = lastKeyPresses.get(name); final long now = System.currentTimeMillis(); if (lastPressTime != null && now - lastPressTime < cooldownTimeMs) return true; - lastKeyPresses.put(translationKey, now); + lastKeyPresses.put(name, now); return false; } } diff --git a/src/main/java/cc/aabss/eventutils/mixin/EntryListWidgetAccessor.java b/src/main/java/cc/aabss/eventutils/mixin/AbstractSelectionListAccessor.java similarity index 55% rename from src/main/java/cc/aabss/eventutils/mixin/EntryListWidgetAccessor.java rename to src/main/java/cc/aabss/eventutils/mixin/AbstractSelectionListAccessor.java index 208bef9..d57a39b 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/EntryListWidgetAccessor.java +++ b/src/main/java/cc/aabss/eventutils/mixin/AbstractSelectionListAccessor.java @@ -1,12 +1,12 @@ package cc.aabss.eventutils.mixin; -import net.minecraft.client.gui.widget.EntryListWidget; +import net.minecraft.client.gui.components.AbstractSelectionList; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; -@Mixin(EntryListWidget.class) -public interface EntryListWidgetAccessor { +@Mixin(AbstractSelectionList.class) +public interface AbstractSelectionListAccessor { @Invoker("getRowTop") int invokeGetRowTop(int index); } diff --git a/versions/1.21.11/src/main/java/cc/aabss/eventutils/mixin/PlayerEntityRenderStateMixin.java b/src/main/java/cc/aabss/eventutils/mixin/AvatarRenderStateMixin.java similarity index 62% rename from versions/1.21.11/src/main/java/cc/aabss/eventutils/mixin/PlayerEntityRenderStateMixin.java rename to src/main/java/cc/aabss/eventutils/mixin/AvatarRenderStateMixin.java index 2d8e186..e3fa9b0 100644 --- a/versions/1.21.11/src/main/java/cc/aabss/eventutils/mixin/PlayerEntityRenderStateMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/AvatarRenderStateMixin.java @@ -1,13 +1,14 @@ -package cc.aabss.eventutils.mixin; +//? if >=1.21.11 { +/*package cc.aabss.eventutils.mixin; import cc.aabss.eventutils.accessor.PlayerEntityRenderStateAccessor; -import net.minecraft.client.render.entity.state.PlayerEntityRenderState; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; -@Mixin(PlayerEntityRenderState.class) -public abstract class PlayerEntityRenderStateMixin implements PlayerEntityRenderStateAccessor { +@Mixin(AvatarRenderState.class) +public abstract class AvatarRenderStateMixin implements PlayerEntityRenderStateAccessor { @Unique private String eventutils$rawName; @@ -22,3 +23,4 @@ public abstract class PlayerEntityRenderStateMixin implements PlayerEntityRender this.eventutils$rawName = name; } } +*///?} diff --git a/src/main/java/cc/aabss/eventutils/mixin/AvatarRendererMixin.java b/src/main/java/cc/aabss/eventutils/mixin/AvatarRendererMixin.java new file mode 100644 index 0000000..2a387e2 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/mixin/AvatarRendererMixin.java @@ -0,0 +1,24 @@ +//? if >=1.21.11 { +/*package cc.aabss.eventutils.mixin; + +import cc.aabss.eventutils.accessor.PlayerEntityRenderStateAccessor; +import cc.aabss.eventutils.versioning.VersionedGameProfile; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.entity.player.AvatarRenderer; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; +import net.minecraft.world.entity.Avatar; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(AvatarRenderer.class) +public class AvatarRendererMixin { + @Inject(method = "extractRenderState*", at = @At("TAIL")) + private void extractRenderState(Avatar entity, AvatarRenderState renderState, float tickDelta, CallbackInfo ci) { + if (!(entity instanceof AbstractClientPlayer player)) return; + ((PlayerEntityRenderStateAccessor) renderState).eventutils$setRawName(new VersionedGameProfile(player.getGameProfile()).getName()); + } +} +*///?} diff --git a/src/main/java/cc/aabss/eventutils/mixin/ButtonWidgetMixin.java b/src/main/java/cc/aabss/eventutils/mixin/ButtonWidgetMixin.java index 6093158..a2e1e18 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/ButtonWidgetMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/ButtonWidgetMixin.java @@ -1,56 +1,62 @@ package cc.aabss.eventutils.mixin; import cc.aabss.eventutils.EventUtils; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.*; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.PressableWidget; -//? if >=1.21.11 -//import net.minecraft.client.input.AbstractInput; -import net.minecraft.text.Text; +import cc.aabss.eventutils.versioning.VersionedClient; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.ConfirmScreen; +import net.minecraft.client.gui.screens.PauseScreen; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//? if >=1.21.11 { +/*import net.minecraft.client.input.InputWithModifiers; +import org.jetbrains.annotations.NotNull; +*///?} -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; -@Mixin(ButtonWidget.class) -public abstract class ButtonWidgetMixin extends PressableWidget { - public ButtonWidgetMixin(int i, int j, int k, int l, Text text) { +@Mixin(Button.class) +public abstract class ButtonWidgetMixin extends AbstractButton { + public ButtonWidgetMixin(int i, int j, int k, int l, Component text) { super(i, j, k, l, text); } //? if >=1.21.11 { - /*@Shadow public abstract void onPress(AbstractInput abstractInput); + /*@Shadow public abstract void onPress(@NotNull InputWithModifiers input); *///?} else { @Shadow public abstract void onPress(); //?} @Inject(method = "onPress", at = @At("HEAD"), cancellable = true) //? if >=1.21.11 { - /*public void onPress(AbstractInput abstractInput, CallbackInfo ci) { + /*public void onPress(InputWithModifiers input, CallbackInfo ci) { *///?} else { private void onPress(CallbackInfo ci) { //?} if (!EventUtils.MOD.config.confirm_disconnect || !translatable("menu.disconnect").equals(getMessage())) return; - final MinecraftClient client = MinecraftClient.getInstance(); - if (client.world == null || !(client.currentScreen instanceof GameMenuScreen)) return; + final Minecraft client = Minecraft.getInstance(); + final VersionedClient vClient = new VersionedClient(client); + if (client.level == null || !(vClient.screen() instanceof PauseScreen)) return; ci.cancel(); - final Screen current = client.currentScreen; - client.setScreen(new ConfirmScreen(yes -> { + final Screen current = vClient.screen(); + vClient.setScreen(new ConfirmScreen(yes -> { if (yes) { //? if >=1.21.11 { - /*this.onPress(abstractInput); + /*this.onPress(input); *///?} else { this.onPress(); //?} return; } - client.setScreen(current); + vClient.setScreen(current); }, translatable("eventutils.confirm_disconnect.title"), translatable("eventutils.confirm_disconnect.message"))); } } \ No newline at end of file diff --git a/src/main/java/cc/aabss/eventutils/mixin/EntityMixin.java b/src/main/java/cc/aabss/eventutils/mixin/EntityMixin.java index fe71e45..9c652a1 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/EntityMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/EntityMixin.java @@ -1,51 +1,47 @@ package cc.aabss.eventutils.mixin; import cc.aabss.eventutils.EventUtils; -import dev.kikugie.fletching_table.annotation.MixinEnvironment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.UUID; - -@Mixin(Entity.class) @MixinEnvironment(type = MixinEnvironment.Env.MAIN) +@Mixin(Entity.class) public abstract class EntityMixin { - @Shadow public abstract UUID getUuid(); - @Shadow public abstract Text getName(); + @Shadow public abstract Component getName(); @Shadow public abstract EntityType getType(); //? if >=1.21.11 { - /*@Shadow public abstract Vec3d getSyncedPos(); + /*@Shadow public abstract Vec3 trackingPosition(); *///?} else { - @Shadow public abstract Vec3d getPos(); + @Shadow public abstract Vec3 position(); //?} - @Inject(method = "spawnSprintingParticles", at = @At("HEAD"), cancellable = true) - private void spawnSprintingParticles(CallbackInfo ci) { - if (MinecraftClient.getInstance().player == null) return; + @Inject(method = "canSpawnSprintParticle", at = @At("HEAD"), cancellable = true) + private void canSpawnSprintParticle(CallbackInfoReturnable cir) { + if (Minecraft.getInstance().player == null) return; final EntityType type = getType(); // Get position //? if >=1.21.11 { - /*final Vec3d position = getSyncedPos(); + /*final Vec3 position = trackingPosition(); *///?} else { - final Vec3d position = getPos(); + final Vec3 position = position(); //?} - if (((Object) this) instanceof ClientPlayerEntity player) { + if (((Object) this) instanceof LocalPlayer player) { // Players - if (!EventUtils.MOD.groupManager.isPlayerVisible(player.getGameProfile(), position)) ci.cancel(); + if (!EventUtils.MOD.groupManager.isPlayerVisible(player.getGameProfile(), position)) cir.setReturnValue(false); } else { // Entity - if (!EventUtils.MOD.groupManager.isEntityVisible(type, position)) ci.cancel(); + if (!EventUtils.MOD.groupManager.isEntityVisible(type, position)) cir.setReturnValue(false); } } } diff --git a/src/main/java/cc/aabss/eventutils/mixin/EntityRenderDispatcherMixin.java b/src/main/java/cc/aabss/eventutils/mixin/EntityRenderDispatcherMixin.java index 991fddf..469865b 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/EntityRenderDispatcherMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/EntityRenderDispatcherMixin.java @@ -1,54 +1,57 @@ package cc.aabss.eventutils.mixin; import cc.aabss.eventutils.EventUtils; +import com.mojang.blaze3d.vertex.PoseStack; //? if >=1.21.11 { /*import cc.aabss.eventutils.accessor.PlayerEntityRenderStateAccessor; -import net.minecraft.client.render.command.OrderedRenderCommandQueue; -import net.minecraft.client.render.entity.EntityRenderManager; -import net.minecraft.client.render.entity.state.EntityRenderState; -import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.client.render.state.CameraRenderState; -import net.minecraft.entity.EntityType; +import net.minecraft.client.renderer.SubmitNodeCollector; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; +import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.client.renderer.state.CameraRenderState; *///?} else { -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.client.render.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; //?} -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.math.Vec3d; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.world.entity.EntityType; +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; -//? if >=1.21.11 { -/*@Mixin(EntityRenderManager.class) -*///?} else { @Mixin(EntityRenderDispatcher.class) -//?} public class EntityRenderDispatcherMixin { - @Inject(method = "render", at = @At("HEAD"), cancellable = true) + @Inject( + //? if >=1.21.11 { + /*method = "submit*", + *///?} else { + method = "render*", + //?} + at = @At("HEAD"), + cancellable = true) //? if >=1.21.11 { - /*private void render(EntityRenderState renderState, CameraRenderState cameraRenderState, double x, double y, double z, MatrixStack matrixStack, OrderedRenderCommandQueue orderedRenderCommandQueue, CallbackInfo ci) { + /*private void render(EntityRenderState renderState, CameraRenderState cameraRenderState, double x, double y, double z, PoseStack matrixStack, SubmitNodeCollector orderedRenderCommandQueue, CallbackInfo ci) { + *///?} else if >1.21.4 { + /*private void render(E entity, double x, double y, double z, float tickDelta, PoseStack poseStack, MultiBufferSource multiBufferSource, int light, CallbackInfo ci) { *///?} else { - private void render(E entity, double x, double y, double z, float tickDelta, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, CallbackInfo ci) { + private void render(E entity, double x, double y, double z, float tickDelta, float h, PoseStack poseStack, MultiBufferSource multiBufferSource, int light, CallbackInfo ci) { //?} // Get target position //? if >=1.21.11 { - /*final Vec3d position = new Vec3d(renderState.x, renderState.y, renderState.z); + /*final Vec3 position = new Vec3(renderState.x, renderState.y, renderState.z); *///?} else { - final Vec3d position = entity.getSyncedPos(); + final Vec3 position = entity.trackingPosition(); //?} // Player //? if >=1.21.11 { - /*if (renderState instanceof PlayerEntityRenderState playerRenderState) { + /*if (renderState instanceof AvatarRenderState playerRenderState) { final String name = ((PlayerEntityRenderStateAccessor) playerRenderState).eventutils$getRawName(); *///?} else { - if (entity instanceof PlayerEntity player) { + if (entity instanceof Player player) { final String name = player.getName().getString(); //?} diff --git a/src/main/java/cc/aabss/eventutils/mixin/JoinMultiplayerScreenMixin.java b/src/main/java/cc/aabss/eventutils/mixin/JoinMultiplayerScreenMixin.java new file mode 100644 index 0000000..1c9ac02 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/mixin/JoinMultiplayerScreenMixin.java @@ -0,0 +1,68 @@ +package cc.aabss.eventutils.mixin; + +import cc.aabss.eventutils.EventUtils; +import cc.aabss.eventutils.manager.EventServerManager; +//? if >=1.21.11 { +/*import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.minecraft.client.gui.screens.Screen; +import org.spongepowered.asm.mixin.Unique; +*///?} +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; +import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList; +import net.minecraft.client.multiplayer.ServerList; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(JoinMultiplayerScreen.class) +public class JoinMultiplayerScreenMixin { + @Shadow private ServerList servers; + @Shadow protected ServerSelectionList serverSelectionList; + + @Inject(method = "init", at = @At("TAIL")) + private void onInit(CallbackInfo ci) { + // Store reference to server list for EventServerManager + EventUtils.MOD.eventServerManager.gotServerList = servers; + + //? if >=1.21.11 { + /*//? if >=26.1 { + /^ScreenEvents.afterExtract( + ^///?} else { + ScreenEvents.afterRender( + //?} + (Screen) (Object) this).register((screen, context, mouseX, mouseY, delta) -> highlightEventRows(context)); + *///?} + } + + //? if >=1.21.11 { + /*@Unique private void highlightEventRows(GuiGraphics context) { + *///?} else { + @Inject(method = "render", at = @At("TAIL")) + private void highlightEventRows(GuiGraphics context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + //?} + // Row-by-row highlight for event servers + if (serverSelectionList == null) return; + final int left = serverSelectionList.getRowLeft(); + final int right = left + serverSelectionList.getRowWidth(); + final int servers = serverSelectionList.children().size(); + for (int i = 0; i < servers; i++) { + final String label = serverSelectionList.children().get(i).getNarration().getString(); + final String normalized = label.replaceAll("§.", ""); + if (!label.contains(EventServerManager.EVENT_SERVER_PREFIX) && !normalized.contains("[Event] ")) continue; + + final int top = ((AbstractSelectionListAccessor) serverSelectionList).invokeGetRowTop(i); + final int bottom = (i + 1 < servers) + ? ((AbstractSelectionListAccessor) serverSelectionList).invokeGetRowTop(i + 1) - 1 + : top + 36; + + // Subtle highlight overlay so text/icon remain readable + context.fill(left, top, right, bottom, 0x403575E0); + // Accent line on the left for emphasis + context.fill(left, top, left + 2, bottom, 0xFF3575E0); + } + } +} diff --git a/src/main/java/cc/aabss/eventutils/mixin/KeyBindingAccessor.java b/src/main/java/cc/aabss/eventutils/mixin/KeyBindingAccessor.java deleted file mode 100644 index 6cb7bee..0000000 --- a/src/main/java/cc/aabss/eventutils/mixin/KeyBindingAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package cc.aabss.eventutils.mixin; - -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - - -@Mixin(KeyBinding.class) -public interface KeyBindingAccessor { - @Accessor("boundKey") - InputUtil.Key getBoundKey(); -} diff --git a/src/main/java/cc/aabss/eventutils/mixin/KeyMappingAccessor.java b/src/main/java/cc/aabss/eventutils/mixin/KeyMappingAccessor.java new file mode 100644 index 0000000..d70dcbe --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/mixin/KeyMappingAccessor.java @@ -0,0 +1,13 @@ +package cc.aabss.eventutils.mixin; + +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.client.KeyMapping; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + + +@Mixin(KeyMapping.class) +public interface KeyMappingAccessor { + @Accessor("key") + InputConstants.Key getKey(); +} diff --git a/src/main/java/cc/aabss/eventutils/mixin/ClientMixin.java b/src/main/java/cc/aabss/eventutils/mixin/MinecraftMixin.java similarity index 57% rename from src/main/java/cc/aabss/eventutils/mixin/ClientMixin.java rename to src/main/java/cc/aabss/eventutils/mixin/MinecraftMixin.java index 7908a1c..c7e26ca 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/ClientMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/MinecraftMixin.java @@ -1,9 +1,10 @@ package cc.aabss.eventutils.mixin; import cc.aabss.eventutils.EventUtils; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ConfirmScreen; -import net.minecraft.client.gui.screen.Screen; +import cc.aabss.eventutils.versioning.VersionedClient; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.ConfirmScreen; +import net.minecraft.client.gui.screens.Screen; import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWWindowCloseCallback; import org.spongepowered.asm.mixin.Mixin; @@ -11,27 +12,32 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; -@Mixin(MinecraftClient.class) -public class ClientMixin { +@Mixin(Minecraft.class) +public class MinecraftMixin { @Inject(method = "run", at = @At("HEAD")) private void onRun(CallbackInfo ci) { if (!EventUtils.MOD.config.confirm_window_close) return; - final MinecraftClient client = MinecraftClient.getInstance(); - final long handle = client.getWindow().getHandle(); + final Minecraft client = Minecraft.getInstance(); + //? if >=1.21.11 { + /*final long handle = client.getWindow().handle(); + *///?} else { + final long handle = client.getWindow().getWindow(); + //?} final GLFWWindowCloseCallback callback = GLFW.glfwSetWindowCloseCallback(handle, win -> client.execute(() -> { + final VersionedClient vClient = new VersionedClient(client); GLFW.glfwSetWindowShouldClose(handle, false); - final Screen current = client.currentScreen; - client.setScreen(new ConfirmScreen( + final Screen current = vClient.screen(); + vClient.setScreen(new ConfirmScreen( result -> { if (result) { - client.scheduleStop(); + client.stop(); return; } GLFW.glfwSetWindowShouldClose(handle, false); - client.setScreen(current); + vClient.setScreen(current); }, translatable("eventutils.confirm_exit.title"), translatable("eventutils.confirm_exit.message"))); diff --git a/src/main/java/cc/aabss/eventutils/mixin/MultiplayerScreenMixin.java b/src/main/java/cc/aabss/eventutils/mixin/MultiplayerScreenMixin.java deleted file mode 100644 index c63ae86..0000000 --- a/src/main/java/cc/aabss/eventutils/mixin/MultiplayerScreenMixin.java +++ /dev/null @@ -1,69 +0,0 @@ -package cc.aabss.eventutils.mixin; - -import cc.aabss.eventutils.EventUtils; -import cc.aabss.eventutils.manager.EventServerManager; -//? if >=1.21.11 { -/*import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import org.spongepowered.asm.mixin.Unique; -*///? } else { -import net.minecraft.client.gui.DrawContext; -//?} -import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; -import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; -import net.minecraft.client.option.ServerList; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(MultiplayerScreen.class) -public class MultiplayerScreenMixin { - - @Shadow private ServerList serverList; - @Shadow protected MultiplayerServerListWidget serverListWidget; - - @Inject(method = "init", at = @At("TAIL")) - private void onInit(CallbackInfo ci) { - // Store reference to server list for EventServerManager - EventUtils.MOD.eventServerManager.gotServerList = serverList; - - //? if >=1.21.11 - //ScreenEvents.afterRender((Screen) (Object) this).register((screen, context, mouseX, mouseY, delta) -> highlightEventRows(context)); - } - - //? if >=1.21.11 { - /*@Unique private void highlightEventRows(DrawContext context) { - *///?} else { - @Inject(method = "render", at = @At("TAIL")) - private void highlightEventRows(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - //?} - // Row-by-row highlight for event servers - if (serverListWidget == null) return; - final int left = serverListWidget.getRowLeft(); - final int right = left + serverListWidget.getRowWidth(); - final int servers = serverListWidget.children().size(); - for (int i = 0; i < servers; i++) { - final MultiplayerServerListWidget.Entry entry = serverListWidget.children().get(i); - final Text narration = entry.getNarration(); - if (narration == null) continue; - final String label = narration.getString(); - final String normalized = label.replaceAll("§.", ""); - if (!label.contains(EventServerManager.EVENT_SERVER_PREFIX) && !normalized.contains("[Event] ")) continue; - - final int top = ((EntryListWidgetAccessor) serverListWidget).invokeGetRowTop(i); - final int bottom = (i + 1 < servers) - ? ((EntryListWidgetAccessor) serverListWidget).invokeGetRowTop(i + 1) - 1 - : top + 36; - - // Subtle highlight overlay so text/icon remain readable - context.fill(left, top, right, bottom, 0x403575E0); - // Accent line on the left for emphasis - context.fill(left, top, left + 2, bottom, 0xFF3575E0); - } - } -} diff --git a/src/main/java/cc/aabss/eventutils/mixin/PlayerListHudMixin.java b/src/main/java/cc/aabss/eventutils/mixin/PlayerTabOverlayMixin.java similarity index 52% rename from src/main/java/cc/aabss/eventutils/mixin/PlayerListHudMixin.java rename to src/main/java/cc/aabss/eventutils/mixin/PlayerTabOverlayMixin.java index d0028fb..13c0786 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/PlayerListHudMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/PlayerTabOverlayMixin.java @@ -3,15 +3,17 @@ import cc.aabss.eventutils.EventUtils; import cc.aabss.eventutils.plustag.IconRenderer; import cc.aabss.eventutils.plustag.PlusTag; +import cc.aabss.eventutils.sdk.EnrichedPlayer; import cc.aabss.eventutils.versioning.VersionedGameProfile; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.ScoreboardObjective; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.PlayerTabOverlay; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.PlayerInfo; +import net.minecraft.world.scores.Objective; +import net.minecraft.world.scores.Scoreboard; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -23,34 +25,48 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; +import java.time.Duration; import java.util.Collection; +import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; -@Mixin(PlayerListHud.class) -public abstract class PlayerListHudMixin { - @Shadow @Final private MinecraftClient client; +@Mixin(PlayerTabOverlay.class) +public abstract class PlayerTabOverlayMixin { + // Setting higher will delay icons showing up for players joining. Good range: 2-6 seconds + @Unique @NotNull private static final Duration BATCH_POPULATE_DELAY = Duration.ofSeconds(5); + + @Shadow @Final private Minecraft minecraft; // Set true by the per-entry hook below. Used to detect clients (Lunar, Feather, ...) that // replace the vanilla tab list rendering and never hit our injection point. @Unique private static boolean eventutils$iconHookFired = false; @Unique private static int eventutils$rendersWithoutHook = 0; @Unique private static boolean eventutils$loggedIncompatibleClient = false; + @Unique @Nullable private static Long lastBatchPopulate = null; + //? if >=26.1 { + /*@Inject(method = "extractRenderState", at = @At("HEAD")) + *///?} else { @Inject(method = "render", at = @At("HEAD")) - private void eventutils$populatePlayersCache(DrawContext context, int scaledWindowWidth, Scoreboard scoreboard, ScoreboardObjective objective, CallbackInfo ci) { - if (client.player == null) return; - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - if (networkHandler == null) return; - final Collection entries = networkHandler.getListedPlayerListEntries(); + //?} + private void eventutils$populatePlayersCache(GuiGraphics graphics, int screenWidth, Scoreboard scoreboard, Objective displayObjective, CallbackInfo ci) { + if (minecraft.player == null) return; + final ClientPacketListener packetListener = minecraft.getConnection(); + if (packetListener == null) return; + final Collection entries = packetListener.getListedOnlinePlayers(); - // We want to cache on both join AND tab open just in-case any players were missed on-join - EventUtils.MOD.cacheManager.players() - .get(entries.stream() - .map(entry -> new VersionedGameProfile(entry.getProfile()).getId()) - .collect(Collectors.toSet())) - .queue(); + // We want to cache on both join AND tab open just in-case any players were missed on-join. + // This also batch-fetches new players that join within the BATCH_POPULATE_DELAY. + if (lastBatchPopulate == null || System.currentTimeMillis() - lastBatchPopulate > BATCH_POPULATE_DELAY.toMillis()) { + lastBatchPopulate = System.currentTimeMillis(); + EventUtils.MOD.cacheManager.players() + .get(entries.stream() + .map(entry -> new VersionedGameProfile(entry.getProfile()).getId()) + .collect(Collectors.toSet())) + .queue(); + } // If bee icons are on and there are players to draw them on, but our per-entry hook hasn't // fired for a few frames, the client has replaced vanilla tab rendering. Warn once rather @@ -71,43 +87,46 @@ public abstract class PlayerListHudMixin { // and every client that shows a vanilla-style tab list. // arg 2/3 are the name's x/y; the head, when present, occupies the 8px slot immediately to its left. @ModifyArgs( + //? if >=26.1 { + /*method = "extractRenderState", + *///?} else { method = "render", + //?} at = @At(value = "INVOKE", - //? if >=1.21.6 { - /*target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;III)V" + //? if >=26.1 { + /*target = "Lnet/minecraft/client/gui/GuiGraphics;text(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;III)V" + *///?} else if >=1.21.6 { + /*target = "Lnet/minecraft/client/gui/GuiGraphics;drawString(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;III)V" *///?} else { - target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;III)I" + target = "Lnet/minecraft/client/gui/GuiGraphics;drawString(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;III)I" //?} ), require = 0) - private void eventutils$drawBeeIcon(Args args, @Local(argsOnly = true) DrawContext context, @Local PlayerListEntry entry) { + private void eventutils$drawBeeIcon(Args args, @Local(argsOnly = true) GuiGraphics context, @Local PlayerInfo entry) { eventutils$iconHookFired = true; - drawPlusTagNextToName(context, args.get(2), args.get(3), entry); - } - - @Unique - private void drawPlusTagNextToName(DrawContext context, int x, int y, PlayerListEntry entry) { - if (client.player == null) return; + if (minecraft.player == null) return; // Bee icons disabled if (!EventUtils.MOD.config.bee_icons) return; - // Get UUID + // Get UUID and x/y final UUID uuid = new VersionedGameProfile(entry.getProfile()).getId(); + final int x = args.get(2); + final int y = args.get(3); // Self - if (client.player.getUuid().equals(uuid)) { + if (minecraft.player.getUUID().equals(uuid)) { if (EventUtils.MOD.authManager.player != null) drawIcon(context, x, y, EventUtils.MOD.authManager.player.getPlusTag(), true); return; } - EventUtils.MOD.cacheManager.players().get(uuid).queue(cached -> { - if (cached != null) drawIcon(context, x, y, cached.getPlusTag(), cached.isOnline()); - }); + // Don't fetch, only get from cache. Rely on batch-fetch in eventutils$populatePlayersCache. + final Optional cached = EventUtils.MOD.cacheManager.players().peek(uuid); + if (cached != null) cached.ifPresent(player -> drawIcon(context, x, y, player.getPlusTag(), player.isOnline())); } @Unique - private static void drawIcon(DrawContext context, int x, int y, @Nullable PlusTag tag, boolean online) { + private static void drawIcon(GuiGraphics context, int x, int y, @Nullable PlusTag tag, boolean online) { final int iconSize = 10; final int iconX = x - 10 - iconSize; IconRenderer.draw(context, online ? PlusTag.BEE_GREEN : PlusTag.BEE, iconX, y, iconSize); diff --git a/src/main/java/cc/aabss/eventutils/mixin/ServerListAccessor.java b/src/main/java/cc/aabss/eventutils/mixin/ServerListAccessor.java index 27cb538..7a6e267 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/ServerListAccessor.java +++ b/src/main/java/cc/aabss/eventutils/mixin/ServerListAccessor.java @@ -1,7 +1,7 @@ package cc.aabss.eventutils.mixin; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.client.option.ServerList; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.multiplayer.ServerList; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -10,6 +10,6 @@ @Mixin(ServerList.class) public interface ServerListAccessor { - @Accessor("servers") - List getServers(); + @Accessor("serverList") + List getServers(); } diff --git a/src/main/java/cc/aabss/eventutils/mixin/ServerListMixin.java b/src/main/java/cc/aabss/eventutils/mixin/ServerListMixin.java index 7ab608d..e6637a4 100644 --- a/src/main/java/cc/aabss/eventutils/mixin/ServerListMixin.java +++ b/src/main/java/cc/aabss/eventutils/mixin/ServerListMixin.java @@ -2,8 +2,8 @@ import cc.aabss.eventutils.manager.EventServerManager; import cc.aabss.eventutils.EventUtils; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.client.option.ServerList; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.multiplayer.ServerList; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -15,21 +15,21 @@ @Mixin(ServerList.class) public abstract class ServerListMixin { - @Shadow public abstract void remove(ServerInfo server); + @Shadow public abstract void remove(ServerData server); - @Shadow public abstract void saveFile(); + @Shadow public abstract void save(); - @Inject(method = "loadFile", at = @At("TAIL")) + @Inject(method = "load", at = @At("TAIL")) private void loadFile(CallbackInfo ci) { // Remove inactive servers boolean removed = false; - for (final ServerInfo server : new ArrayList<>(((ServerListAccessor) this).getServers())) { + for (final ServerData server : new ArrayList<>(((ServerListAccessor) this).getServers())) { // Remove servers that start with the event server prefix but aren't an active event server - if (server.name.startsWith(EventServerManager.EVENT_SERVER_PREFIX) && !EventUtils.MOD.eventServerManager.isActiveEventServer(server.address)) { + if (server.name.startsWith(EventServerManager.EVENT_SERVER_PREFIX) && !EventUtils.MOD.eventServerManager.isActiveEventServer(server.ip)) { remove(server); removed = true; } } - if (removed) saveFile(); + if (removed) save(); } } diff --git a/src/main/java/cc/aabss/eventutils/plustag/IconRenderer.java b/src/main/java/cc/aabss/eventutils/plustag/IconRenderer.java index a2b7c62..d351e3b 100644 --- a/src/main/java/cc/aabss/eventutils/plustag/IconRenderer.java +++ b/src/main/java/cc/aabss/eventutils/plustag/IconRenderer.java @@ -1,13 +1,17 @@ package cc.aabss.eventutils.plustag; -import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.GuiGraphics; +import org.jetbrains.annotations.NotNull; +//? if >=1.21.11 { +/*import net.minecraft.resources.Identifier; +*///?} else { +import net.minecraft.resources.ResourceLocation; +//?} //? if >=1.21.6 { -/*import net.minecraft.client.gl.RenderPipelines; +/*import net.minecraft.client.renderer.RenderPipelines; *///?} else if >=1.21.4 { -import net.minecraft.client.render.RenderLayer; -//?} -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; +import net.minecraft.client.renderer.RenderType; + //?} /** @@ -20,13 +24,20 @@ public final class IconRenderer { private IconRenderer() {} /** Draw the icon at (x, y) with the given size (e.g. 8 for tab list). Samples full 64x64 texture, scaled to size. */ - public static void draw(@NotNull DrawContext context, @NotNull Identifier texture, int x, int y, int size) { + public static void draw( + @NotNull GuiGraphics context, + //? if >=1.21.11 { + /*@NotNull Identifier texture, + *///?} else { + @NotNull ResourceLocation texture, + //?} + int x, int y, int size) { //? if >=1.21.6 { - /*context.drawTexture(RenderPipelines.GUI_TEXTURED, texture, x, y, 0f, 0f, size, size, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE); + /*context.blit(RenderPipelines.GUI_TEXTURED, texture, x, y, 0f, 0f, size, size, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE); *///?} else if >=1.21.4 { - context.drawTexture(RenderLayer::getGuiTextured, texture, x, y, 0f, 0f, size, size, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE); + context.blit(RenderType::guiTextured, texture, x, y, 0f, 0f, size, size, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE); //?} else { - //context.drawTexture(texture, x, y, 0f, 0f, size, size, TEX_SIZE, TEX_SIZE); - //?} + /*context.blit(texture, x, y, 0f, 0f, size, size, TEX_SIZE, TEX_SIZE); + *///?} } } diff --git a/src/main/java/cc/aabss/eventutils/plustag/PlusTag.java b/src/main/java/cc/aabss/eventutils/plustag/PlusTag.java index 4ff7406..7273508 100644 --- a/src/main/java/cc/aabss/eventutils/plustag/PlusTag.java +++ b/src/main/java/cc/aabss/eventutils/plustag/PlusTag.java @@ -1,11 +1,15 @@ package cc.aabss.eventutils.plustag; -import cc.aabss.eventutils.BuildProperties; import cc.aabss.eventutils.EventUtils; +import cc.aabss.eventutils.versioning.VersionedIdentifier; import gg.eventalerts.sdk.object.EAPlayer; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +//? if >=1.21.11 { +/*import net.minecraft.resources.Identifier; +*///?} else { +import net.minecraft.resources.ResourceLocation; +//?} import java.util.function.Predicate; @@ -30,14 +34,29 @@ public enum PlusTag { WHITE(player -> player.discord != null && player.minecraft != null); - @NotNull public static final Identifier BEE = Identifier.of(BuildProperties.MOD_ID, "textures/bee/bee.png"); - @NotNull public static final Identifier BEE_GREEN = Identifier.of(BuildProperties.MOD_ID, "textures/bee/bee_green.png"); - @NotNull public final Identifier textureId; + //? if >=1.21.11 { + /*@NotNull public static final Identifier BEE + *///?} else { + @NotNull public static final ResourceLocation BEE + //?} + = VersionedIdentifier.of("textures/bee/bee.png"); + //? if >=1.21.11 { + /*@NotNull public static final Identifier BEE_GREEN + *///?} else { + @NotNull public static final ResourceLocation BEE_GREEN + //?} + = VersionedIdentifier.of("textures/bee/bee_green.png"); + + //? if >=1.21.11 { + /*@NotNull public final Identifier textureId; + *///?} else { + @NotNull public final ResourceLocation textureId; + //?} @NotNull public final Predicate isUnlocked; PlusTag(@NotNull Predicate isUnlocked) { - this.textureId = Identifier.of(BuildProperties.MOD_ID, "textures/bee/plus/" + name().toLowerCase() + ".png"); + this.textureId = VersionedIdentifier.of("textures/bee/plus/" + name().toLowerCase() + ".png"); this.isUnlocked = isUnlocked; } diff --git a/src/main/java/cc/aabss/eventutils/screen/EventInfoScreen.java b/src/main/java/cc/aabss/eventutils/screen/EventInfoScreen.java index a0ae051..4ffd477 100644 --- a/src/main/java/cc/aabss/eventutils/screen/EventInfoScreen.java +++ b/src/main/java/cc/aabss/eventutils/screen/EventInfoScreen.java @@ -2,15 +2,16 @@ import cc.aabss.eventutils.EventUtils; import cc.aabss.eventutils.sdk.EventWrapper; +import cc.aabss.eventutils.versioning.VersionedGraphicsGui; import gg.eventalerts.sdk.object.EAEvent; import gg.eventalerts.sdk.object.EAFamousEvent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.OrderedText; -import net.minecraft.text.StringVisitable; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.util.FormattedCharSequence; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -26,39 +27,41 @@ public class EventInfoScreen extends Screen { @NotNull private final EventWrapper event; public EventInfoScreen(@NotNull EventUtils mod, @NotNull EventWrapper event) { - //? if >=1.21.11 { - /*super(Text.translatable(mod.keybindManager.eventInfoKey.getId())); - *///?} else { - super(Text.translatable(mod.keybindManager.eventInfoKey.getTranslationKey())); - //?} + super(Component.translatable(mod.keybindManager.eventInfoKey.getName())); this.event = event; } @Override - public void render(DrawContext drawContext, int i, int j, float f) { + //? if >=26.1 { + /*public void extractRenderState(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float delta) { + *///?} else { + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + //?} + final VersionedGraphicsGui vGraphics = new VersionedGraphicsGui(graphics); + final int boxX = (width - BOX_WIDTH) / 2; final int boxY = (height - BOX_HEIGHT) / 2; final int startX = boxX + (BOX_WIDTH / 2); // Draw box - drawContext.fill(boxX, boxY, boxX + BOX_WIDTH, boxY + BOX_HEIGHT, 0x88000000); + graphics.fill(boxX, boxY, boxX + BOX_WIDTH, boxY + BOX_HEIGHT, 0x88000000); // Draw lines - final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + final Font textRenderer = Minecraft.getInstance().font; int startY = boxY + 5; for (final String line : event.toInfoScreenText()) { // Split long lines into multiple lines - if (textRenderer.getWidth(line) > BOX_WIDTH - 10) { - final List splitLines = textRenderer.wrapLines(StringVisitable.plain(line), BOX_WIDTH - 10); - for (final OrderedText splitLine : splitLines) { - drawContext.drawCenteredTextWithShadow(textRenderer, splitLine, startX, startY, 0xFFFFFFFF); + if (textRenderer.width(line) > BOX_WIDTH - 10) { + final List splitLines = textRenderer.split(FormattedText.of(line), BOX_WIDTH - 10); + for (final FormattedCharSequence splitLine : splitLines) { + vGraphics.drawCenteredString(textRenderer, splitLine, startX, startY, 0xFFFFFFFF); startY += 12; } continue; } // Draw line - drawContext.drawCenteredTextWithShadow(textRenderer, line, startX, startY, 0xFFFFFFFF); + vGraphics.drawCenteredString(textRenderer, line, startX, startY, 0xFFFFFFFF); startY += 12; } } diff --git a/src/main/java/cc/aabss/eventutils/screen/config/ConfigScreen.java b/src/main/java/cc/aabss/eventutils/screen/config/ConfigScreen.java index 28aac47..5c7248d 100644 --- a/src/main/java/cc/aabss/eventutils/screen/config/ConfigScreen.java +++ b/src/main/java/cc/aabss/eventutils/screen/config/ConfigScreen.java @@ -1,23 +1,23 @@ package cc.aabss.eventutils.screen.config; -import cc.aabss.eventutils.BuildProperties; import cc.aabss.eventutils.config.EventType; import cc.aabss.eventutils.EventUtils; import cc.aabss.eventutils.config.EUConfig; import cc.aabss.eventutils.screen.config.group.GroupManagerScreen; +import cc.aabss.eventutils.versioning.VersionedClient; +import cc.aabss.eventutils.versioning.VersionedIdentifier; import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; import dev.isxander.yacl3.api.controller.EnumDropdownControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import dev.isxander.yacl3.api.controller.StringControllerBuilder; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.util.Identifier; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; import org.apache.logging.log4j.spi.StandardLevel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class ConfigScreen { @@ -31,7 +31,7 @@ public static Screen getConfigScreen(@Nullable Screen parent) { .name(translatable("eventutils.config.discord.label")) .description(OptionDescription.createBuilder() .text(translatable("eventutils.config.discord.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/discord_rpc.png"), 351, 165) + .image(VersionedIdentifier.of("textures/config/discord_rpc.png"), 351, 165) .build()) .binding(EUConfig.Defaults.DISCORD_RPC, () -> config.discord_rpc, newValue -> { config.discord_rpc = newValue; @@ -63,7 +63,7 @@ public static Screen getConfigScreen(@Nullable Screen parent) { .name(translatable("eventutils.config.window.label")) .description(OptionDescription.createBuilder() .text(translatable("eventutils.config.window.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/confirm_exit.png"), 950, 272) + .image(VersionedIdentifier.of("textures/config/confirm_exit.png"), 950, 272) .build()) .binding(EUConfig.Defaults.CONFIRM_WINDOW_CLOSE, () -> config.confirm_window_close, newValue -> { config.confirm_window_close = newValue; @@ -75,7 +75,7 @@ public static Screen getConfigScreen(@Nullable Screen parent) { .name(translatable("eventutils.config.disconnect.label")) .description(OptionDescription.createBuilder() .text(translatable("eventutils.config.disconnect.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/confirm_disconnect.png"), 972, 295) + .image(VersionedIdentifier.of("textures/config/confirm_disconnect.png"), 972, 295) .build()) .binding(EUConfig.Defaults.CONFIRM_DISCONNECT, () -> config.confirm_disconnect, newValue -> { config.confirm_disconnect = newValue; @@ -87,7 +87,7 @@ public static Screen getConfigScreen(@Nullable Screen parent) { .name(translatable("eventutils.config.bee_icons.label")) .description(OptionDescription.createBuilder() .text(translatable("eventutils.config.bee_icons.description")) - .image(Identifier.of(BuildProperties.MOD_ID, "textures/config/bee_icons.png"), 404, 88) + .image(VersionedIdentifier.of("textures/config/bee_icons.png"), 404, 88) .build()) .binding(EUConfig.Defaults.BEE_ICONS, () -> config.bee_icons, newValue -> { config.bee_icons = newValue; @@ -99,7 +99,7 @@ public static Screen getConfigScreen(@Nullable Screen parent) { .name(translatable("eventutils.config.groups.manage.label")) .description(OptionDescription.of(translatable("eventutils.config.groups.manage.description"))) .text(translatable("eventutils.config.groups.manage.button")) - .action((yaclScreen, option) -> MinecraftClient.getInstance().setScreen(new GroupManagerScreen(EventUtils.MOD, yaclScreen))) + .action((yaclScreen, option) -> new VersionedClient(Minecraft.getInstance()).setScreen(new GroupManagerScreen(EventUtils.MOD, yaclScreen))) .build()) // Advanced .group(OptionGroup.createBuilder() diff --git a/src/main/java/cc/aabss/eventutils/screen/config/group/EditGroupScreen.java b/src/main/java/cc/aabss/eventutils/screen/config/group/EditGroupScreen.java index 477cfd5..6943ea4 100644 --- a/src/main/java/cc/aabss/eventutils/screen/config/group/EditGroupScreen.java +++ b/src/main/java/cc/aabss/eventutils/screen/config/group/EditGroupScreen.java @@ -11,23 +11,23 @@ import dev.isxander.yacl3.api.controller.EnumControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import dev.isxander.yacl3.api.controller.StringControllerBuilder; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.entity.EntityType; -import net.minecraft.registry.Registries; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.EntityType; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class EditGroupScreen { - @NotNull private static final List ENTITY_TYPES = Registries.ENTITY_TYPE.stream() - .map(entityType -> EntityType.getId(entityType).toString()) + @NotNull private static final List ENTITY_TYPES = BuiltInRegistries.ENTITY_TYPE.stream() + .map(entityType -> EntityType.getKey(entityType).toString()) .toList(); @NotNull @@ -61,9 +61,9 @@ public static Screen getScreen(@NotNull EventUtils mod, @NotNull Screen parent, .range(1, Group.MAX_RADIUS + 1) .step(1) .formatValue(value -> { - final Text valueText = value > Group.MAX_RADIUS + final Component valueText = value > Group.MAX_RADIUS ? translatable("eventutils.config.groups.radius.infinite") - : Text.literal(value.toString()); + : Component.literal(value.toString()); return translatable("eventutils.config.groups.radius.value", valueText); })) .build()) @@ -97,7 +97,7 @@ public static Screen getScreen(@NotNull EventUtils mod, @NotNull Screen parent, group.setPlayers(newValue); mod.config.upsertGroup(group); }) - .initial(new VersionedGameProfile(MinecraftClient.getInstance().getGameProfile()).getName()) + .initial(new VersionedGameProfile(Minecraft.getInstance().getGameProfile()).getName()) .controller(StringControllerBuilder::create) .build()) .group(ListOption.createBuilder() @@ -117,6 +117,6 @@ public static Screen getScreen(@NotNull EventUtils mod, @NotNull Screen parent, private static EnumControllerBuilder getModeController(@NotNull Option option) { return EnumControllerBuilder.create(option) .enumClass(Group.Mode.class) - .formatValue(value -> translatable("eventutils.config.groups.mode." + value.name()).formatted(value.formatting)); + .formatValue(value -> translatable("eventutils.config.groups.mode." + value.name()).withStyle(value.formatting)); } } diff --git a/src/main/java/cc/aabss/eventutils/screen/config/group/GroupManagerScreen.java b/src/main/java/cc/aabss/eventutils/screen/config/group/GroupManagerScreen.java index 5da51de..eb78617 100644 --- a/src/main/java/cc/aabss/eventutils/screen/config/group/GroupManagerScreen.java +++ b/src/main/java/cc/aabss/eventutils/screen/config/group/GroupManagerScreen.java @@ -2,17 +2,19 @@ import cc.aabss.eventutils.EventUtils; import cc.aabss.eventutils.config.Group; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.text.Style; -import net.minecraft.text.TextColor; -import net.minecraft.util.Formatting; +import cc.aabss.eventutils.versioning.VersionedClient; +import cc.aabss.eventutils.versioning.VersionedGraphicsGui; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Style; +import net.minecraft.network.chat.TextColor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static net.minecraft.text.Text.literal; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.literal; +import static net.minecraft.network.chat.Component.translatable; public class GroupManagerScreen extends Screen { @@ -25,13 +27,14 @@ public class GroupManagerScreen extends Screen { @Nullable private final Screen parent; public GroupManagerScreen(@NotNull EventUtils mod, @Nullable Screen parent) { - super(translatable("eventutils.config.groups.manage_title")); + super(translatable("eventutils.config.groups.manage.label")); this.mod = mod; this.parent = parent; } @Override protected void init() { + final VersionedClient vClient = new VersionedClient(minecraft); final int listTop = 40; int i = 0; @@ -40,42 +43,47 @@ protected void init() { if (y >= height - 60) break; i++; - final ButtonWidget editBtn = ButtonWidget.builder( - literal(group.getName()).fillStyle(Style.EMPTY.withColor(TextColor.fromRgb(0xE0E0E0))), - button -> { - if (client != null) client.setScreen(EditGroupScreen.getScreen(mod, this, group)); - } - ).dimensions(PADDING, y, width - PADDING * 2 - REMOVE_WIDTH - 4, 20).build(); - addDrawableChild(editBtn); + final Button editBtn = Button.builder(literal(group.getName()).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(0xE0E0E0))), button -> { + if (minecraft != null) vClient.setScreen(EditGroupScreen.getScreen(mod, this, group)); + }).bounds(PADDING, y, width - PADDING * 2 - REMOVE_WIDTH - 4, 20).build(); + addRenderableWidget(editBtn); - addDrawableChild(ButtonWidget.builder(literal("X").formatted(Formatting.RED), button -> { + addRenderableWidget(Button.builder(literal("X").withStyle(ChatFormatting.RED), button -> { if (mod.groupManager.selectedGroup == group.getUuid()) mod.groupManager.selectedGroup = null; mod.config.groups.remove(group.getUuid()); mod.config.save(); - if (client != null) client.setScreen(new GroupManagerScreen(mod, parent)); - }).dimensions(width - PADDING - REMOVE_WIDTH, y, REMOVE_WIDTH, 20).build()); + if (minecraft != null) vClient.setScreen(new GroupManagerScreen(mod, parent)); + }).bounds(width - PADDING - REMOVE_WIDTH, y, REMOVE_WIDTH, 20).build()); } - final ButtonWidget addBtn = ButtonWidget.builder(translatable("eventutils.config.groups.add"), button -> { + final Button addBtn = Button.builder(translatable("eventutils.config.groups.add"), button -> { mod.config.upsertGroup(new Group()); - if (client != null) client.setScreen(new GroupManagerScreen(mod, parent)); - }).dimensions(width / 2 - BUTTON_WIDTH - 4, height - 32, BUTTON_WIDTH, 20).build(); - addDrawableChild(addBtn); + if (minecraft != null) vClient.setScreen(new GroupManagerScreen(mod, parent)); + }).bounds(width / 2 - BUTTON_WIDTH - 4, height - 32, BUTTON_WIDTH, 20).build(); + addRenderableWidget(addBtn); - addDrawableChild(ButtonWidget.builder(translatable("gui.done"), button -> goBack()) - .dimensions(width / 2 + 4, height - 32, BUTTON_WIDTH, 20).build()); + addRenderableWidget(Button.builder(translatable("gui.done"), button -> goBack()) + .bounds(width / 2 + 4, height - 32, BUTTON_WIDTH, 20).build()); } private void goBack() { - if (client != null) client.setScreen(parent); + if (minecraft != null) new VersionedClient(minecraft).setScreen(parent); } @Override - public void render(@NotNull DrawContext context, int mouseX, int mouseY, float delta) { - context.fill(0, 0, width, height, 0xC0101010); - context.drawCenteredTextWithShadow(textRenderer, title, width / 2, 12, 0xFFFFFF); - super.render(context, mouseX, mouseY, delta); + //? if >=26.1 { + /*public void extractRenderState(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float delta) { + *///?} else { + public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { + //?} + final VersionedGraphicsGui vGraphics = new VersionedGraphicsGui(graphics); + graphics.fill(0, 0, width, height, 0xC0101010); + vGraphics.drawCenteredString(font, title, width / 2, 12, 0xFFFFFF); + //? if >=26.1 { + /*super.extractRenderState(graphics, mouseX, mouseY, delta); + *///?} else { + super.render(graphics, mouseX, mouseY, delta); + //?} } - } diff --git a/src/main/java/cc/aabss/eventutils/sdk/EventWrapper.java b/src/main/java/cc/aabss/eventutils/sdk/EventWrapper.java index 2334c2f..c5ed157 100644 --- a/src/main/java/cc/aabss/eventutils/sdk/EventWrapper.java +++ b/src/main/java/cc/aabss/eventutils/sdk/EventWrapper.java @@ -9,8 +9,8 @@ import cc.aabss.eventutils.utility.MarkdownSanitizer; import gg.eventalerts.sdk.object.EAEvent; import gg.eventalerts.sdk.object.EAFamousEvent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; import org.bson.types.ObjectId; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -180,22 +180,29 @@ public void executeTypeSettings() { // toast if (!toastSent && settings.toasts) { - final MinecraftClient client = MinecraftClient.getInstance(); - if (client != null) { - // Get title - final String prizeTranslation = prize != null ? "eventutils.event.toast.prize.text" : "eventutils.event.toast.prize.none"; - final Text title = Text.translatable("eventutils.event.toast.title", eventType.nameTranslation, Text.translatable(prizeTranslation, prize)).formatted(eventType.color); - - // Get description - final Text description = ip != null ? Text.translatable("eventutils.event.teleport.text", Text.translatable("eventutils.event.teleport.command", eventType.name().toLowerCase()).formatted(eventType.color)) : null; - - // Update metric - mod.stats.eventToastsReceived.incrementAndGet(); - - // Send toast - client.execute(() -> client.getToastManager().add(new NotificationToast(title, description, ip != null))); - toastSent = true; - } + // Get title + final String prizeTranslation = prize != null ? "eventutils.event.toast.prize.text" : "eventutils.event.toast.prize.none"; + final Component title = Component.translatable("eventutils.event.toast.title", eventType.nameTranslation, Component.translatable(prizeTranslation, prize)).withStyle(eventType.color); + + // Get description + final Component description = ip != null ? Component.translatable("eventutils.event.teleport.text", Component.translatable("eventutils.event.teleport.command", eventType.name().toLowerCase()).withStyle(eventType.color)) : null; + + // Update metric + mod.stats.eventToastsReceived.incrementAndGet(); + + // Send toast + final Minecraft client = Minecraft.getInstance(); + client.execute(() -> { + //? if >=26.2 { + /*client.gui.toastManager() + *///? } else if >1.21.1 { + client.getToastManager() + //?} else { + /*client.getToasts() + *///?} + .addToast(new NotificationToast(title, description, ip != null)); + }); + toastSent = true; } // sound diff --git a/src/main/java/cc/aabss/eventutils/stats/Stat.java b/src/main/java/cc/aabss/eventutils/stats/Stat.java new file mode 100644 index 0000000..6b785a4 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/stats/Stat.java @@ -0,0 +1,29 @@ +package cc.aabss.eventutils.stats; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Collection; +import java.util.List; +import java.util.Map; + + +@Target({ElementType.FIELD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Stat { + /** + * Defaults to the field name + */ + String key() default ""; + + /** + * If this is a {@link Collection} or array, the size of the collection will be used as the value + */ + boolean sizeOnly() default false; + + /** + * If this is a {@link Map}, the keys of the map will be used as the value in a {@link List} + */ + boolean mapKeysOnly() default false; +} diff --git a/src/main/java/cc/aabss/eventutils/stats/Statable.java b/src/main/java/cc/aabss/eventutils/stats/Statable.java new file mode 100644 index 0000000..a08d554 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/stats/Statable.java @@ -0,0 +1,13 @@ +package cc.aabss.eventutils.stats; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import org.jetbrains.annotations.Nullable; + + +public interface Statable { + @Nullable + default JsonElement toStat() { + return new JsonPrimitive(toString()); + } +} diff --git a/src/main/java/cc/aabss/eventutils/Stats.java b/src/main/java/cc/aabss/eventutils/stats/Stats.java similarity index 75% rename from src/main/java/cc/aabss/eventutils/Stats.java rename to src/main/java/cc/aabss/eventutils/stats/Stats.java index 3be50da..7f3c0f4 100644 --- a/src/main/java/cc/aabss/eventutils/Stats.java +++ b/src/main/java/cc/aabss/eventutils/stats/Stats.java @@ -1,10 +1,18 @@ -package cc.aabss.eventutils; +package cc.aabss.eventutils.stats; +import cc.aabss.eventutils.BuildProperties; +import cc.aabss.eventutils.EventUtils; +import cc.aabss.eventutils.stats.gson.StatsGson; +import com.google.gson.JsonObject; import dev.faststats.ErrorTracker; import dev.faststats.data.Metric; +import dev.faststats.data.SourceId; import dev.faststats.fabric.FabricContext; +import eu.okaeri.configs.OkaeriConfig; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -29,8 +37,8 @@ public Stats(@NotNull EventUtils mod) { eventsJoined.set(0); }); - // Config TODO: take from annoying api FastStatsLoader.config(...) and StatsGson (adapters too) -// factory.addMetric(Metric.object("config", mod.config::getJson)); + // Config + factory.addMetric(config("config", () -> mod.config)); // WebSocket factory.addMetric(Metric.bool("socket_open", () -> mod.webSocket.isOpen())); @@ -48,4 +56,12 @@ public Stats(@NotNull EventUtils mod) { }) .create(); } + + @NotNull + public static Metric config(@NotNull @SourceId String id, @NotNull Callable<@Nullable OkaeriConfig> callable) { + return Metric.object(id, () -> { + final OkaeriConfig config = callable.call(); + return config == null ? null : StatsGson.GSON.toJsonTree(config, OkaeriConfig.class).getAsJsonObject(); + }); + } } diff --git a/src/main/java/cc/aabss/eventutils/stats/gson/StatsGson.java b/src/main/java/cc/aabss/eventutils/stats/gson/StatsGson.java new file mode 100644 index 0000000..748e2ba --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/stats/gson/StatsGson.java @@ -0,0 +1,21 @@ +package cc.aabss.eventutils.stats.gson; + +import cc.aabss.eventutils.stats.Statable; +import cc.aabss.eventutils.stats.gson.adapter.ConfigAdapter; +import cc.aabss.eventutils.stats.gson.adapter.DurationAdapter; +import cc.aabss.eventutils.stats.gson.adapter.StatableAdapter; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import eu.okaeri.configs.OkaeriConfig; +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; + + +public class StatsGson { + @NotNull public static final Gson GSON = new GsonBuilder() + .registerTypeHierarchyAdapter(OkaeriConfig.class, new ConfigAdapter()) + .registerTypeAdapter(Duration.class, new DurationAdapter()) + .registerTypeHierarchyAdapter(Statable.class, new StatableAdapter()) + .create(); +} diff --git a/src/main/java/cc/aabss/eventutils/stats/gson/adapter/ConfigAdapter.java b/src/main/java/cc/aabss/eventutils/stats/gson/adapter/ConfigAdapter.java new file mode 100644 index 0000000..933f79e --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/stats/gson/adapter/ConfigAdapter.java @@ -0,0 +1,94 @@ +package cc.aabss.eventutils.stats.gson.adapter; + +import cc.aabss.eventutils.stats.Stat; +import cc.aabss.eventutils.stats.gson.StatsGson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import eu.okaeri.configs.OkaeriConfig; +import eu.okaeri.configs.schema.FieldDeclaration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + + +public class ConfigAdapter extends TypeAdapter { + @Override + public void write(@NotNull JsonWriter out, @Nullable OkaeriConfig config) throws IOException { + if (config == null) { + out.nullValue(); + return; + } + + // Build object (not using JsonWriter so that we can check if empty before writing) + final JsonObject json = new JsonObject(); + for (final FieldDeclaration field : config.getDeclaration().getFields()) { + // Get value + final Object value = field.getValue(); + if (value == null) continue; + final Class type = field.getType().getType(); + + // Get @Stat + final Stat stat = field.getAnnotation(Stat.class).orElse(null); + final String key = stat != null && !stat.key().isEmpty() ? stat.key() : field.getName(); + + if (!OkaeriConfig.class.isAssignableFrom(type)) { + // OkaeriConfig instances don't require @Stat + if (stat == null) continue; + + // Array/Collection/Map specials + final boolean isArray = type.isArray(); + final boolean isCollection = Collection.class.isAssignableFrom(type); + final boolean isMap = Map.class.isAssignableFrom(type); + if (isArray || isCollection || isMap) { + // Size-only + if (stat.sizeOnly()) { + // Get size + final int size; + if (isArray) { + // Array + size = Array.getLength(value); + } else if (isCollection) { + // Collection + size = ((Collection) value).size(); + } else { + // Map + size = ((Map) value).size(); + } + + // Put size + json.addProperty(key + "_size", size); + continue; + } + + // Map keys only + if (stat.mapKeysOnly() && isMap) { + json.add(key + "_keys", StatsGson.GSON.toJsonTree(((Map) value).keySet(), Set.class)); + continue; + } + } + } + + // Else (skip null elements and empty objects) + final JsonElement element = StatsGson.GSON.toJsonTree(value, type); + if (!element.isJsonNull() && (!element.isJsonObject() || !element.getAsJsonObject().isEmpty())) { + json.add(key, element); + } + } + + // We don't want empty objects + if (!json.isEmpty()) StatsGson.GSON.toJson(json, out); + } + + @Override @Nullable + public OkaeriConfig read(@NotNull JsonReader in) { + return null; + } +} diff --git a/src/main/java/cc/aabss/eventutils/stats/gson/adapter/DurationAdapter.java b/src/main/java/cc/aabss/eventutils/stats/gson/adapter/DurationAdapter.java new file mode 100644 index 0000000..31e51e5 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/stats/gson/adapter/DurationAdapter.java @@ -0,0 +1,28 @@ +package cc.aabss.eventutils.stats.gson.adapter; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.time.Duration; + + +public class DurationAdapter extends TypeAdapter { + @Override + public void write(@NotNull JsonWriter out, @Nullable Duration value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + + out.value(value.toMillis()); + } + + @Override @NotNull + public Duration read(@NotNull JsonReader in) throws IOException { + return Duration.ofMillis(in.nextLong()); + } +} diff --git a/src/main/java/cc/aabss/eventutils/stats/gson/adapter/StatableAdapter.java b/src/main/java/cc/aabss/eventutils/stats/gson/adapter/StatableAdapter.java new file mode 100644 index 0000000..f54b967 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/stats/gson/adapter/StatableAdapter.java @@ -0,0 +1,36 @@ +package cc.aabss.eventutils.stats.gson.adapter; + +import cc.aabss.eventutils.stats.Statable; +import cc.aabss.eventutils.stats.gson.StatsGson; +import com.google.gson.JsonElement; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + + +public class StatableAdapter extends TypeAdapter { + @Override + public void write(@NotNull JsonWriter out, @Nullable Statable value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + + final JsonElement json = value.toStat(); + if (json == null) { + out.nullValue(); + return; + } + + StatsGson.GSON.toJson(json, out); + } + + @Override @Nullable + public Statable read(@NotNull JsonReader in) { + return null; + } +} diff --git a/src/main/java/cc/aabss/eventutils/utility/ConnectUtility.java b/src/main/java/cc/aabss/eventutils/utility/ConnectUtility.java index 3f91f2d..3818a09 100644 --- a/src/main/java/cc/aabss/eventutils/utility/ConnectUtility.java +++ b/src/main/java/cc/aabss/eventutils/utility/ConnectUtility.java @@ -1,12 +1,12 @@ package cc.aabss.eventutils.utility; import cc.aabss.eventutils.EventUtils; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.MessageScreen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; -import net.minecraft.client.network.ServerAddress; -import net.minecraft.client.network.ServerInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.ConnectScreen; +import net.minecraft.client.gui.screens.GenericMessageScreen; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.multiplayer.resolver.ServerAddress; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,35 +19,34 @@ import java.util.List; import java.util.concurrent.ExecutionException; -import static net.minecraft.text.Text.translatable; +import static net.minecraft.network.chat.Component.translatable; public class ConnectUtility { public static void connect(@NotNull String ip) { - final MinecraftClient client = MinecraftClient.getInstance(); - if (client == null) return; - final ServerInfo currentServer = client.getCurrentServerEntry(); - if (currentServer != null && currentServer.address.equalsIgnoreCase(ip)) return; + final Minecraft client = Minecraft.getInstance(); + final ServerData currentServer = client.getCurrentServer(); + if (currentServer != null && currentServer.ip.equalsIgnoreCase(ip)) return; // Update metric EventUtils.MOD.stats.eventsJoined.incrementAndGet(); final TitleScreen screen = new TitleScreen(); - final ServerAddress address = ServerAddress.parse(ip); + final ServerAddress address = ServerAddress.parseString(ip); client.execute(() -> { try { //? if >=1.21.11 { - /*client.disconnect(new MessageScreen(translatable("multiplayer.disconnect.generic")), false, false); + /*client.disconnect(new GenericMessageScreen(translatable("multiplayer.disconnect.generic")), false, false); *///?} else if >=1.21 { - client.disconnect(new MessageScreen(translatable("multiplayer.disconnect.generic")), false); + client.disconnect(new GenericMessageScreen(translatable("multiplayer.disconnect.generic")), false); //?} else { - /*client.disconnect(new MessageScreen(translatable("multiplayer.disconnect.generic"))); + /*client.disconnect(new GenericMessageScreen(translatable("multiplayer.disconnect.generic"))); *///?} //? if <=1.20.4 { - /*ConnectScreen.connect(screen, client, address, new ServerInfo("EventUtils Event Server", ip, ServerInfo.ServerType.OTHER), true); + /*ConnectScreen.startConnecting(screen, client, address, new ServerData("EventUtils Event Server", ip, ServerData.Type.OTHER), true); *///?} else { - ConnectScreen.connect(screen, client, address, new ServerInfo("EventUtils Event Server", ip, ServerInfo.ServerType.OTHER), true, null); + ConnectScreen.startConnecting(screen, client, address, new ServerData("EventUtils Event Server", ip, ServerData.Type.OTHER), true, null); //?} } catch (final Exception e) { EventUtils.LOGGER.error("Failed to connect to server: {}", e.getMessage()); diff --git a/src/main/java/cc/aabss/eventutils/versioning/VersionedClient.java b/src/main/java/cc/aabss/eventutils/versioning/VersionedClient.java new file mode 100644 index 0000000..073d922 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/versioning/VersionedClient.java @@ -0,0 +1,32 @@ +package cc.aabss.eventutils.versioning; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + + +public class VersionedClient { + @NotNull private final Minecraft client; + + public VersionedClient(@NotNull Minecraft client) { + this.client = client; + } + + @Nullable + public Screen screen() { + //? if >=26.2 { + /*return client.gui.screen(); + *///?} else { + return client.screen; + //?} + } + + public void setScreen(@Nullable Screen screen) { + //? if >=26.2 { + /*client.gui.setScreen(screen); + *///?} else { + client.setScreen(screen); + //?} + } +} diff --git a/src/main/java/cc/aabss/eventutils/versioning/VersionedEntityType.java b/src/main/java/cc/aabss/eventutils/versioning/VersionedEntityType.java new file mode 100644 index 0000000..a7fff82 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/versioning/VersionedEntityType.java @@ -0,0 +1,39 @@ +package cc.aabss.eventutils.versioning; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +//? >=26.2 { +/*import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.Identifier; +*///?} + + +public class VersionedEntityType { + /** + * @param identifier example: {@code minecraft:chicken} + */ + @Nullable + public static EntityType getEntityTypeByIdentifier(@NotNull String identifier) { + try { + return (EntityType) + //? if >=26.2 { + /*BuiltInRegistries.ENTITY_TYPE.getOptional(Identifier.parse(identifier)) + *///?} else { + EntityType.byString(identifier) + //?} + .orElse(null); + } catch (final Exception e) { + return null; + } + } + + /** + * @param name example: {@code chicken} + */ + @Nullable + public static EntityType getEntityTypeByName(@NotNull String name) { + return getEntityTypeByIdentifier("minecraft:" + name); + } +} diff --git a/src/main/java/cc/aabss/eventutils/versioning/VersionedGraphicsGui.java b/src/main/java/cc/aabss/eventutils/versioning/VersionedGraphicsGui.java new file mode 100644 index 0000000..2c2f2dc --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/versioning/VersionedGraphicsGui.java @@ -0,0 +1,62 @@ +package cc.aabss.eventutils.versioning; + +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.util.FormattedCharSequence; +import org.jetbrains.annotations.NotNull; + + +// Not named VersionedGuiGraphics to dodge Stonecutter replacements +public class VersionedGraphicsGui { + @NotNull private final GuiGraphics graphics; + + public VersionedGraphicsGui(@NotNull GuiGraphics graphics) { + this.graphics = graphics; + } + + public void drawString(@NotNull Font font, @NotNull Component text, int x, int y, int color, boolean shadow) { + //? if >=26.1 { + /*graphics.text( + *///? } else { + graphics.drawString( + //?} + font, text, x, y, color, shadow); + } + + public void drawString(@NotNull Font font, @NotNull FormattedCharSequence text, int x, int y, int color, boolean shadow) { + //? if >=26.1 { + /*graphics.text( + *///? } else { + graphics.drawString( + //?} + font, text, x, y, color, shadow); + } + + public void drawCenteredString(@NotNull Font font, @NotNull String text, int x, int y, int color) { + //? if >=26.1 { + /*graphics.centeredText( + *///? } else { + graphics.drawCenteredString( + //?} + font, text, x, y, color); + } + + public void drawCenteredString(@NotNull Font font, @NotNull Component text, int x, int y, int color) { + //? if >=26.1 { + /*graphics.centeredText( + *///? } else { + graphics.drawCenteredString( + //?} + font, text, x, y, color); + } + + public void drawCenteredString(@NotNull Font font, @NotNull FormattedCharSequence text, int x, int y, int color) { + //? if >=26.1 { + /*graphics.centeredText( + *///? } else { + graphics.drawCenteredString( + //?} + font, text, x, y, color); + } +} diff --git a/src/main/java/cc/aabss/eventutils/versioning/VersionedIdentifier.java b/src/main/java/cc/aabss/eventutils/versioning/VersionedIdentifier.java new file mode 100644 index 0000000..bb026fe --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/versioning/VersionedIdentifier.java @@ -0,0 +1,26 @@ +package cc.aabss.eventutils.versioning; + +import cc.aabss.eventutils.BuildProperties; +import org.jetbrains.annotations.NotNull; +//? if >=1.21.11 { +/*import net.minecraft.resources.Identifier; +*///?} else { +import net.minecraft.resources.ResourceLocation; +//?} + + +public class VersionedIdentifier { + @NotNull + //? if >=1.21.11 { + /*public static Identifier of(@NotNull String path) { + return Identifier.fromNamespaceAndPath(BuildProperties.MOD_ID, path); + *///?} else { + public static ResourceLocation of(@NotNull String path) { + //? if >1.20.4 { + return ResourceLocation.fromNamespaceAndPath(BuildProperties.MOD_ID, path); + //?} else { + /*return new ResourceLocation(BuildProperties.MOD_ID, path); + *///?} + //?} + } +} diff --git a/src/main/java/cc/aabss/eventutils/versioning/VersionedLocalPlayer.java b/src/main/java/cc/aabss/eventutils/versioning/VersionedLocalPlayer.java new file mode 100644 index 0000000..b0c1053 --- /dev/null +++ b/src/main/java/cc/aabss/eventutils/versioning/VersionedLocalPlayer.java @@ -0,0 +1,30 @@ +package cc.aabss.eventutils.versioning; + +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; + + +public class VersionedLocalPlayer { + @NotNull private final LocalPlayer player; + + public VersionedLocalPlayer(@NotNull LocalPlayer player) { + this.player = player; + } + + public void sendMessage(@NotNull Component component) { + //? if >=26.1 { + /*player.sendSystemMessage(component); + *///?} else { + player.displayClientMessage(component, false); + //?} + } + + public void sendActionBar(@NotNull Component component) { + //? if >=26.1 { + /*player.sendOverlayMessage(component); + *///?} else { + player.displayClientMessage(component, true); + //?} + } +} diff --git a/src/main/resources/assets/eventutils/lang/en_us.json b/src/main/resources/assets/eventutils/lang/en_us.json index fb4c474..caf9415 100644 --- a/src/main/resources/assets/eventutils/lang/en_us.json +++ b/src/main/resources/assets/eventutils/lang/en_us.json @@ -1,7 +1,9 @@ { "key": { "category": { - "eventutils": "EventUtils" + "eventutils": { + "eventutils": "EventUtils" + } }, "eventutils": { @@ -115,7 +117,7 @@ "command": { "unknown": "Unknown command! Use tab-completion to see available commands.", "no_event_specified": "No event type specified!", - "no_event_found": "No event/IP found for ", + "no_event_found": "No event/IP found for %s", "priority": { "self": "%s§e You have pickup priority %s §ebased on the people around you.", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c7e0f5e..7c48b40 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -6,8 +6,10 @@ "description": "${description}", "authors": ["Event Alerts", "aabss", "srnyx", "pvty", "QWERTZ_EXE"], "contact": { - "repo": "https://github.com/Event-Alerts/EventUtils", - "discord": "https://eventalerts.gg/discord" + "homepage": "https://eventalerts.gg?utm_source=minecraft&utm_medium=fabric_mod_json&utm_campaign=fabric", + "sources": "https://github.com/Event-Alerts/EventUtils", + "issues": "https://github.com/Event-Alerts/EventUtils/issues", + "discord": "https://eventalerts.gg/discord?utm_source=minecraft&utm_medium=fabric_mod_json&utm_campaign=fabric" }, "license": "GPL-3.0", "icon": "assets/eventutils/textures/icon.png", @@ -15,16 +17,19 @@ "depends": { "minecraft": ">=${deps_minecraft}", "fabricloader": ">=${deps_loader}", - "fabric": ">=${deps_fabric_api}", + "${fabric_api_id}": ">=${deps_fabric_api}", "yet_another_config_lib_v3": ">=${deps_yacl}" }, "suggests": { "modmenu": ">=${deps_modmenu}" }, + "mixins": [ + "eventutils.mixins.json" + ], "custom": { "modmenu": { "links": { - "modmenu.discord": "https://eventalerts.gg/discord", + "modmenu.discord": "https://eventalerts.gg/discord?utm_source=minecraft&utm_medium=mod_list&utm_campaign=mod_menu", "modmenu.source": "https://github.com/Event-Alerts/EventUtils" } } diff --git a/stonecutter.properties.toml b/stonecutter.properties.toml index c6232cb..010bf99 100644 --- a/stonecutter.properties.toml +++ b/stonecutter.properties.toml @@ -6,7 +6,7 @@ mod.group = "cc.aabss" loomx.loom_version = "1.17-SNAPSHOT" loomx.loom_remap_plugin = "fabric-loom" -deps.loader = "0.18.4" +deps.loader = "0.19.0" library.java_utilities = "0c7c450" library.semver4j = "6.0.0" @@ -16,45 +16,47 @@ library.discord_ipc = "0.11.3" library.faststats = "0.29.4" +["26.2"] +deps.fabric_api="0.152.1+26.2" +deps.yacl="3.9.4+26.2-fabric" +deps.modmenu="20.0.0" + +["26.1.2"] +deps.fabric_api="0.145.4+26.1.2" +deps.yacl="3.9.2+26.1-fabric" +deps.modmenu="18.0.0" + ["1.21.11"] -mixins = "eventutils-1.21.11.mixin.json" -deps.yarn_mappings="1.21.11+build.1" deps.fabric_api="0.141.0+1.21.11" deps.yacl="3.8.1+1.21.11-fabric" deps.modmenu="17.0.0" ["1.21.6"] -deps.yarn_mappings="1.21.6+build.1" deps.fabric_api="0.128.2+1.21.6" deps.yacl="3.7.1+1.21.6-fabric" deps.modmenu="15.0.0" ["1.21.5"] -deps.yarn_mappings="1.21.5+build.1" deps.fabric_api="0.128.2+1.21.5" deps.yacl="3.7.1+1.21.5-fabric" deps.modmenu="14.0.0" ["1.21.4"] -deps.yarn_mappings="1.21.4+build.7" deps.fabric_api="0.114.0+1.21.4" deps.yacl="3.6.2+1.21.4-fabric" deps.modmenu="13.0.0" ["1.21.1"] -deps.yarn_mappings="1.21.1+build.3" deps.fabric_api="0.102.0+1.21.1" deps.yacl="3.6.0+1.21-fabric" deps.modmenu="11.0.3" ["1.21"] -deps.yarn_mappings="1.21+build.9" deps.fabric_api="0.102.0+1.21" deps.yacl="3.6.0+1.21-fabric" deps.modmenu="11.0.3" ["1.20.4"] -deps.yarn_mappings="1.20.4+build.3" deps.fabric_api="0.97.1+1.20.4" deps.yacl="3.6.0+1.20.4-fabric" deps.modmenu="9.2.0" diff --git a/versions/1.21.11/src/main/java/cc/aabss/eventutils/mixin/PlayerEntityRendererMixin.java b/versions/1.21.11/src/main/java/cc/aabss/eventutils/mixin/PlayerEntityRendererMixin.java deleted file mode 100644 index db645ed..0000000 --- a/versions/1.21.11/src/main/java/cc/aabss/eventutils/mixin/PlayerEntityRendererMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package cc.aabss.eventutils.mixin; - -import cc.aabss.eventutils.accessor.PlayerEntityRenderStateAccessor; -import cc.aabss.eventutils.versioning.VersionedGameProfile; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.entity.PlayerEntityRenderer; -import net.minecraft.client.render.entity.state.PlayerEntityRenderState; -import net.minecraft.entity.PlayerLikeEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - - -@Mixin(PlayerEntityRenderer.class) -public class PlayerEntityRendererMixin { - @Inject(method = "updateRenderState(Lnet/minecraft/entity/PlayerLikeEntity;Lnet/minecraft/client/render/entity/state/PlayerEntityRenderState;F)V", at = @At("TAIL")) - private void updateRenderState(PlayerLikeEntity entity, PlayerEntityRenderState renderState, float tickDelta, CallbackInfo ci) { - if (!(entity instanceof AbstractClientPlayerEntity player)) return; - ((PlayerEntityRenderStateAccessor) renderState).eventutils$setRawName(new VersionedGameProfile(player.getGameProfile()).getName()); - } -}