From eeecedaf7058a8085416aa7b2cbe51f0ca191924 Mon Sep 17 00:00:00 2001 From: Kieran Wallbanks Date: Fri, 27 Jun 2025 12:30:50 +0100 Subject: [PATCH 01/91] build: Bump Java version to 21, remove extra-kotlin module --- bom/build.gradle.kts | 1 - build-logic/build.gradle.kts | 6 +- .../adventure.base-conventions.gradle.kts | 2 +- extra-kotlin/build.gradle.kts | 25 ----- .../adventure/extra/kotlin/ComponentDSL.kt | 106 ------------------ .../extra/kotlin/ComponentExtensions.kt | 56 --------- .../extra/kotlin/HSVLikeExtensions.kt | 56 --------- .../extra/kotlin/JoinConfigurationDSL.kt | 36 ------ .../extra/kotlin/NBTComponentExtensions.kt | 56 --------- .../extra/kotlin/RGBLikeExtensions.kt | 56 --------- .../kyori/adventure/extra/kotlin/StyleDSL.kt | 35 ------ .../adventure/extra/kotlin/StyleExtensions.kt | 37 ------ gradle.properties | 4 +- gradle/libs.versions.toml | 1 - settings.gradle.kts | 1 - text-logger-slf4j/build.gradle.kts | 6 - .../text/logger/slf4j/CallerClassFinder.java | 11 +- .../text/logger/slf4j/CallerClassFinder.java | 41 ------- 18 files changed, 10 insertions(+), 526 deletions(-) delete mode 100644 extra-kotlin/build.gradle.kts delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentDSL.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentExtensions.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/HSVLikeExtensions.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/JoinConfigurationDSL.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/NBTComponentExtensions.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/RGBLikeExtensions.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleDSL.kt delete mode 100644 extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleExtensions.kt delete mode 100644 text-logger-slf4j/src/main/java9/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 11d7367c1..bc1adf219 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -14,7 +14,6 @@ dependencies { sequenceOf( "api", "annotation-processors", - "extra-kotlin", "key", "nbt", "serializer-configurate4", diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 33e0163ec..0df348e63 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -20,14 +20,14 @@ dependencies { } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlin { target { compilerOptions { - jvmTarget = JvmTarget.JVM_11 + jvmTarget = JvmTarget.JVM_21 } } } diff --git a/build-logic/src/main/kotlin/adventure.base-conventions.gradle.kts b/build-logic/src/main/kotlin/adventure.base-conventions.gradle.kts index 53a8df8df..74734b58a 100644 --- a/build-logic/src/main/kotlin/adventure.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/adventure.base-conventions.gradle.kts @@ -7,7 +7,7 @@ val libs = extensions.getByType(org.gradle.accessors.dm.LibrariesForLibs::class) indra { javaVersions { - minimumToolchain(17) + target(21) val testVersions = (project.property("testJdks") as String) .split(",") .map { it.trim().toInt() } diff --git a/extra-kotlin/build.gradle.kts b/extra-kotlin/build.gradle.kts deleted file mode 100644 index 1dc55277e..000000000 --- a/extra-kotlin/build.gradle.kts +++ /dev/null @@ -1,25 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.dsl.KotlinVersion - -plugins { - id("adventure.common-conventions") - alias(libs.plugins.kotlin) -} - -kotlin { - explicitApi() - coreLibrariesVersion = "1.4.32" - compilerOptions { - jvmTarget = JvmTarget.JVM_1_8 - @Suppress("DEPRECATION") - languageVersion = KotlinVersion.KOTLIN_1_6 - } -} - -dependencies { - api(projects.adventureApi) - implementation(libs.kotlin.stdlib) - testImplementation(libs.kotlin.testJunit5) -} - -applyJarMetadata("net.kyori.adventure.extra.kotlin") diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentDSL.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentDSL.kt deleted file mode 100644 index 1ea456b13..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentDSL.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.text.BlockNBTComponent -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.EntityNBTComponent -import net.kyori.adventure.text.KeybindComponent -import net.kyori.adventure.text.ScoreComponent -import net.kyori.adventure.text.SelectorComponent -import net.kyori.adventure.text.StorageNBTComponent -import net.kyori.adventure.text.TextComponent -import net.kyori.adventure.text.TranslatableComponent - -/** - * Builds a new [BlockNBTComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [BlockNBTComponent] - * @since 4.6.0 - */ -public fun blockNBT(builder: BlockNBTComponent.Builder.() -> Unit): BlockNBTComponent = Component.blockNBT(builder) - -/** - * Builds a new [EntityNBTComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [EntityNBTComponent] - * @since 4.6.0 - */ -public fun entityNBT(builder: EntityNBTComponent.Builder.() -> Unit): EntityNBTComponent = Component.entityNBT(builder) - -/** - * Builds a new [KeybindComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [KeybindComponent] - * @since 4.6.0 - */ -public fun keybind(builder: KeybindComponent.Builder.() -> Unit): KeybindComponent = Component.keybind(builder) - -/** - * Builds a new [ScoreComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [ScoreComponent] - * @since 4.6.0 - */ -public fun score(builder: ScoreComponent.Builder.() -> Unit): ScoreComponent = Component.score(builder) - -/** - * Builds a new [SelectorComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [SelectorComponent] - * @since 4.6.0 - */ -public fun selector(builder: SelectorComponent.Builder.() -> Unit): SelectorComponent = Component.selector(builder) - -/** - * Builds a new [StorageNBTComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [StorageNBTComponent] - * @since 4.6.0 - */ -public fun storageNBT(builder: StorageNBTComponent.Builder.() -> Unit): StorageNBTComponent = Component.storageNBT(builder) - -/** - * Builds a new [TextComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [TextComponent] - * @since 4.6.0 - */ -public fun text(builder: TextComponent.Builder.() -> Unit): TextComponent = Component.text(builder) - -/** - * Builds a new [TranslatableComponent] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [TranslatableComponent] - * @since 4.6.0 - */ -public fun translatable(builder: TranslatableComponent.Builder.() -> Unit): TranslatableComponent = Component.translatable(builder) diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentExtensions.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentExtensions.kt deleted file mode 100644 index 98a5c88e5..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/ComponentExtensions.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.ComponentLike -import net.kyori.adventure.text.JoinConfiguration - -/** - * Adds [that] as a child component. - * - * @return a component - * @since 4.6.0 - */ -public operator fun Component.plus(that: ComponentLike): Component = this.append(that) - -/** - * Joins this array of components using the provided [config]. - * - * @param config the join configuration - * @return the resulting component - * @since 4.10.0 - */ -public fun Array.join(config: JoinConfiguration = JoinConfiguration.noSeparators()): Component = - this.toList().join(config) - -/** - * Joins this iterable of components using the provided [config]. - * - * @param config the join configuration - * @return the resulting component - * @since 4.10.0 - */ -public fun Iterable.join(config: JoinConfiguration = JoinConfiguration.noSeparators()): Component = - Component.join(config, this) diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/HSVLikeExtensions.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/HSVLikeExtensions.kt deleted file mode 100644 index 1c57be215..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/HSVLikeExtensions.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.util.HSVLike - -/** - * The [HSVLike.h] component. - * - * Allows for destructuring into `(h, s, v)`. - * - * @return the [HSVLike.h] component - * @since 4.10.0 - */ -public operator fun HSVLike.component1(): Float = h() - -/** - * The [HSVLike.s] component. - * - * Allows for destructuring into `(h, s, v)`. - * - * @return the [HSVLike.s] component - * @since 4.10.0 - */ -public operator fun HSVLike.component2(): Float = s() - -/** - * The [HSVLike.v] component. - * - * Allows for destructuring into `(h, s, v)`. - * - * @return the [HSVLike.v] component - * @since 4.10.0 - */ -public operator fun HSVLike.component3(): Float = v() diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/JoinConfigurationDSL.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/JoinConfigurationDSL.kt deleted file mode 100644 index 1c780b529..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/JoinConfigurationDSL.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.text.JoinConfiguration - -/** - * Builds a new join configuration from the provided [builder]. - * - * @param builder the builder to configure the resulting join configuration - * @return a new join configuration - * @since 4.10.0 - */ -public fun joinConfiguration(builder: JoinConfiguration.Builder.() -> Unit): JoinConfiguration = - JoinConfiguration.builder().also(builder).build() diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/NBTComponentExtensions.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/NBTComponentExtensions.kt deleted file mode 100644 index 26c656637..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/NBTComponentExtensions.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.text.BlockNBTComponent - -/** - * The X component of this world position. - * - * Allows for destructuring into `(x, y, z)`. - * - * @return the X component - * @since 4.10.0 - */ -public operator fun BlockNBTComponent.WorldPos.component1(): BlockNBTComponent.WorldPos.Coordinate = x() - -/** - * The Y component of this world position. - * - * Allows for destructuring into `(x, y, z)`. - * - * @return the Y component - * @since 4.10.0 - */ -public operator fun BlockNBTComponent.WorldPos.component2(): BlockNBTComponent.WorldPos.Coordinate = y() - -/** - * The Z component of this world position. - * - * Allows for destructuring into `(x, y, z)`. - * - * @return the Z component - * @since 4.10.0 - */ -public operator fun BlockNBTComponent.WorldPos.component3(): BlockNBTComponent.WorldPos.Coordinate = z() diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/RGBLikeExtensions.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/RGBLikeExtensions.kt deleted file mode 100644 index e689b8365..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/RGBLikeExtensions.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.util.RGBLike - -/** - * The [RGBLike.red] component. - * - * Allows for destructuring into `(r, g, b)`. - * - * @return the [RGBLike.red] component - * @since 4.6.0 - */ -public operator fun RGBLike.component1(): Int = this.red() - -/** - * The [RGBLike.green] component. - * - * Allows for destructuring into `(r, g, b)`. - * - * @return the [RGBLike.green] component - * @since 4.6.0 - */ -public operator fun RGBLike.component2(): Int = this.green() - -/** - * The [RGBLike.blue] component. - * - * Allows for destructuring into `(r, g, b)`. - * - * @return the [RGBLike.blue] component - * @since 4.6.0 - */ -public operator fun RGBLike.component3(): Int = this.blue() diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleDSL.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleDSL.kt deleted file mode 100644 index b4381d5bf..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleDSL.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.text.format.Style - -/** - * Builds a new [Style] from the specified [builder]. - * - * @param builder the builder to apply values from - * @return a new [Style] - * @since 4.6.0 - */ -public fun style(builder: Style.Builder.() -> Unit): Style = Style.style(builder) diff --git a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleExtensions.kt b/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleExtensions.kt deleted file mode 100644 index 820205d92..000000000 --- a/extra-kotlin/src/main/kotlin/net/kyori/adventure/extra/kotlin/StyleExtensions.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.extra.kotlin - -import net.kyori.adventure.text.format.Style -import org.jetbrains.annotations.Contract - -/** - * Allows editing using [Style.Builder] as the receiver parameter. - * - * @param consumer the consumer to edit this style with - * @return a new style, with the changes applied from this builder - * @since 4.10.0 - */ -@Contract("_ -> new") -public fun Style.edit(consumer: Style.Builder.() -> Unit): Style = edit(consumer) diff --git a/gradle.properties b/gradle.properties index 233e2b05c..d496d5877 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,9 @@ group=net.kyori -version=4.26.0-SNAPSHOT +version=5.0.0-SNAPSHOT description=A user-interface library for Minecraft: Java Edition. org.gradle.parallel=true systemProp.org.gradle.unsafe.kotlin.assignment=true javadocPublishRoot=https://jd.advntr.dev/ -testJdks=8, 17, 21 +testJdks=21, 24 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index df8470290..01622034c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,5 +75,4 @@ zJmh = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" } [plugins] indra-sonatype = { id = "net.kyori.indra.publishing.sonatype", version.ref = "indra" } jmh = { id = "me.champeau.jmh", version.ref = "jmhPlugin" } -kotlin = "org.jetbrains.kotlin.jvm:2.1.20" nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 874eaf09b..81c954bd5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,7 +34,6 @@ sequenceOf( "api", "annotation-processors", "bom", - "extra-kotlin", "key", "nbt", "serializer-configurate4", diff --git a/text-logger-slf4j/build.gradle.kts b/text-logger-slf4j/build.gradle.kts index 5c62a79df..e27f18863 100644 --- a/text-logger-slf4j/build.gradle.kts +++ b/text-logger-slf4j/build.gradle.kts @@ -25,12 +25,6 @@ dependencies { testImplementation(libs.slf4j) } -sourceSets.main { - multirelease { - alternateVersions(9) - } -} - applyJarMetadata("net.kyori.adventure.text.logger.slf4j") eclipse { diff --git a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java index b6cbb7d6a..85ff22a02 100644 --- a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java +++ b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.text.logger.slf4j; -// Java 8 version, see Java 9 version as well final class CallerClassFinder { private CallerClassFinder() { } @@ -33,11 +32,9 @@ static String callingClassName() { } static String callingClassName(final int elementsToSkip) { // elementsToSkip not counting this method - final StackTraceElement[] elements = Thread.currentThread().getStackTrace(); // includes call to getStackTrace() - if (elements.length <= elementsToSkip) { - throw new IllegalArgumentException("Not enough stack elements to skip " + elementsToSkip + " elements"); - } else { - return elements[elementsToSkip + 2].getClassName(); - } + return StackWalker.getInstance().walk(stream -> stream.map(StackWalker.StackFrame::getClassName) + .skip(elementsToSkip + 1) + .findFirst()) + .orElseThrow(() -> new IllegalArgumentException("Not enough stack elements to skip " + elementsToSkip + " elements")); } } diff --git a/text-logger-slf4j/src/main/java9/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java b/text-logger-slf4j/src/main/java9/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java deleted file mode 100644 index 023cb3fc0..000000000 --- a/text-logger-slf4j/src/main/java9/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.text.logger.slf4j; - -// Java 9+ version, see Java 8 version as well -final class CallerClassFinder { - private CallerClassFinder() { - } - - static String callingClassName() { - return callingClassName(2); // this, plus the calling method - } - - static String callingClassName(final int elementsToSkip) { // elementsToSkip not counting this method - return StackWalker.getInstance().walk(stream -> stream.map(StackWalker.StackFrame::getClassName) - .skip(elementsToSkip + 1) - .findFirst()) - .orElseThrow(() -> new IllegalArgumentException("Not enough stack elements to skip " + elementsToSkip + " elements")); - } -} From c4bb366d4e53499b1f9efbb13af46e481330188b Mon Sep 17 00:00:00 2001 From: Kieran Wallbanks Date: Fri, 27 Jun 2025 12:31:12 +0100 Subject: [PATCH 02/91] chore(key): Refactor module to remove deprecations and use modern language features --- .../adventure/key/InvalidKeyException.java | 6 ++-- .../java/net/kyori/adventure/key/Key.java | 7 ++-- .../java/net/kyori/adventure/key/KeyImpl.java | 35 +++---------------- .../net/kyori/adventure/key/KeyedValue.java | 17 --------- .../kyori/adventure/key/KeyedValueImpl.java | 33 +++-------------- .../java/net/kyori/adventure/key/KeyTest.java | 3 ++ 6 files changed, 20 insertions(+), 81 deletions(-) diff --git a/key/src/main/java/net/kyori/adventure/key/InvalidKeyException.java b/key/src/main/java/net/kyori/adventure/key/InvalidKeyException.java index d55bf2612..073a663e5 100644 --- a/key/src/main/java/net/kyori/adventure/key/InvalidKeyException.java +++ b/key/src/main/java/net/kyori/adventure/key/InvalidKeyException.java @@ -23,6 +23,7 @@ */ package net.kyori.adventure.key; +import java.io.Serial; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,6 +33,7 @@ * @since 4.0.0 */ public final class InvalidKeyException extends RuntimeException { + @Serial private static final long serialVersionUID = -5413304087321449434L; private final String keyNamespace; private final String keyValue; @@ -48,7 +50,7 @@ public final class InvalidKeyException extends RuntimeException { * @return a key * @since 4.0.0 */ - public final @NotNull String keyNamespace() { + public @NotNull String keyNamespace() { return this.keyNamespace; } @@ -58,7 +60,7 @@ public final class InvalidKeyException extends RuntimeException { * @return a key * @since 4.0.0 */ - public final @NotNull String keyValue() { + public @NotNull String keyValue() { return this.keyValue; } } diff --git a/key/src/main/java/net/kyori/adventure/key/Key.java b/key/src/main/java/net/kyori/adventure/key/Key.java index dd0769715..f6fad35d2 100644 --- a/key/src/main/java/net/kyori/adventure/key/Key.java +++ b/key/src/main/java/net/kyori/adventure/key/Key.java @@ -122,6 +122,7 @@ public interface Key extends Comparable, Examinable, Namespaced, Keyed { * @throws InvalidKeyException if the namespace or value contains an invalid character * @since 4.4.0 */ + @SuppressWarnings("PatternValidation") // The namespace is tested later. static @NotNull Key key(final @NotNull Namespaced namespaced, @KeyPattern.Value final @NotNull String value) { return key(Objects.requireNonNull(namespaced, "namespaced").namespace(), value); } @@ -136,6 +137,8 @@ public interface Key extends Comparable, Examinable, Namespaced, Keyed { * @since 4.0.0 */ static @NotNull Key key(@KeyPattern.Namespace final @NotNull String namespace, @KeyPattern.Value final @NotNull String value) { + KeyImpl.checkError("namespace", namespace, namespace, value, Key.checkNamespace(namespace), KeyImpl.NAMESPACE_PATTERN); + KeyImpl.checkError("value", value, namespace, value, Key.checkValue(value), KeyImpl.VALUE_PATTERN); return new KeyImpl(namespace, value); } @@ -176,7 +179,7 @@ static boolean parseable(final @Nullable String string) { * @since 4.12.0 */ static boolean parseableNamespace(final @NotNull String namespace) { - return !checkNamespace(namespace).isPresent(); + return checkNamespace(namespace).isEmpty(); } /** @@ -204,7 +207,7 @@ static boolean parseableNamespace(final @NotNull String namespace) { * @since 4.12.0 */ static boolean parseableValue(final @NotNull String value) { - return !checkValue(value).isPresent(); + return checkValue(value).isEmpty(); } /** diff --git a/key/src/main/java/net/kyori/adventure/key/KeyImpl.java b/key/src/main/java/net/kyori/adventure/key/KeyImpl.java index 214ec8033..b5c47e636 100644 --- a/key/src/main/java/net/kyori/adventure/key/KeyImpl.java +++ b/key/src/main/java/net/kyori/adventure/key/KeyImpl.java @@ -35,23 +35,14 @@ import static java.util.Objects.requireNonNull; -final class KeyImpl implements Key { +record KeyImpl(String namespace, String value) implements Key { static final Comparator COMPARATOR = Comparator.comparing(Key::value).thenComparing(Key::namespace); static final @RegExp String NAMESPACE_PATTERN = "[a-z0-9_\\-.]+"; static final @RegExp String VALUE_PATTERN = "[a-z0-9_\\-./]+"; - private final String namespace; - private final String value; - - KeyImpl(final @NotNull String namespace, final @NotNull String value) { - checkError("namespace", namespace, namespace, value, Key.checkNamespace(namespace), NAMESPACE_PATTERN); - checkError("value", value, namespace, value, Key.checkValue(value), VALUE_PATTERN); - this.namespace = requireNonNull(namespace, "namespace"); - this.value = requireNonNull(value, "value"); - } - - private static void checkError(final String name, final String checkPart, final String namespace, final String value, final OptionalInt index, final String pattern) { + static void checkError(final String name, final String checkPart, final String namespace, final String value, final OptionalInt index, final String pattern) { + requireNonNull(checkPart, name); if (index.isPresent()) { final int indexValue = index.getAsInt(); final char character = checkPart.charAt(indexValue); @@ -74,16 +65,6 @@ static boolean allowedInValue(final char character) { return character == '_' || character == '-' || (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9') || character == '.' || character == '/'; } - @Override - public @NotNull String namespace() { - return this.namespace; - } - - @Override - public @NotNull String value() { - return this.value; - } - @Override public @NotNull String asString() { return asString(this.namespace, this.value); @@ -109,18 +90,10 @@ static boolean allowedInValue(final char character) { @Override public boolean equals(final Object other) { if (this == other) return true; - if (!(other instanceof Key)) return false; - final Key that = (Key) other; + if (!(other instanceof Key that)) return false; return Objects.equals(this.namespace, that.namespace()) && Objects.equals(this.value, that.value()); } - @Override - public int hashCode() { - int result = this.namespace.hashCode(); - result = (31 * result) + this.value.hashCode(); - return result; - } - @Override public int compareTo(final @NotNull Key that) { return Key.super.compareTo(that); diff --git a/key/src/main/java/net/kyori/adventure/key/KeyedValue.java b/key/src/main/java/net/kyori/adventure/key/KeyedValue.java index ce8d458af..4b68e4661 100644 --- a/key/src/main/java/net/kyori/adventure/key/KeyedValue.java +++ b/key/src/main/java/net/kyori/adventure/key/KeyedValue.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.key; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import static java.util.Objects.requireNonNull; @@ -48,22 +47,6 @@ public interface KeyedValue extends Keyed { return new KeyedValueImpl<>(key, requireNonNull(value, "value")); } - /** - * Creates a link. - * - * @param key the key - * @param value the value - * @param the value type - * @return the keyed - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #keyedValue(Key, Object)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull KeyedValue of(final @NotNull Key key, final @NotNull T value) { - return new KeyedValueImpl<>(key, requireNonNull(value, "value")); - } - /** * Gets the value. * diff --git a/key/src/main/java/net/kyori/adventure/key/KeyedValueImpl.java b/key/src/main/java/net/kyori/adventure/key/KeyedValueImpl.java index 5ebbbedd3..20c6cacdc 100644 --- a/key/src/main/java/net/kyori/adventure/key/KeyedValueImpl.java +++ b/key/src/main/java/net/kyori/adventure/key/KeyedValueImpl.java @@ -30,38 +30,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -final class KeyedValueImpl implements Examinable, KeyedValue { - private final Key key; - private final T value; - - KeyedValueImpl(final Key key, final T value) { - this.key = key; - this.value = value; - } - - @Override - public @NotNull Key key() { - return this.key; - } - - @Override - public @NotNull T value() { - return this.value; - } +record KeyedValueImpl(Key key, T value) implements Examinable, KeyedValue { @Override public boolean equals(final @Nullable Object other) { if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final KeyedValueImpl that = (KeyedValueImpl) other; - return this.key.equals(that.key) && this.value.equals(that.value); - } - - @Override - public int hashCode() { - int result = this.key.hashCode(); - result = (31 * result) + this.value.hashCode(); - return result; + if (!(other instanceof KeyedValue that)) return false; + return this.key.equals(that.key()) && this.value.equals(that.value()); } @Override @@ -73,7 +48,7 @@ public int hashCode() { } @Override - public String toString() { + public @NotNull String toString() { return this.examine(StringExaminer.simpleEscaping()); } } diff --git a/key/src/test/java/net/kyori/adventure/key/KeyTest.java b/key/src/test/java/net/kyori/adventure/key/KeyTest.java index 04dae38fa..79f5a3434 100644 --- a/key/src/test/java/net/kyori/adventure/key/KeyTest.java +++ b/key/src/test/java/net/kyori/adventure/key/KeyTest.java @@ -53,6 +53,7 @@ void testOfNamespaceAndValueParsed() { assertEquals("empty", key.value()); } + @SuppressWarnings("PatternValidation") // We are testing to ensure this throws an exception. @Test void testOfInvalid() { assertEquals("!", assertThrows(InvalidKeyException.class, () -> Key.key("!")).keyValue()); @@ -115,6 +116,7 @@ void testParseableValue() { assertTrue(Key.parseableValue("some/path")); } + @SuppressWarnings("PatternValidation") // We are testing to ensure this throws an exception. @Test void testNulChar() { assertThrows(InvalidKeyException.class, () -> Key.key("carbon:global\0\0\0")); @@ -125,6 +127,7 @@ void testParseWithEmptyNamespace() { assertEquals(Key.key(Key.MINECRAFT_NAMESPACE, "test"), Key.key(":test")); } + @SuppressWarnings("PatternValidation") // We are testing to ensure this throws an exception. @Test void testKeyWithInvalidCharacter() { assertThrows(InvalidKeyException.class, () -> Key.key("a/b", "a")); From 88ce295494e1749a1f62f40e8192c799eef487d9 Mon Sep 17 00:00:00 2001 From: Kieran Wallbanks Date: Fri, 27 Jun 2025 12:53:50 +0100 Subject: [PATCH 03/91] chore(text-logger-slf4j): Refactor module to use modern language features Also adds a missing `PlatformAPI` annotation and removes an unused method in CallerClassFinder. --- .../adventure/text/logger/slf4j/CallerClassFinder.java | 8 ++------ .../text/logger/slf4j/ComponentLoggerProvider.java | 7 +++++-- .../text/logger/slf4j/UnpackedComponentThrowable.java | 9 ++++----- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java index 85ff22a02..c613f54f5 100644 --- a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java +++ b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/CallerClassFinder.java @@ -28,13 +28,9 @@ private CallerClassFinder() { } static String callingClassName() { - return callingClassName(2); // this, plus the calling method - } - - static String callingClassName(final int elementsToSkip) { // elementsToSkip not counting this method return StackWalker.getInstance().walk(stream -> stream.map(StackWalker.StackFrame::getClassName) - .skip(elementsToSkip + 1) + .skip(2) // Skip this method, plus the calling method. .findFirst()) - .orElseThrow(() -> new IllegalArgumentException("Not enough stack elements to skip " + elementsToSkip + " elements")); + .orElseThrow(() -> new IllegalArgumentException("Not enough stack elements to skip 2 elements")); } } diff --git a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/ComponentLoggerProvider.java b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/ComponentLoggerProvider.java index e1c86baa1..8d3619d04 100644 --- a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/ComponentLoggerProvider.java +++ b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/ComponentLoggerProvider.java @@ -25,6 +25,7 @@ import java.util.function.Function; import net.kyori.adventure.text.Component; +import net.kyori.adventure.util.PlatformAPI; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -34,7 +35,8 @@ * * @since 4.11.0 */ -@ApiStatus.Internal // SPI for platform use only +@ApiStatus.Internal +@PlatformAPI public interface ComponentLoggerProvider { /** * Create a component logger for the provided logger name. @@ -52,10 +54,11 @@ public interface ComponentLoggerProvider { * @since 4.11.0 */ @ApiStatus.NonExtendable + @PlatformAPI interface LoggerHelper { /** - * Create a serializer function that will translate logged output into the system default locale, and then serialize it to plain text. + * Create a serializer function that will translate logged output into the system default locale and then serialize it to plain text. * * @return a plain serializer * @since 4.11.0 diff --git a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/UnpackedComponentThrowable.java b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/UnpackedComponentThrowable.java index 3ebd78dfe..6e11fc141 100644 --- a/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/UnpackedComponentThrowable.java +++ b/text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/UnpackedComponentThrowable.java @@ -23,6 +23,7 @@ */ package net.kyori.adventure.text.logger.slf4j; +import java.io.Serial; import java.util.function.Function; import net.kyori.adventure.text.Component; import net.kyori.adventure.util.ComponentMessageThrowable; @@ -33,7 +34,7 @@ */ @SuppressWarnings("OverrideThrowableToString") final class UnpackedComponentThrowable extends Throwable { - private static final long serialVersionUID = -1L; + @Serial private static final long serialVersionUID = -1L; private final Class backingType; @@ -46,10 +47,8 @@ static Throwable unpack(final Throwable maybeRich, final Function 0) { - for (int i = 0; i < suppressed.length; i++) { - ret.addSuppressed(unpack(suppressed[i], serializer)); - } + for (final Throwable throwable : suppressed) { + ret.addSuppressed(unpack(throwable, serializer)); } return ret; From 1f6b3ec11253419cf56e2e2f404d933824100138 Mon Sep 17 00:00:00 2001 From: Kieran Wallbanks Date: Mon, 30 Jun 2025 13:39:19 +0100 Subject: [PATCH 04/91] chore(api): Initial refactor (minus `text` package) to remove deprecations and use modern language features --- .../kyori/adventure/audience/Audience.java | 187 +------------ .../adventure/audience/EmptyAudience.java | 12 - .../audience/ForwardingAudience.java | 28 +- .../net/kyori/adventure/bossbar/BossBar.java | 74 +---- .../kyori/adventure/bossbar/BossBarImpl.java | 3 - .../bossbar/HackyBossBarPlatformBridge.java | 3 +- .../kyori/adventure/chat/ChatTypeImpl.java | 43 +-- .../kyori/adventure/chat/SignedMessage.java | 7 +- .../adventure/chat/SignedMessageImpl.java | 46 +--- .../kyori/adventure/identity/Identity.java | 2 +- .../adventure/identity/IdentityImpl.java | 28 +- .../net/kyori/adventure/inventory/Book.java | 28 +- .../kyori/adventure/inventory/BookImpl.java | 30 +- .../adventure/nbt/api/BinaryTagHolder.java | 15 - .../nbt/api/BinaryTagHolderImpl.java | 25 +- .../permission/PermissionCheckers.java | 37 +-- .../net/kyori/adventure/pointer/Pointer.java | 3 +- .../kyori/adventure/pointer/PointerImpl.java | 38 +-- .../net/kyori/adventure/pointer/Pointers.java | 5 +- .../kyori/adventure/pointer/PointersImpl.java | 39 +-- .../adventure/pointer/PointersSupplier.java | 4 +- .../pointer/PointersSupplierImpl.java | 63 ++--- .../adventure/resource/ResourcePackInfo.java | 4 +- .../resource/ResourcePackInfoImpl.java | 46 +--- .../resource/ResourcePackRequest.java | 4 +- .../resource/ResourcePackRequestImpl.java | 69 +---- .../java/net/kyori/adventure/sound/Sound.java | 6 +- .../net/kyori/adventure/sound/SoundImpl.java | 5 +- .../net/kyori/adventure/sound/SoundStop.java | 46 +--- .../kyori/adventure/sound/SoundStopImpl.java | 30 +- .../adventure/text/BuildableComponent.java | 1 - .../adventure/text/ComponentBuilder.java | 1 - .../adventure/text/JoinConfiguration.java | 1 - .../adventure/text/TextReplacementConfig.java | 1 - .../adventure/text/TranslatableComponent.java | 1 - .../text/flattener/ComponentFlattener.java | 1 - .../kyori/adventure/text/format/Style.java | 1 - .../java/net/kyori/adventure/title/Title.java | 22 +- .../net/kyori/adventure/title/TitleImpl.java | 115 ++------ .../net/kyori/adventure/title/TitlePart.java | 30 +- .../TitlePartImpl.java} | 44 +-- .../translation/AbstractTranslationStore.java | 12 +- .../translation/GlobalTranslator.java | 14 - .../MessageFormatTranslationStore.java | 2 +- .../translation/TranslationRegistry.java | 260 ------------------ .../adventure/translation/Translator.java | 6 +- .../net/kyori/adventure/util/Buildable.java | 85 ------ .../java/net/kyori/adventure/util/Codec.java | 30 -- .../net/kyori/adventure/util/HSVLike.java | 17 -- .../net/kyori/adventure/util/HSVLikeImpl.java | 44 +-- .../java/net/kyori/adventure/util/Nag.java | 3 +- .../net/kyori/adventure/util/ShadyPines.java | 22 -- .../net/kyori/adventure/util/TriState.java | 30 +- .../kyori/adventure/inventory/BookTest.java | 6 - .../kyori/adventure/pointer/PointersTest.java | 8 - .../kyori/adventure/text/title/TitleTest.java | 15 - .../gson/GsonComponentSerializer.java | 1 - .../legacy/LegacyComponentSerializer.java | 1 - .../plain/PlainComponentSerializer.java | 1 - .../plain/PlainTextComponentSerializer.java | 1 - 60 files changed, 170 insertions(+), 1536 deletions(-) rename api/src/main/java/net/kyori/adventure/{audience/MessageType.java => title/TitlePartImpl.java} (60%) delete mode 100644 api/src/main/java/net/kyori/adventure/translation/TranslationRegistry.java delete mode 100644 api/src/main/java/net/kyori/adventure/util/Buildable.java diff --git a/api/src/main/java/net/kyori/adventure/audience/Audience.java b/api/src/main/java/net/kyori/adventure/audience/Audience.java index 587371fb0..00d344f7d 100644 --- a/api/src/main/java/net/kyori/adventure/audience/Audience.java +++ b/api/src/main/java/net/kyori/adventure/audience/Audience.java @@ -38,8 +38,6 @@ import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.chat.SignedMessage; import net.kyori.adventure.dialog.DialogLike; -import net.kyori.adventure.identity.Identified; -import net.kyori.adventure.identity.Identity; import net.kyori.adventure.inventory.Book; import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.resource.ResourcePackInfo; @@ -52,7 +50,6 @@ import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.title.Title; import net.kyori.adventure.title.TitlePart; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -200,8 +197,6 @@ default void forEachAudience(final @NotNull Consumer action) { * * @param message a message * @see Component - * @see #sendMessage(Identified, ComponentLike) - * @see #sendMessage(Identity, ComponentLike) * @since 4.1.0 */ @ForwardingAudienceOverrideNotRequired @@ -214,180 +209,12 @@ default void sendMessage(final @NotNull ComponentLike message) { * * @param message a message * @see Component - * @see #sendMessage(Identified, Component) - * @see #sendMessage(Identity, Component) * @since 4.1.0 */ - @SuppressWarnings("deprecation") default void sendMessage(final @NotNull Component message) { - this.sendMessage(message, MessageType.SYSTEM); - } - - /** - * Sends a system chat message to this {@link Audience} ignoring the provided {@link MessageType}. - * - * @param message a message - * @param type the type - * @see Component - * @see #sendMessage(Identified, ComponentLike, MessageType) - * @see #sendMessage(Identity, ComponentLike, MessageType) - * @since 4.1.0 - * @deprecated for removal since 4.12.0, {@link MessageType} is deprecated for removal, use {@link #sendMessage(ComponentLike)} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull ComponentLike message, final @NotNull MessageType type) { - this.sendMessage(message.asComponent(), type); - } - - /** - * Sends a system chat message to this {@link Audience} ignoring the provided {@link MessageType}. - * - * @param message a message - * @param type the type - * @see Component - * @see #sendMessage(Identified, Component, MessageType) - * @see #sendMessage(Identity, Component, MessageType) - * @since 4.1.0 - * @deprecated for removal since 4.12.0, {@link MessageType} is deprecated for removal, use {@link #sendMessage(Component)} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Component message, final @NotNull MessageType type) { - this.sendMessage(Identity.nil(), message, type); } /* End: system messages */ - /* Start: unsigned player messages */ - /** - * Sends an unsigned player chat message from the given {@link Identified} to this {@link Audience} with the {@link ChatType#CHAT system} chat type. - * - * @param source the source of the message - * @param message a message - * @see Component - * @since 4.0.0 - * @deprecated since 4.12.0, the client errors on and can reject identified messages without {@link SignedMessage} data, this may be unsupported in the future, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Identified source, final @NotNull ComponentLike message) { - this.sendMessage(source, message.asComponent()); - } - - /** - * Sends an unsigned player chat message from the entity represented by the given {@link Identity} to this {@link Audience} with the {@link ChatType#CHAT system} chat type. - * - * @param source the identity of the source of the message - * @param message a message - * @see Component - * @since 4.0.0 - * @deprecated since 4.12.0, the client errors on and can reject identified messages without {@link SignedMessage} data, this may be unsupported in the future, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Identity source, final @NotNull ComponentLike message) { - this.sendMessage(source, message.asComponent()); - } - - /** - * Sends an unsigned player chat message from the given {@link Identified} to this {@link Audience} with the {@link ChatType#CHAT system} chat type. - * - * @param source the source of the message - * @param message a message - * @see Component - * @since 4.0.0 - * @deprecated since 4.12.0, the client errors on receiving and can reject identified messages without {@link SignedMessage} data, this may be unsupported in the future, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Identified source, final @NotNull Component message) { - this.sendMessage(source, message, MessageType.CHAT); - } - - /** - * Sends an unsigned player chat message from the entity represented by the given {@link Identity} to this {@link Audience} with the {@link ChatType#CHAT system} chat type. - * - * @param source the identity of the source of the message - * @param message a message - * @see Component - * @since 4.0.0 - * @deprecated since 4.12.0, the client errors on receiving and can reject identified messages without {@link SignedMessage} data, this may be unsupported in the future, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Identity source, final @NotNull Component message) { - this.sendMessage(source, message, MessageType.CHAT); - } - - /** - * Sends an unsigned player chat message from the given {@link Identified} to this {@link Audience} with the {@link ChatType} corresponding to the provided {@link MessageType}. - * - * @param source the source of the message - * @param message a message - * @param type the type - * @see Component - * @since 4.0.0 - * @deprecated for removal since 4.12.0, {@link MessageType} is deprecated for removal and the client errors on receiving and can reject identified messages without {@link SignedMessage} data, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Identified source, final @NotNull ComponentLike message, final @NotNull MessageType type) { - this.sendMessage(source, message.asComponent(), type); - } - - /** - * Sends an unsigned player chat message from the entity represented by the given {@link Identity} to this {@link Audience}. - * - * @param source the identity of the source of the message - * @param message a message - * @param type the type - * @see Component - * @since 4.0.0 - * @deprecated for removal since 4.12.0, {@link MessageType} is deprecated for removal and the client errors on receiving and can reject identified messages without {@link SignedMessage} data, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @ForwardingAudienceOverrideNotRequired - default void sendMessage(final @NotNull Identity source, final @NotNull ComponentLike message, final @NotNull MessageType type) { - this.sendMessage(source, message.asComponent(), type); - } - - /** - * Sends an unsigned player chat message from the given {@link Identified} to this {@link Audience} with the {@link ChatType} corresponding to the provided {@link MessageType}. - * - * @param source the source of the message - * @param message a message - * @param type the type - * @see Component - * @since 4.0.0 - * @deprecated for removal since 4.12.0, {@link MessageType} is deprecated for removal and the client errors on receiving and can reject identified messages without {@link SignedMessage} data, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - default void sendMessage(final @NotNull Identified source, final @NotNull Component message, final @NotNull MessageType type) { - this.sendMessage(source.identity(), message, type); - } - - /** - * Sends a player chat message from the entity represented by the given {@link Identity} to this {@link Audience} with the {@link ChatType} corresponding to the provided {@link MessageType}. - * - * @param source the identity of the source of the message - * @param message a message - * @param type the type - * @see Component - * @since 4.0.0 - * @deprecated for removal since 4.12.0, {@link MessageType} is deprecated for removal and the client errors on receiving and can reject identified messages without {@link SignedMessage} data, use {@link #sendMessage(SignedMessage, ChatType.Bound)} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - default void sendMessage(final @NotNull Identity source, final @NotNull Component message, final @NotNull MessageType type) { - // implementation required - } - /* End: unsigned player messages */ - /* Start: disguised player messages */ /** * Sends a message to this {@link Audience} with the provided {@link ChatType.Bound bound chat type}. @@ -397,9 +224,7 @@ default void sendMessage(final @NotNull Identity source, final @NotNull Componen * @since 4.12.0 * @sinceMinecraft 1.19 */ - @SuppressWarnings("deprecation") default void sendMessage(final @NotNull Component message, final ChatType.@NotNull Bound boundChatType) { - this.sendMessage(message, MessageType.CHAT); } /** @@ -425,14 +250,7 @@ default void sendMessage(final @NotNull ComponentLike message, final ChatType.@N * @since 4.12.0 * @sinceMinecraft 1.19 */ - @SuppressWarnings("deprecation") default void sendMessage(final @NotNull SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType) { - final Component content = signedMessage.unsignedContent() != null ? signedMessage.unsignedContent() : Component.text(signedMessage.message()); - if (signedMessage.isSystem()) { - this.sendMessage(content); - } else { - this.sendMessage(signedMessage.identity(), content, MessageType.CHAT); - } } /** @@ -581,7 +399,6 @@ default void showTitle(final @NotNull Title title) { * @param part the part * @param value the value * @param the type of the value of the part - * @throws IllegalArgumentException if a title part that is not in {@link TitlePart} is used * @since 4.9.0 */ default void sendTitlePart(final @NotNull TitlePart part, final @NotNull T value) { @@ -782,7 +599,7 @@ default void removeResourcePacks(final @NotNull ResourcePackRequestLike request) default void removeResourcePacks(final @NotNull ResourcePackRequest request) { final List infos = request.packs(); if (infos.size() == 1) { - this.removeResourcePacks(infos.get(0).id()); + this.removeResourcePacks(infos.getFirst().id()); } else if (infos.isEmpty()) { return; } @@ -791,7 +608,7 @@ default void removeResourcePacks(final @NotNull ResourcePackRequest request) { for (int i = 0; i < otherReqs.length; i++) { otherReqs[i] = infos.get(i + 1).id(); } - this.removeResourcePacks(infos.get(0).id(), otherReqs); + this.removeResourcePacks(infos.getFirst().id(), otherReqs); } /** diff --git a/api/src/main/java/net/kyori/adventure/audience/EmptyAudience.java b/api/src/main/java/net/kyori/adventure/audience/EmptyAudience.java index fe8d354f6..2cf97f9cd 100644 --- a/api/src/main/java/net/kyori/adventure/audience/EmptyAudience.java +++ b/api/src/main/java/net/kyori/adventure/audience/EmptyAudience.java @@ -29,8 +29,6 @@ import java.util.function.Supplier; import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.chat.SignedMessage; -import net.kyori.adventure.identity.Identified; -import net.kyori.adventure.identity.Identity; import net.kyori.adventure.inventory.Book; import net.kyori.adventure.pointer.Pointer; import net.kyori.adventure.resource.ResourcePackInfoLike; @@ -78,16 +76,6 @@ public void sendMessage(final @NotNull ComponentLike message) { public void sendMessage(final @NotNull Component message) { } - @Override - @Deprecated - public void sendMessage(final @NotNull Identified source, final @NotNull Component message, final @NotNull MessageType type) { - } - - @Override - @Deprecated - public void sendMessage(final @NotNull Identity source, final @NotNull Component message, final @NotNull MessageType type) { - } - @Override public void sendMessage(final @NotNull Component message, final ChatType.@NotNull Bound boundChatType) { } diff --git a/api/src/main/java/net/kyori/adventure/audience/ForwardingAudience.java b/api/src/main/java/net/kyori/adventure/audience/ForwardingAudience.java index 177191076..80ad53ea7 100644 --- a/api/src/main/java/net/kyori/adventure/audience/ForwardingAudience.java +++ b/api/src/main/java/net/kyori/adventure/audience/ForwardingAudience.java @@ -35,8 +35,6 @@ import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.chat.SignedMessage; import net.kyori.adventure.dialog.DialogLike; -import net.kyori.adventure.identity.Identified; -import net.kyori.adventure.identity.Identity; import net.kyori.adventure.inventory.Book; import net.kyori.adventure.pointer.Pointer; import net.kyori.adventure.pointer.Pointers; @@ -120,18 +118,6 @@ default void deleteMessage(final SignedMessage.@NotNull Signature signature) { for (final Audience audience : this.audiences()) audience.deleteMessage(signature); } - @Override - @Deprecated - default void sendMessage(final @NotNull Identified source, final @NotNull Component message, final @NotNull MessageType type) { - for (final Audience audience : this.audiences()) audience.sendMessage(source, message, type); - } - - @Override - @Deprecated - default void sendMessage(final @NotNull Identity source, final @NotNull Component message, final @NotNull MessageType type) { - for (final Audience audience : this.audiences()) audience.sendMessage(source, message, type); - } - @Override default void sendActionBar(final @NotNull Component message) { for (final Audience audience : this.audiences()) audience.sendActionBar(message); @@ -253,7 +239,7 @@ interface Single extends ForwardingAudience { * @return {@link #audience()} * @deprecated this audience only supports forwarding to a single audience */ - @Deprecated(/* forRemoval = false */) + @Deprecated @Override default @NotNull Iterable audiences() { return Collections.singleton(this.audience()); @@ -313,18 +299,6 @@ default void deleteMessage(final SignedMessage.@NotNull Signature signature) { this.audience().deleteMessage(signature); } - @Override - @Deprecated - default void sendMessage(final @NotNull Identified source, final @NotNull Component message, final @NotNull MessageType type) { - this.audience().sendMessage(source, message, type); - } - - @Override - @Deprecated - default void sendMessage(final @NotNull Identity source, final @NotNull Component message, final @NotNull MessageType type) { - this.audience().sendMessage(source, message, type); - } - @Override default void sendActionBar(final @NotNull Component message) { this.audience().sendActionBar(message); diff --git a/api/src/main/java/net/kyori/adventure/bossbar/BossBar.java b/api/src/main/java/net/kyori/adventure/bossbar/BossBar.java index 6a35e6a4c..bf56de0f7 100644 --- a/api/src/main/java/net/kyori/adventure/bossbar/BossBar.java +++ b/api/src/main/java/net/kyori/adventure/bossbar/BossBar.java @@ -28,6 +28,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.util.Index; +import net.kyori.adventure.util.PlatformAPI; import net.kyori.examination.Examinable; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; @@ -53,8 +54,7 @@ * * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface BossBar extends Examinable { +public sealed interface BossBar extends Examinable permits BossBarImpl { /** * The minimum value the progress can be. * @@ -67,24 +67,6 @@ public interface BossBar extends Examinable { * @since 4.2.0 */ float MAX_PROGRESS = 1f; - /** - * The minimum value the progress can be. - * - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #MIN_PROGRESS} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - float MIN_PERCENT = MIN_PROGRESS; - /** - * The maximum value the progress can be. - * - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #MAX_PROGRESS} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - float MAX_PERCENT = MAX_PROGRESS; /** * Creates a new bossbar. @@ -205,39 +187,6 @@ public interface BossBar extends Examinable { @Contract("_ -> this") @NotNull BossBar progress(final float progress); - /** - * Gets the progress. - * - *

The progress is a value between 0 and 1.

- * - * @return the progress - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #progress()} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - default float percent() { - return this.progress(); - } - - /** - * Sets the progress. - * - *

The progress is a value between 0 and 1.

- * - * @param progress the progress - * @return the bossbar - * @throws IllegalArgumentException if progress is less than 0 or greater than 1 - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #progress(float)} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract("_ -> this") - @Deprecated - default @NotNull BossBar percent(final float progress) { - return this.progress(progress); - } - /** * Gets the color. * @@ -423,7 +372,8 @@ default float percent() { * * @since 4.0.0 */ - @ApiStatus.OverrideOnly + @ApiStatus.NonExtendable + @PlatformAPI interface Listener { /** * Bossbar name changed. @@ -445,22 +395,6 @@ default void bossBarNameChanged(final @NotNull BossBar bar, final @NotNull Compo * @since 4.0.0 */ default void bossBarProgressChanged(final @NotNull BossBar bar, final float oldProgress, final float newProgress) { - this.bossBarPercentChanged(bar, oldProgress, newProgress); - } - - /** - * Bossbar progress changed. - * - * @param bar the bossbar - * @param oldProgress the old progress - * @param newProgress the new progress - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #bossBarProgressChanged(BossBar, float, float)} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @SuppressWarnings("DeprecatedIsStillUsed") - default void bossBarPercentChanged(final @NotNull BossBar bar, final float oldProgress, final float newProgress) { } /** diff --git a/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java b/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java index 410b5f376..1862b942a 100644 --- a/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java +++ b/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java @@ -37,13 +37,11 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.util.Services; import net.kyori.examination.ExaminableProperty; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static java.util.Objects.requireNonNull; -@SuppressWarnings("deprecation") final class BossBarImpl extends HackyBossBarPlatformBridge implements BossBar { private final List listeners = new CopyOnWriteArrayList<>(); private Component name; @@ -53,7 +51,6 @@ final class BossBarImpl extends HackyBossBarPlatformBridge implements BossBar { private final Set flags = EnumSet.noneOf(Flag.class); @Nullable BossBarImplementation implementation; - @ApiStatus.Internal static final class ImplementationAccessor { @SuppressWarnings("OptionalUsedAsFieldOrParameterType") private static final Optional SERVICE = Services.service(BossBarImplementation.Provider.class); diff --git a/api/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/api/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java index eced6046c..0ed15752d 100644 --- a/api/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java +++ b/api/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java @@ -30,10 +30,9 @@ * This class is a major hack, intended to allow certain platforms a way * to define a platform-native counterpart to an Adventure boss bar. * - * @deprecated not an official API, and may disappear without warning + * @since 4.3.0 */ @ApiStatus.Internal -@Deprecated @PlatformAPI abstract class HackyBossBarPlatformBridge { } diff --git a/api/src/main/java/net/kyori/adventure/chat/ChatTypeImpl.java b/api/src/main/java/net/kyori/adventure/chat/ChatTypeImpl.java index 27c566961..07861b9cf 100644 --- a/api/src/main/java/net/kyori/adventure/chat/ChatTypeImpl.java +++ b/api/src/main/java/net/kyori/adventure/chat/ChatTypeImpl.java @@ -29,51 +29,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -final class ChatTypeImpl implements ChatType { - private final Key key; - - ChatTypeImpl(final @NotNull Key key) { - this.key = key; - } - - @Override - public @NotNull Key key() { - return this.key; - } +record ChatTypeImpl(@NotNull Key key) implements ChatType { @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - static final class BoundImpl implements ChatType.Bound { - private final ChatType chatType; - private final Component name; - private final @Nullable Component target; - - BoundImpl(final ChatType chatType, final Component name, final @Nullable Component target) { - this.chatType = chatType; - this.name = name; - this.target = target; - } - - @Override - public @NotNull ChatType type() { - return this.chatType; - } - - @Override - public @NotNull Component name() { - return this.name; - } - - @Override - public @Nullable Component target() { - return this.target; - } - + record BoundImpl(ChatType type, Component name, @Nullable Component target) implements Bound { @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } } diff --git a/api/src/main/java/net/kyori/adventure/chat/SignedMessage.java b/api/src/main/java/net/kyori/adventure/chat/SignedMessage.java index 2c04527fb..673e1c149 100644 --- a/api/src/main/java/net/kyori/adventure/chat/SignedMessage.java +++ b/api/src/main/java/net/kyori/adventure/chat/SignedMessage.java @@ -31,7 +31,6 @@ import net.kyori.adventure.text.ComponentLike; import net.kyori.examination.Examinable; import net.kyori.examination.ExaminableProperty; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,8 +41,7 @@ * @since 4.12.0 * @sinceMinecraft 1.19 */ -@ApiStatus.NonExtendable -public interface SignedMessage extends Identified, Examinable { +public sealed interface SignedMessage extends Identified, Examinable permits SignedMessageImpl { /** * Creates a signature wrapper. @@ -163,8 +161,7 @@ default boolean canDelete() { * @since 4.12.0 * @sinceMinecraft 1.19 */ - @ApiStatus.NonExtendable - interface Signature extends Examinable { + sealed interface Signature extends Examinable permits SignedMessageImpl.SignatureImpl { /** * Gets the bytes for this signature. diff --git a/api/src/main/java/net/kyori/adventure/chat/SignedMessageImpl.java b/api/src/main/java/net/kyori/adventure/chat/SignedMessageImpl.java index 2548052ca..9bb5d75f5 100644 --- a/api/src/main/java/net/kyori/adventure/chat/SignedMessageImpl.java +++ b/api/src/main/java/net/kyori/adventure/chat/SignedMessageImpl.java @@ -28,32 +28,13 @@ import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; // Used for system messages ONLY -final class SignedMessageImpl implements SignedMessage { +record SignedMessageImpl(String message, Component unsignedContent, Instant timestamp, long salt) implements SignedMessage { static final SecureRandom RANDOM = new SecureRandom(); - private final Instant instant; - private final long salt; - private final String message; - private final Component unsignedContent; - SignedMessageImpl(final String message, final Component unsignedContent) { - this.instant = Instant.now(); - this.salt = RANDOM.nextLong(); - this.message = message; - this.unsignedContent = unsignedContent; - } - - @Override - public @NotNull Instant timestamp() { - return this.instant; - } - - @Override - public long salt() { - return this.salt; + this(message, unsignedContent, Instant.now(), RANDOM.nextLong()); } @Override @@ -61,32 +42,11 @@ public Signature signature() { return null; } - @Override - public @Nullable Component unsignedContent() { - return this.unsignedContent; - } - - @Override - public @NotNull String message() { - return this.message; - } - @Override public @NotNull Identity identity() { return Identity.nil(); } - static final class SignatureImpl implements Signature { - - final byte[] signature; - - SignatureImpl(final byte[] signature) { - this.signature = signature; - } - - @Override - public byte[] bytes() { - return this.signature; - } + record SignatureImpl(byte[] bytes) implements Signature { } } diff --git a/api/src/main/java/net/kyori/adventure/identity/Identity.java b/api/src/main/java/net/kyori/adventure/identity/Identity.java index c49a3e6fe..b707e9879 100644 --- a/api/src/main/java/net/kyori/adventure/identity/Identity.java +++ b/api/src/main/java/net/kyori/adventure/identity/Identity.java @@ -41,7 +41,7 @@ * @since 4.0.0 * @sinceMinecraft 1.16 */ -public interface Identity extends Examinable, Identified { +public sealed interface Identity extends Examinable, Identified permits IdentityImpl, NilIdentity { /** * A pointer to a name. * diff --git a/api/src/main/java/net/kyori/adventure/identity/IdentityImpl.java b/api/src/main/java/net/kyori/adventure/identity/IdentityImpl.java index c121444ba..a904266fa 100644 --- a/api/src/main/java/net/kyori/adventure/identity/IdentityImpl.java +++ b/api/src/main/java/net/kyori/adventure/identity/IdentityImpl.java @@ -27,35 +27,11 @@ import net.kyori.adventure.internal.Internals; import net.kyori.examination.Examinable; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -final class IdentityImpl implements Examinable, Identity { - private final UUID uuid; - - IdentityImpl(final UUID uuid) { - this.uuid = uuid; - } - - @Override - public @NotNull UUID uuid() { - return this.uuid; - } +record IdentityImpl(UUID uuid) implements Examinable, Identity { @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof Identity)) return false; - final Identity that = (Identity) other; - return this.uuid.equals(that.uuid()); - } - - @Override - public int hashCode() { - return this.uuid.hashCode(); - } } diff --git a/api/src/main/java/net/kyori/adventure/inventory/Book.java b/api/src/main/java/net/kyori/adventure/inventory/Book.java index 255517222..1ba204a21 100644 --- a/api/src/main/java/net/kyori/adventure/inventory/Book.java +++ b/api/src/main/java/net/kyori/adventure/inventory/Book.java @@ -30,9 +30,7 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.builder.AbstractBuilder; import net.kyori.adventure.text.Component; -import net.kyori.adventure.util.Buildable; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -47,8 +45,7 @@ * @see Audience#openBook(Book) * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface Book extends Buildable, Examinable { +public sealed interface Book extends Examinable permits BookImpl { /** * Creates a book. * @@ -153,25 +150,12 @@ public interface Book extends Buildable, Examinable { @Contract(value = "_ -> new", pure = true) @NotNull Book pages(final @NotNull List pages); - /** - * Create a new builder initialized with the attributes of this book. - * - * @return the builder - */ - @Override - default @NotNull Builder toBuilder() { - return builder() - .title(this.title()) - .author(this.author()) - .pages(this.pages()); - } - /** * A builder for a {@link Book}. * * @since 4.0.0 */ - interface Builder extends AbstractBuilder, Buildable.Builder { + sealed interface Builder extends AbstractBuilder permits BookImpl.BuilderImpl { /** * Set the title. * @@ -226,13 +210,5 @@ interface Builder extends AbstractBuilder, Buildable.Builder { */ @Contract("_ -> this") @NotNull Builder pages(final @NotNull Collection pages); - - /** - * Builds. - * - * @return a new book - */ - @Override - @NotNull Book build(); } } diff --git a/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java b/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java index 3776935b8..6a21cdc0f 100644 --- a/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java +++ b/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java @@ -35,11 +35,7 @@ import static java.util.Objects.requireNonNull; -final class BookImpl implements Book { - private final Component title; - private final Component author; - private final List pages; - +record BookImpl(Component title, Component author, List pages) implements Book { BookImpl(final @NotNull Component title, final @NotNull Component author, final @NotNull List pages) { this.title = requireNonNull(title, "title"); this.author = requireNonNull(author, "author"); @@ -86,29 +82,11 @@ final class BookImpl implements Book { } @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (!(o instanceof BookImpl)) return false; - final BookImpl that = (BookImpl) o; - return this.title.equals(that.title) - && this.author.equals(that.author) - && this.pages.equals(that.pages); - } - - @Override - public int hashCode() { - int result = this.title.hashCode(); - result = 31 * result + this.author.hashCode(); - result = 31 * result + this.pages.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - static final class BuilderImpl implements Book.Builder { + static final class BuilderImpl implements Builder { private Component title = Component.empty(); private Component author = Component.empty(); private final List pages = new ArrayList<>(); @@ -138,7 +116,7 @@ static final class BuilderImpl implements Book.Builder { } @Override - public @NotNull Builder pages(final @NotNull Component@NotNull... pages) { + public @NotNull Builder pages(final @NotNull Component @NotNull ... pages) { Collections.addAll(this.pages, pages); return this; } diff --git a/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolder.java b/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolder.java index 5b55b1f37..d8da195f2 100644 --- a/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolder.java +++ b/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolder.java @@ -25,7 +25,6 @@ import net.kyori.adventure.text.event.DataComponentValue; import net.kyori.adventure.util.Codec; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -65,20 +64,6 @@ public interface BinaryTagHolder extends DataComponentValue.TagSerializable { return new BinaryTagHolderImpl(string); } - /** - * Creates an encoded binary tag holder. - * - * @param string the encoded binary tag value - * @return the encoded binary tag - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #binaryTagHolder(String)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull BinaryTagHolder of(final @NotNull String string) { - return new BinaryTagHolderImpl(string); - } - /** * Gets the raw string value. * diff --git a/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolderImpl.java b/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolderImpl.java index b15ff520d..a5b00659d 100644 --- a/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolderImpl.java +++ b/api/src/main/java/net/kyori/adventure/nbt/api/BinaryTagHolderImpl.java @@ -28,39 +28,18 @@ import static java.util.Objects.requireNonNull; -final class BinaryTagHolderImpl implements BinaryTagHolder { - private final String string; - +record BinaryTagHolderImpl(String string) implements BinaryTagHolder { BinaryTagHolderImpl(final String string) { this.string = requireNonNull(string, "string"); } - @Override - public @NotNull String string() { - return this.string; - } - @Override public @NotNull T get(final @NotNull Codec codec) throws DX { return codec.decode(this.string); } @Override - public int hashCode() { - return 31 * this.string.hashCode(); - } - - @Override - public boolean equals(final Object that) { - if (!(that instanceof BinaryTagHolderImpl)) { - return false; - } - - return this.string.equals(((BinaryTagHolderImpl) that).string); - } - - @Override - public String toString() { + public @NotNull String toString() { return this.string; } } diff --git a/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java b/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java index f495b1612..a5fcc56e7 100644 --- a/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java +++ b/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java @@ -25,7 +25,6 @@ import net.kyori.adventure.util.TriState; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; final class PermissionCheckers { static final PermissionChecker NOT_SET = new Always(TriState.NOT_SET); @@ -35,34 +34,16 @@ final class PermissionCheckers { private PermissionCheckers() { } - private static final class Always implements PermissionChecker { - private final TriState value; - - private Always(final TriState value) { - this.value = value; - } - - @Override - public @NotNull TriState value(final @NotNull String permission) { - return this.value; - } - - @Override - public String toString() { - return PermissionChecker.class.getSimpleName() + ".always(" + this.value + ")"; - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final Always always = (Always) other; - return this.value == always.value; - } + private record Always(TriState value) implements PermissionChecker { @Override - public int hashCode() { - return this.value.hashCode(); - } + public @NotNull TriState value(final @NotNull String permission) { + return this.value; + } + + @Override + public @NotNull String toString() { + return PermissionChecker.class.getSimpleName() + ".always(" + this.value + ")"; + } } } diff --git a/api/src/main/java/net/kyori/adventure/pointer/Pointer.java b/api/src/main/java/net/kyori/adventure/pointer/Pointer.java index 28fcb97a4..43385139f 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/Pointer.java +++ b/api/src/main/java/net/kyori/adventure/pointer/Pointer.java @@ -25,6 +25,7 @@ import java.util.stream.Stream; import net.kyori.adventure.key.Key; +import net.kyori.adventure.key.Keyed; import net.kyori.examination.Examinable; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; @@ -35,7 +36,7 @@ * @param the value type * @since 4.8.0 */ -public interface Pointer extends Examinable { +public sealed interface Pointer extends Examinable, Keyed permits PointerImpl { /** * Creates a pointer. * diff --git a/api/src/main/java/net/kyori/adventure/pointer/PointerImpl.java b/api/src/main/java/net/kyori/adventure/pointer/PointerImpl.java index 96327c67d..0b01f434b 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/PointerImpl.java +++ b/api/src/main/java/net/kyori/adventure/pointer/PointerImpl.java @@ -26,44 +26,10 @@ import net.kyori.adventure.internal.Internals; import net.kyori.adventure.key.Key; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -final class PointerImpl implements Pointer { - private final Class type; - private final Key key; - - PointerImpl(final Class type, final Key key) { - this.type = type; - this.key = key; - } - - @Override - public @NotNull Class type() { - return this.type; - } +record PointerImpl(Class type, Key key) implements Pointer { @Override - public @NotNull Key key() { - return this.key; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final PointerImpl that = (PointerImpl) other; - return this.type.equals(that.type) && this.key.equals(that.key); - } - - @Override - public int hashCode() { - int result = this.type.hashCode(); - result = (31 * result) + this.key.hashCode(); - return result; - } } diff --git a/api/src/main/java/net/kyori/adventure/pointer/Pointers.java b/api/src/main/java/net/kyori/adventure/pointer/Pointers.java index 5360207c1..b13e5b644 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/Pointers.java +++ b/api/src/main/java/net/kyori/adventure/pointer/Pointers.java @@ -26,7 +26,6 @@ import java.util.Optional; import java.util.function.Supplier; import net.kyori.adventure.builder.AbstractBuilder; -import net.kyori.adventure.util.Buildable; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +36,7 @@ * * @since 4.8.0 */ -public interface Pointers extends Buildable { +public sealed interface Pointers permits PointersImpl, PointersSupplierImpl.ForwardingPointers { /** * Gets an empty pointers collection. * @@ -122,7 +121,7 @@ public interface Pointers extends Buildable { * @see Pointers * @since 4.8.0 */ - interface Builder extends AbstractBuilder, Buildable.Builder { + sealed interface Builder extends AbstractBuilder permits PointersImpl.BuilderImpl { /** * Adds a pointer with a static, optional value. * diff --git a/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java b/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java index c732b87d6..5d55ea33c 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java +++ b/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java @@ -31,33 +31,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -final class PointersImpl implements Pointers { - static final Pointers EMPTY = new Pointers() { - @Override - public @NotNull Optional get(final @NotNull Pointer pointer) { - return Optional.empty(); - } - - @Override - public boolean supports(final @NotNull Pointer pointer) { - return false; - } - - @Override - public Pointers.@NotNull Builder toBuilder() { - return new PointersImpl.BuilderImpl(); - } +record PointersImpl(Map, Supplier> pointers) implements Pointers { + static final PointersImpl EMPTY = new PointersImpl(Map.of()); - @Override - public String toString() { - return "EmptyPointers"; - } - }; - - private final Map, Supplier> pointers; - - PointersImpl(final @NotNull BuilderImpl builder) { - this.pointers = new HashMap<>(builder.pointers); + PointersImpl(final @NotNull BuilderImpl pointers) { + this(new HashMap<>(pointers.pointers)); } @Override @@ -78,11 +56,6 @@ public boolean supports(final @NotNull Pointer pointer) { return this.pointers.containsKey(pointer); } - @Override - public Pointers.@NotNull Builder toBuilder() { - return new BuilderImpl(this); - } - static final class BuilderImpl implements Builder { private final Map, Supplier> pointers; @@ -90,10 +63,6 @@ static final class BuilderImpl implements Builder { this.pointers = new HashMap<>(); } - BuilderImpl(final @NotNull PointersImpl pointers) { - this.pointers = new HashMap<>(pointers.pointers); - } - @Override public @NotNull Builder withDynamic(final @NotNull Pointer pointer, final @NotNull Supplier<@Nullable T> value) { this.pointers.put(Objects.requireNonNull(pointer, "pointer"), Objects.requireNonNull(value, "value")); diff --git a/api/src/main/java/net/kyori/adventure/pointer/PointersSupplier.java b/api/src/main/java/net/kyori/adventure/pointer/PointersSupplier.java index 11c3df451..3cf5221de 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/PointersSupplier.java +++ b/api/src/main/java/net/kyori/adventure/pointer/PointersSupplier.java @@ -53,7 +53,7 @@ * @param the type * @since 4.17.0 */ -public interface PointersSupplier { +public sealed interface PointersSupplier permits PointersSupplierImpl { /** * Gets a new pointers supplier builder. * @@ -100,7 +100,7 @@ public interface PointersSupplier { * @param the type to supply pointers for * @since 4.17.0 */ - interface Builder extends AbstractBuilder> { + sealed interface Builder extends AbstractBuilder> permits PointersSupplierImpl.BuilderImpl { /** * Sets (or removes, if {@code null}) the parent pointer supplier that will be used * to resolve pointers that are not supplied by this supplier. diff --git a/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java b/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java index e1f01d24d..bf0a391dc 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java +++ b/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java @@ -28,7 +28,6 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Function; -import java.util.function.Supplier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -71,53 +70,33 @@ public

boolean supports(final @NotNull Pointer

pointer) { } } - static final class ForwardingPointers implements Pointers { - private final U instance; - private final PointersSupplierImpl supplier; - - ForwardingPointers(final @NotNull U instance, final @NotNull PointersSupplierImpl supplier) { - this.instance = instance; - this.supplier = supplier; - } - - @Override - @SuppressWarnings("unchecked") // all values are checked on entry - public @NotNull Optional get(final @NotNull Pointer pointer) { - Function resolver = this.supplier.resolvers.get(Objects.requireNonNull(pointer, "pointer")); - - // Fallback to the parent. - if (resolver == null) { - final PointersSupplier parent = this.supplier.parent; - if (parent != null) { - resolver = parent.resolver(pointer); + record ForwardingPointers(U instance, PointersSupplierImpl supplier) implements Pointers { + @Override + @SuppressWarnings("unchecked") // all values are checked on entry + public @NotNull Optional get(final @NotNull Pointer pointer) { + Function resolver = this.supplier.resolvers.get(Objects.requireNonNull(pointer, "pointer")); + + // Fallback to the parent. + if (resolver == null) { + final PointersSupplier parent = this.supplier.parent; + if (parent != null) { + resolver = parent.resolver(pointer); + } } - } - // Finally, wrap in an optional. - if (resolver == null) { - return Optional.empty(); - } else { - return Optional.ofNullable((T) resolver.apply(this.instance)); + // Finally, wrap in an optional. + if (resolver == null) { + return Optional.empty(); + } else { + return Optional.ofNullable((T) resolver.apply(this.instance)); + } } - } - @Override - public boolean supports(final @NotNull Pointer pointer) { - return this.supplier.supports(pointer); - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) // all values are checked on entry - public Pointers.@NotNull Builder toBuilder() { - final Pointers.Builder builder = this.supplier.parent == null ? Pointers.builder() : this.supplier.parent.view(this.instance).toBuilder(); - - for (final Map.Entry, Function> entry : this.supplier.resolvers.entrySet()) { - builder.withDynamic(entry.getKey(), (Supplier) () -> entry.getValue().apply(this.instance)); + @Override + public boolean supports(final @NotNull Pointer pointer) { + return this.supplier.supports(pointer); } - - return builder; } - } static final class BuilderImpl implements Builder { private @Nullable PointersSupplier parent = null; diff --git a/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfo.java b/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfo.java index 277831cac..c48dd85e6 100644 --- a/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfo.java +++ b/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfo.java @@ -41,7 +41,7 @@ * @see Audience#sendResourcePacks(ResourcePackInfoLike, ResourcePackInfoLike...) * @since 4.15.0 */ -public interface ResourcePackInfo extends Examinable, ResourcePackInfoLike { +public sealed interface ResourcePackInfo extends Examinable, ResourcePackInfoLike permits ResourcePackInfoImpl { /** * Creates information about a resource pack. * @@ -99,7 +99,7 @@ public interface ResourcePackInfo extends Examinable, ResourcePackInfoLike { * * @since 4.15.0 */ - interface Builder extends AbstractBuilder, ResourcePackInfoLike { + sealed interface Builder extends AbstractBuilder, ResourcePackInfoLike permits ResourcePackInfoImpl.BuilderImpl { /** * Sets the id. * diff --git a/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java b/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java index a3d0c0d85..27d45f696 100644 --- a/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java +++ b/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java @@ -40,36 +40,16 @@ import net.kyori.adventure.internal.Internals; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import static java.util.Objects.requireNonNull; -final class ResourcePackInfoImpl implements ResourcePackInfo { - private final UUID id; - private final URI uri; - private final String hash; - +record ResourcePackInfoImpl(UUID id, URI uri, String hash) implements ResourcePackInfo { ResourcePackInfoImpl(final @NotNull UUID id, final @NotNull URI uri, final @NotNull String hash) { this.id = requireNonNull(id, "id"); this.uri = requireNonNull(uri, "uri"); this.hash = requireNonNull(hash, "hash"); } - @Override - public @NotNull UUID id() { - return this.id; - } - - @Override - public @NotNull URI uri() { - return this.uri; - } - - @Override - public @NotNull String hash() { - return this.hash; - } - @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -80,28 +60,10 @@ final class ResourcePackInfoImpl implements ResourcePackInfo { } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof ResourcePackInfoImpl)) return false; - final ResourcePackInfoImpl that = (ResourcePackInfoImpl) other; - return this.id.equals(that.id) && - this.uri.equals(that.uri) && - this.hash.equals(that.hash); - } - - @Override - public int hashCode() { - int result = this.id.hashCode(); - result = 31 * result + this.uri.hashCode(); - result = 31 * result + this.hash.hashCode(); - return result; - } - static final class BuilderImpl implements Builder { private UUID id; private URI uri; @@ -174,8 +136,8 @@ static CompletableFuture computeHash(final URI uri, final Executor exec) static String bytesToString(final byte[] arr) { final StringBuilder builder = new StringBuilder(arr.length * 2); final Formatter fmt = new Formatter(builder, Locale.ROOT); - for (int i = 0; i < arr.length; i++) { - fmt.format("%02x", arr[i] & 0xff); + for (byte b : arr) { + fmt.format("%02x", b & 0xff); } return builder.toString(); } diff --git a/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequest.java b/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequest.java index 8a49ef2de..6260808ba 100644 --- a/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequest.java +++ b/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequest.java @@ -40,7 +40,7 @@ * * @since 4.15.0 */ -public interface ResourcePackRequest extends Examinable, ResourcePackRequestLike { +public sealed interface ResourcePackRequest extends Examinable, ResourcePackRequestLike permits ResourcePackRequestImpl { /** * Create a basic request to apply the provided resource packs. * @@ -160,7 +160,7 @@ public interface ResourcePackRequest extends Examinable, ResourcePackRequestLike * * @since 4.15.0 */ - interface Builder extends AbstractBuilder, ResourcePackRequestLike { + sealed interface Builder extends AbstractBuilder, ResourcePackRequestLike permits ResourcePackRequestImpl.BuilderImpl { /** * Set the resource packs to apply. * diff --git a/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequestImpl.java b/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequestImpl.java index 6d44a5db1..6fb7e0afa 100644 --- a/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequestImpl.java +++ b/api/src/main/java/net/kyori/adventure/resource/ResourcePackRequestImpl.java @@ -25,7 +25,6 @@ import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.stream.Stream; import net.kyori.adventure.internal.Internals; import net.kyori.adventure.text.Component; @@ -36,48 +35,24 @@ import static java.util.Objects.requireNonNull; -final class ResourcePackRequestImpl implements ResourcePackRequest { - private final List packs; - private final ResourcePackCallback cb; - private final boolean replace; - private final boolean required; - private final @Nullable Component prompt; - - ResourcePackRequestImpl(final List packs, final ResourcePackCallback cb, final boolean replace, final boolean required, final @Nullable Component prompt) { - this.packs = packs; - this.cb = cb; - this.replace = replace; - this.required = required; - this.prompt = prompt; - } - - @Override - public @NotNull List packs() { - return this.packs; - } - +record ResourcePackRequestImpl(List packs, ResourcePackCallback callback, boolean replace, boolean required, @Nullable Component prompt) implements ResourcePackRequest { @Override @SuppressWarnings("UndefinedEquals") - public @NotNull ResourcePackRequest packs(final@NotNull Iterable packs) { + public @NotNull ResourcePackRequest packs(final @NotNull Iterable packs) { if (this.packs.equals(packs)) return this; return new ResourcePackRequestImpl( MonkeyBars.toUnmodifiableList(ResourcePackInfoLike::asResourcePackInfo, packs), - this.cb, + this.callback, this.replace, this.required, this.prompt ); } - @Override - public @NotNull ResourcePackCallback callback() { - return this.cb; - } - @Override public @NotNull ResourcePackRequest callback(final @NotNull ResourcePackCallback cb) { - if (cb == this.cb) return this; + if (cb == this.callback) return this; return new ResourcePackRequestImpl( this.packs, @@ -88,43 +63,11 @@ final class ResourcePackRequestImpl implements ResourcePackRequest { ); } - @Override - public boolean replace() { - return this.replace; - } - - @Override - public boolean required() { - return this.required; - } - - @Override - public @Nullable Component prompt() { - return this.prompt; - } - @Override public @NotNull ResourcePackRequest replace(final boolean replace) { if (replace == this.replace) return this; - return new ResourcePackRequestImpl(this.packs, this.cb, replace, this.required, this.prompt); - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final ResourcePackRequestImpl that = (ResourcePackRequestImpl) other; - return this.replace == that.replace - && Objects.equals(this.packs, that.packs) - && Objects.equals(this.cb, that.cb) - && this.required == that.required - && Objects.equals(this.prompt, that.prompt); - } - - @Override - public int hashCode() { - return Objects.hash(this.packs, this.cb, this.replace, this.required, this.prompt); + return new ResourcePackRequestImpl(this.packs, this.callback, replace, this.required, this.prompt); } @Override @@ -136,7 +79,7 @@ public int hashCode() { public @NotNull Stream examinableProperties() { return Stream.of( ExaminableProperty.of("packs", this.packs), - ExaminableProperty.of("callback", this.cb), + ExaminableProperty.of("callback", this.callback), ExaminableProperty.of("replace", this.replace), ExaminableProperty.of("required", this.required), ExaminableProperty.of("prompt", this.prompt) diff --git a/api/src/main/java/net/kyori/adventure/sound/Sound.java b/api/src/main/java/net/kyori/adventure/sound/Sound.java index c49075d7e..5407682e3 100644 --- a/api/src/main/java/net/kyori/adventure/sound/Sound.java +++ b/api/src/main/java/net/kyori/adventure/sound/Sound.java @@ -31,7 +31,6 @@ import net.kyori.adventure.key.Keyed; import net.kyori.adventure.util.Index; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Range; @@ -63,8 +62,7 @@ * @see SoundStop * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface Sound extends Examinable { +public sealed interface Sound extends Examinable permits SoundImpl { /** * Create a new builder for {@link Sound} instances. * @@ -411,7 +409,7 @@ interface Emitter { * * @since 4.12.0 */ - interface Builder extends AbstractBuilder { + sealed interface Builder extends AbstractBuilder permits SoundImpl.BuilderImpl { /** * Set the type of this sound. * diff --git a/api/src/main/java/net/kyori/adventure/sound/SoundImpl.java b/api/src/main/java/net/kyori/adventure/sound/SoundImpl.java index ba05709e0..248872289 100644 --- a/api/src/main/java/net/kyori/adventure/sound/SoundImpl.java +++ b/api/src/main/java/net/kyori/adventure/sound/SoundImpl.java @@ -36,7 +36,7 @@ import static java.util.Objects.requireNonNull; -abstract class SoundImpl implements Sound { +sealed abstract class SoundImpl implements Sound permits SoundImpl.Eager, SoundImpl.Lazy { static final Emitter EMITTER_SELF = new Emitter() { @Override public String toString() { @@ -86,8 +86,7 @@ public float pitch() { @Override public boolean equals(final @Nullable Object other) { if (this == other) return true; - if (!(other instanceof SoundImpl)) return false; - final SoundImpl that = (SoundImpl) other; + if (!(other instanceof SoundImpl that)) return false; return this.name().equals(that.name()) && this.source == that.source && ShadyPines.equals(this.volume, that.volume) diff --git a/api/src/main/java/net/kyori/adventure/sound/SoundStop.java b/api/src/main/java/net/kyori/adventure/sound/SoundStop.java index 59875e22b..29e6a48ad 100644 --- a/api/src/main/java/net/kyori/adventure/sound/SoundStop.java +++ b/api/src/main/java/net/kyori/adventure/sound/SoundStop.java @@ -27,7 +27,6 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.key.Key; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,8 +43,7 @@ * @see Audience#stopSound(SoundStop) * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface SoundStop extends Examinable { +public sealed interface SoundStop extends Examinable permits SoundStopImpl { /** * Stops all sounds. * @@ -65,12 +63,7 @@ public interface SoundStop extends Examinable { */ static @NotNull SoundStop named(final @NotNull Key sound) { requireNonNull(sound, "sound"); - return new SoundStopImpl(null) { - @Override - public @NotNull Key sound() { - return sound; - } - }; + return new SoundStopImpl(sound, null); } /** @@ -82,12 +75,7 @@ public interface SoundStop extends Examinable { */ static @NotNull SoundStop named(final Sound.@NotNull Type sound) { requireNonNull(sound, "sound"); - return new SoundStopImpl(null) { - @Override - public @NotNull Key sound() { - return sound.key(); - } - }; + return new SoundStopImpl(sound.key(), null); } /** @@ -99,12 +87,7 @@ public interface SoundStop extends Examinable { */ static @NotNull SoundStop named(final @NotNull Supplier sound) { requireNonNull(sound, "sound"); - return new SoundStopImpl(null) { - @Override - public @NotNull Key sound() { - return sound.get().key(); - } - }; + return new SoundStopImpl(sound.get().key(), null); } /** @@ -116,12 +99,7 @@ public interface SoundStop extends Examinable { */ static @NotNull SoundStop source(final Sound.@NotNull Source source) { requireNonNull(source, "source"); - return new SoundStopImpl(source) { - @Override - public @Nullable Key sound() { - return null; - } - }; + return new SoundStopImpl(null, source); } /** @@ -135,12 +113,7 @@ public interface SoundStop extends Examinable { static @NotNull SoundStop namedOnSource(final @NotNull Key sound, final Sound.@NotNull Source source) { requireNonNull(sound, "sound"); requireNonNull(source, "source"); - return new SoundStopImpl(source) { - @Override - public @NotNull Key sound() { - return sound; - } - }; + return new SoundStopImpl(sound, source); } /** @@ -167,12 +140,7 @@ public interface SoundStop extends Examinable { static @NotNull SoundStop namedOnSource(final @NotNull Supplier sound, final Sound.@NotNull Source source) { requireNonNull(sound, "sound"); requireNonNull(source, "source"); - return new SoundStopImpl(source) { - @Override - public @NotNull Key sound() { - return sound.get().key(); - } - }; + return new SoundStopImpl(sound.get().key(), source); } /** diff --git a/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java b/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java index b36dcb24c..5cb3e7966 100644 --- a/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java +++ b/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java @@ -31,32 +31,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -abstract class SoundStopImpl implements SoundStop { - static final SoundStop ALL = new SoundStopImpl(null) { - @Override - public @Nullable Key sound() { - return null; // all - } - }; - private final Sound.@Nullable Source source; - - SoundStopImpl(final Sound.@Nullable Source source) { - this.source = source; - } - - @Override - public Sound.@Nullable Source source() { - return this.source; - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof SoundStopImpl)) return false; - final SoundStopImpl that = (SoundStopImpl) other; - return Objects.equals(this.sound(), that.sound()) - && Objects.equals(this.source, that.source); - } +record SoundStopImpl(@Nullable Key sound, Sound.@Nullable Source source) implements SoundStop { + static final SoundStopImpl ALL = new SoundStopImpl(null, null); @Override public int hashCode() { @@ -74,7 +50,7 @@ public int hashCode() { } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } } diff --git a/api/src/main/java/net/kyori/adventure/text/BuildableComponent.java b/api/src/main/java/net/kyori/adventure/text/BuildableComponent.java index 03334008e..cf203bf0a 100644 --- a/api/src/main/java/net/kyori/adventure/text/BuildableComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/BuildableComponent.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.text; -import net.kyori.adventure.util.Buildable; import org.jetbrains.annotations.NotNull; /** diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java index 85b0848ea..d554d3bd7 100644 --- a/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java @@ -36,7 +36,6 @@ import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.util.Buildable; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/net/kyori/adventure/text/JoinConfiguration.java b/api/src/main/java/net/kyori/adventure/text/JoinConfiguration.java index 97120ebfa..192491cbc 100644 --- a/api/src/main/java/net/kyori/adventure/text/JoinConfiguration.java +++ b/api/src/main/java/net/kyori/adventure/text/JoinConfiguration.java @@ -27,7 +27,6 @@ import java.util.function.Predicate; import net.kyori.adventure.builder.AbstractBuilder; import net.kyori.adventure.text.format.Style; -import net.kyori.adventure.util.Buildable; import net.kyori.examination.Examinable; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; diff --git a/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java b/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java index 5b8c2cc7e..26f5de4f7 100644 --- a/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java +++ b/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java @@ -29,7 +29,6 @@ import java.util.regex.Pattern; import net.kyori.adventure.builder.AbstractBuilder; import net.kyori.adventure.text.event.HoverEvent; -import net.kyori.adventure.util.Buildable; import net.kyori.adventure.util.IntFunction2; import net.kyori.examination.Examinable; import org.intellij.lang.annotations.RegExp; diff --git a/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java b/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java index eebd78f71..0e22a5d3a 100644 --- a/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java @@ -30,7 +30,6 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.translation.GlobalTranslator; import net.kyori.adventure.translation.Translatable; -import net.kyori.adventure.translation.TranslationRegistry; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java index 8556bd61d..c111706b2 100644 --- a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java +++ b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java @@ -28,7 +28,6 @@ import java.util.function.Function; import net.kyori.adventure.builder.AbstractBuilder; import net.kyori.adventure.text.Component; -import net.kyori.adventure.util.Buildable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Range; diff --git a/api/src/main/java/net/kyori/adventure/text/format/Style.java b/api/src/main/java/net/kyori/adventure/text/format/Style.java index 51550f806..3b22c90ae 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/Style.java +++ b/api/src/main/java/net/kyori/adventure/text/format/Style.java @@ -34,7 +34,6 @@ import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEventSource; -import net.kyori.adventure.util.Buildable; import net.kyori.adventure.util.MonkeyBars; import net.kyori.examination.Examinable; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/net/kyori/adventure/title/Title.java b/api/src/main/java/net/kyori/adventure/title/Title.java index 693890a46..718e8330f 100644 --- a/api/src/main/java/net/kyori/adventure/title/Title.java +++ b/api/src/main/java/net/kyori/adventure/title/Title.java @@ -27,7 +27,6 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.util.Ticks; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; @@ -38,8 +37,7 @@ * @see Times * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface Title extends Examinable { +public sealed interface Title extends Examinable permits TitleImpl { /** * The default times. * @@ -126,23 +124,7 @@ public interface Title extends Examinable { * * @since 4.0.0 */ - interface Times extends Examinable { - /** - * Creates times. - * - * @param fadeIn the fade-in time - * @param stay the stay time - * @param fadeOut the fade-out time - * @return times - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #times()} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - static @NotNull Times of(final @NotNull Duration fadeIn, final @NotNull Duration stay, final @NotNull Duration fadeOut) { - return times(fadeIn, stay, fadeOut); - } - + sealed interface Times extends Examinable permits TitleImpl.TimesImpl { /** * Creates times. * diff --git a/api/src/main/java/net/kyori/adventure/title/TitleImpl.java b/api/src/main/java/net/kyori/adventure/title/TitleImpl.java index 1e4386b3d..756058de5 100644 --- a/api/src/main/java/net/kyori/adventure/title/TitleImpl.java +++ b/api/src/main/java/net/kyori/adventure/title/TitleImpl.java @@ -24,7 +24,6 @@ package net.kyori.adventure.title; import java.time.Duration; -import java.util.Objects; import java.util.stream.Stream; import net.kyori.adventure.internal.Internals; import net.kyori.adventure.text.Component; @@ -35,32 +34,13 @@ import static java.util.Objects.requireNonNull; -final class TitleImpl implements Title { - private final Component title; - private final Component subtitle; - private final @Nullable Times times; - +record TitleImpl(Component title, Component subtitle, @Nullable Times times) implements Title { TitleImpl(final @NotNull Component title, final @NotNull Component subtitle, final @Nullable Times times) { this.title = requireNonNull(title, "title"); this.subtitle = requireNonNull(subtitle, "subtitle"); this.times = times; } - @Override - public @NotNull Component title() { - return this.title; - } - - @Override - public @NotNull Component subtitle() { - return this.subtitle; - } - - @Override - public @Nullable Times times() { - return this.times; - } - @Override @SuppressWarnings("unchecked") // compared with parts directly public @UnknownNullability T part(final @NotNull TitlePart part) { @@ -76,24 +56,6 @@ final class TitleImpl implements Title { throw new IllegalArgumentException("Don't know what " + part + " is."); } - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final TitleImpl that = (TitleImpl) other; - return this.title.equals(that.title) - && this.subtitle.equals(that.subtitle) - && Objects.equals(this.times, that.times); - } - - @Override - public int hashCode() { - int result = this.title.hashCode(); - result = (31 * result) + this.subtitle.hashCode(); - result = (31 * result) + Objects.hashCode(this.times); - return result; - } - @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -104,66 +66,29 @@ public int hashCode() { } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - static class TimesImpl implements Times { - private final Duration fadeIn; - private final Duration stay; - private final Duration fadeOut; - - TimesImpl(final @NotNull Duration fadeIn, final @NotNull Duration stay, final @NotNull Duration fadeOut) { - this.fadeIn = requireNonNull(fadeIn, "fadeIn"); - this.stay = requireNonNull(stay, "stay"); - this.fadeOut = requireNonNull(fadeOut, "fadeOut"); - } + record TimesImpl(Duration fadeIn, Duration stay, Duration fadeOut) implements Times { + TimesImpl(final @NotNull Duration fadeIn, final @NotNull Duration stay, final @NotNull Duration fadeOut) { + this.fadeIn = requireNonNull(fadeIn, "fadeIn"); + this.stay = requireNonNull(stay, "stay"); + this.fadeOut = requireNonNull(fadeOut, "fadeOut"); + } @Override - public @NotNull Duration fadeIn() { - return this.fadeIn; + public @NotNull Stream examinableProperties() { + return Stream.of( + ExaminableProperty.of("fadeIn", this.fadeIn), + ExaminableProperty.of("stay", this.stay), + ExaminableProperty.of("fadeOut", this.fadeOut) + ); + } + + @Override + public @NotNull String toString() { + return Internals.toString(this); + } } - - @Override - public @NotNull Duration stay() { - return this.stay; - } - - @Override - public @NotNull Duration fadeOut() { - return this.fadeOut; - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof TimesImpl)) return false; - final TimesImpl that = (TimesImpl) other; - return this.fadeIn.equals(that.fadeIn) - && this.stay.equals(that.stay) - && this.fadeOut.equals(that.fadeOut); - } - - @Override - public int hashCode() { - int result = this.fadeIn.hashCode(); - result = (31 * result) + this.stay.hashCode(); - result = (31 * result) + this.fadeOut.hashCode(); - return result; - } - - @Override - public @NotNull Stream examinableProperties() { - return Stream.of( - ExaminableProperty.of("fadeIn", this.fadeIn), - ExaminableProperty.of("stay", this.stay), - ExaminableProperty.of("fadeOut", this.fadeOut) - ); - } - - @Override - public String toString() { - return Internals.toString(this); - } - } } diff --git a/api/src/main/java/net/kyori/adventure/title/TitlePart.java b/api/src/main/java/net/kyori/adventure/title/TitlePart.java index fa70d1d7c..736d834d6 100644 --- a/api/src/main/java/net/kyori/adventure/title/TitlePart.java +++ b/api/src/main/java/net/kyori/adventure/title/TitlePart.java @@ -23,51 +23,35 @@ */ package net.kyori.adventure.title; +import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; -import org.jetbrains.annotations.ApiStatus; /** * A part of a title. * - * @param the type of the content of the part - * @see net.kyori.adventure.audience.Audience#sendTitlePart(TitlePart, Object) + * @param the type of the part's contents + * @see Audience#sendTitlePart(TitlePart, Object) * @since 4.9.0 */ -@ApiStatus.NonExtendable -public interface TitlePart { +public sealed interface TitlePart permits TitlePartImpl { /** * The title part of a title. * * @since 4.9.0 */ - TitlePart TITLE = new TitlePart() { - @Override - public String toString() { - return "TitlePart.TITLE"; - } - }; + TitlePart TITLE = new TitlePartImpl<>("TITLE"); /** * The subtitle part of a title. * * @since 4.9.0 */ - TitlePart SUBTITLE = new TitlePart() { - @Override - public String toString() { - return "TitlePart.SUBTITLE"; - } - }; + TitlePart SUBTITLE = new TitlePartImpl<>("SUBTITLE"); /** * The times part of a title. * * @since 4.9.0 */ - TitlePart TIMES = new TitlePart() { - @Override - public String toString() { - return "TitlePart.TIMES"; - } - }; + TitlePart TIMES = new TitlePartImpl<>("TIMES"); } diff --git a/api/src/main/java/net/kyori/adventure/audience/MessageType.java b/api/src/main/java/net/kyori/adventure/title/TitlePartImpl.java similarity index 60% rename from api/src/main/java/net/kyori/adventure/audience/MessageType.java rename to api/src/main/java/net/kyori/adventure/title/TitlePartImpl.java index a70cae0f4..3cab56848 100644 --- a/api/src/main/java/net/kyori/adventure/audience/MessageType.java +++ b/api/src/main/java/net/kyori/adventure/title/TitlePartImpl.java @@ -21,36 +21,20 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package net.kyori.adventure.audience; +package net.kyori.adventure.title; -import net.kyori.adventure.chat.ChatType; -import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; -/** - * Message types. - * - * @since 4.0.0 - * @deprecated for removal since 4.12.0, use separate methods on {@link Audience} for sending player or system messages - */ -@ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") -@Deprecated -public enum MessageType { - /** - * Chat message type. - * - * @since 4.0.0 - * @deprecated for removal since 4.12.0, use {@link ChatType#CHAT} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - CHAT, - /** - * System message type. - * - * @since 4.0.0 - * @deprecated for removal since 4.12.0 - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - SYSTEM; +public record TitlePartImpl( + @NotNull String part +) implements TitlePart { + @Override + public boolean equals(final Object o) { + return o == this; + } + + @Override + public @NotNull String toString() { + return "TitlePart." + this.part(); + } } diff --git a/api/src/main/java/net/kyori/adventure/translation/AbstractTranslationStore.java b/api/src/main/java/net/kyori/adventure/translation/AbstractTranslationStore.java index 568c2ca16..675447e76 100644 --- a/api/src/main/java/net/kyori/adventure/translation/AbstractTranslationStore.java +++ b/api/src/main/java/net/kyori/adventure/translation/AbstractTranslationStore.java @@ -163,9 +163,7 @@ public final void unregister(final @NotNull String key) { @Override public final boolean equals(final Object other) { if (this == other) return true; - if (!(other instanceof AbstractTranslationStore)) return false; - - final AbstractTranslationStore that = (AbstractTranslationStore) other; + if (!(other instanceof AbstractTranslationStore that)) return false; return this.name.equals(that.name); } @@ -192,7 +190,7 @@ private Translation(final @NotNull String key) { private @Nullable T translate(final @NotNull Locale locale) { T format = this.translations.get(requireNonNull(locale, "locale")); if (format == null) { - format = this.translations.get(new Locale(locale.getLanguage())); // try without country + format = this.translations.get(Locale.of(locale.getLanguage())); // try without country if (format == null) { format = this.translations.get(AbstractTranslationStore.this.defaultLocale); // try local default locale if (format == null) { @@ -220,10 +218,8 @@ private void register(final @NotNull Locale locale, final @NotNull T translation @Override public boolean equals(final Object other) { if (this == other) return true; - if (!(other instanceof AbstractTranslationStore.Translation)) return false; - final AbstractTranslationStore.Translation that = (AbstractTranslationStore.Translation) other; - return this.key.equals(that.key) && - this.translations.equals(that.translations); + if (!(other instanceof AbstractTranslationStore.Translation that)) return false; + return this.key.equals(that.key) && this.translations.equals(that.translations); } @Override diff --git a/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java b/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java index 537c75427..83a5471b4 100644 --- a/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java +++ b/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java @@ -29,7 +29,6 @@ import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -52,19 +51,6 @@ public interface GlobalTranslator extends Translator, Examinable { return GlobalTranslatorImpl.INSTANCE; } - /** - * Gets the global translation source. - * - * @return the source - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #translator()} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull GlobalTranslator get() { - return GlobalTranslatorImpl.INSTANCE; - } - /** * Gets a renderer which uses the global source for translating. * diff --git a/api/src/main/java/net/kyori/adventure/translation/MessageFormatTranslationStore.java b/api/src/main/java/net/kyori/adventure/translation/MessageFormatTranslationStore.java index 0807b1aca..50a58c128 100644 --- a/api/src/main/java/net/kyori/adventure/translation/MessageFormatTranslationStore.java +++ b/api/src/main/java/net/kyori/adventure/translation/MessageFormatTranslationStore.java @@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -final class MessageFormatTranslationStore extends AbstractTranslationStore.StringBased implements TranslationRegistry { +final class MessageFormatTranslationStore extends AbstractTranslationStore.StringBased { MessageFormatTranslationStore(final Key name) { super(name); diff --git a/api/src/main/java/net/kyori/adventure/translation/TranslationRegistry.java b/api/src/main/java/net/kyori/adventure/translation/TranslationRegistry.java deleted file mode 100644 index 1314ba1ec..000000000 --- a/api/src/main/java/net/kyori/adventure/translation/TranslationRegistry.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.translation; - -import java.io.BufferedReader; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.MessageFormat; -import java.util.Locale; -import java.util.Map; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; -import java.util.Set; -import java.util.function.Function; -import java.util.regex.Pattern; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.util.UTF8ResourceBundleControl; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import static java.util.Objects.requireNonNull; - -/** - * A registry of translations. Used to register localized strings for translation keys. The registry can be submitted - * to the {@link GlobalTranslator} or can translate manually through {@link #translate(String, Locale)}. - * - *

The recommended way to register translations is through {@link #registerAll(Locale, ResourceBundle, boolean)}

- * - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ -@Deprecated -public interface TranslationRegistry extends Translator, TranslationStore.StringBased { - /** - * A pattern which matches a single quote. - * - * @since 4.0.0 - * @deprecated For removal, since 4.20.0, with no replacement. - */ - @Deprecated - Pattern SINGLE_QUOTE_PATTERN = Pattern.compile("'"); - - /** - * Creates a new standalone translation registry. - * - * @param name the registry id - * @return a translation registry - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Deprecated - static @NotNull TranslationRegistry create(final Key name) { - return new MessageFormatTranslationStore(requireNonNull(name, "name")); - } - - /** - * Checks if any translations are explicitly registered for the specified key. - * - * @param key a translation key - * @return whether the registry contains a value for the translation key - * @since 4.7.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - boolean contains(final @NotNull String key); - - /** - * Gets a message format from a key and locale. - * - *

If a translation for {@code locale} is not found, we will then try {@code locale} without a country code, and then finally fallback to a default locale.

- * - * @param locale a locale - * @param key a translation key - * @return a message format or {@code null} to skip translation - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Deprecated - @Override - @Nullable MessageFormat translate(final @NotNull String key, final @NotNull Locale locale); - - /** - * Sets the default locale used by this registry. - * - * @param locale the locale to use a default - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - void defaultLocale(final @NotNull Locale locale); - - /** - * Registers a translation. - * - *
-   *   final TranslationRegistry registry;
-   *   registry.register("example.hello", Locale.US, new MessageFormat("Hi, {0}. How are you?"));
-   * 
- * - * @param key a translation key - * @param locale a locale - * @param format a translation format - * @throws IllegalArgumentException if the translation key is already exists - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - void register(final @NotNull String key, final @NotNull Locale locale, final @NotNull MessageFormat format); - - /** - * Registers a map of translations. - * - *
-   *   final TranslationRegistry registry;
-   *   final Map<String, MessageFormat> translations;
-   *
-   *   translations.put("example.greeting", new MessageFormat("Greetings {0}. Doing ok?));
-   *   translations.put("example.goodbye", new MessageFormat("Goodbye {0}. Have a nice day!));
-   *
-   *   registry.registerAll(Locale.US, translations);
-   * 
- * - * @param locale a locale - * @param formats a map of translation keys to formats - * @throws IllegalArgumentException if a translation key already exists - * @see #register(String, Locale, MessageFormat) - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - default void registerAll(final @NotNull Locale locale, final @NotNull Map formats) { - this.registerAll(locale, formats.keySet(), formats::get); - } - - /** - * Registers a resource bundle of translations. - * - * @param locale a locale - * @param path a path to the resource bundle - * @param escapeSingleQuotes whether to escape single quotes - * @throws IllegalArgumentException if a translation key already exists - * @see #registerAll(Locale, ResourceBundle, boolean) - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - default void registerAll(final @NotNull Locale locale, final @NotNull Path path, final boolean escapeSingleQuotes) { - try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { - this.registerAll(locale, new PropertyResourceBundle(reader), escapeSingleQuotes); - } catch (final IOException e) { - // ignored - } - } - - /** - * Registers a resource bundle of translations. - * - *

It is highly recommended to create your bundle using {@link UTF8ResourceBundleControl} as your bundle control for UTF-8 support - for example:

- * - *
-   *   final ResourceBundle bundle = ResourceBundle.getBundle("my_bundle", Locale.GERMANY, UTF8ResourceBundleControl.get());
-   *   registry.registerAll(Locale.GERMANY, bundle, false);
-   * 
- * - * @param locale a locale - * @param bundle a resource bundle - * @param escapeSingleQuotes whether to escape single quotes - * @throws IllegalArgumentException if a translation key already exists - * @see UTF8ResourceBundleControl - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - default void registerAll(final @NotNull Locale locale, final @NotNull ResourceBundle bundle, final boolean escapeSingleQuotes) { - this.registerAll(locale, bundle.keySet(), key -> { - final String format = bundle.getString(key); - return new MessageFormat( - escapeSingleQuotes - ? SINGLE_QUOTE_PATTERN.matcher(format).replaceAll("''") - : format, - locale - ); - }); - } - - /** - * Registers a resource bundle of translations. - * - * @param locale a locale - * @param keys the translation keys to register - * @param function a function to transform a key into a message format - * @throws IllegalArgumentException if a translation key already exists - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - @SuppressWarnings("DuplicatedCode") // We need a default impl here - will be removed in 5.x - default void registerAll(final @NotNull Locale locale, final @NotNull Set keys, final Function function) { - IllegalArgumentException firstError = null; - int errorCount = 0; - for (final String key : keys) { - try { - this.register(key, locale, function.apply(key)); - } catch (final IllegalArgumentException e) { - if (firstError == null) { - firstError = e; - } - errorCount++; - } - } - if (firstError != null) { - if (errorCount == 1) { - throw firstError; - } else if (errorCount > 1) { - throw new IllegalArgumentException(String.format("Invalid key (and %d more)", errorCount - 1), firstError); - } - } - } - - /** - * Unregisters a translation key. - * - * @param key a translation key - * @since 4.0.0 - * @deprecated For removal since 4.20.0. Use {@link TranslationStore#messageFormat(Key)} instead. - */ - @Override - @Deprecated - void unregister(final @NotNull String key); -} diff --git a/api/src/main/java/net/kyori/adventure/translation/Translator.java b/api/src/main/java/net/kyori/adventure/translation/Translator.java index 33dc7e2e7..b01653570 100644 --- a/api/src/main/java/net/kyori/adventure/translation/Translator.java +++ b/api/src/main/java/net/kyori/adventure/translation/Translator.java @@ -61,11 +61,11 @@ public interface Translator { final String[] segments = string.split("_", 3); // language_country_variant final int length = segments.length; if (length == 1) { - return new Locale(string); // language + return Locale.of(string); // language } else if (length == 2) { - return new Locale(segments[0], segments[1]); // language + country + return Locale.of(segments[0], segments[1]); // language + country } else if (length == 3) { - return new Locale(segments[0], segments[1], segments[2]); // language + country + variant + return Locale.of(segments[0], segments[1], segments[2]); // language + country + variant } return null; } diff --git a/api/src/main/java/net/kyori/adventure/util/Buildable.java b/api/src/main/java/net/kyori/adventure/util/Buildable.java deleted file mode 100644 index 8aac59f1e..000000000 --- a/api/src/main/java/net/kyori/adventure/util/Buildable.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.util; - -import java.util.function.Consumer; -import net.kyori.adventure.builder.AbstractBuilder; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Something that can be built. - * - * @param the type that can be built - * @param the builder type - * @since 4.0.0 - */ -public interface Buildable> { - /** - * Configures {@code builder} using {@code consumer} and then builds. - * - * @param builder the builder - * @param consumer the builder consume - * @param the type to be built - * @param the builder type - * @return the built thing - * @since 4.0.0 - * @deprecated since 4.10.0, use {@link AbstractBuilder#configureAndBuild(AbstractBuilder, Consumer)} - */ - @Contract(mutates = "param1") - @Deprecated - static , B extends Builder> @NotNull R configureAndBuild(final @NotNull B builder, final @Nullable Consumer consumer) { - return AbstractBuilder.configureAndBuild(builder, consumer); - } - - /** - * Create a builder from this thing. - * - * @return a builder - * @since 4.0.0 - */ - @Contract(value = "-> new", pure = true) - @NotNull B toBuilder(); - - /** - * A builder. - * - * @param the type to be built - * @since 4.0.0 - * @deprecated since 4.10.0, use {@link AbstractBuilder} - */ - @Deprecated - interface Builder extends AbstractBuilder { - /** - * Builds. - * - * @return the built thing - * @since 4.0.0 - */ - @Contract(value = "-> new", pure = true) - @Override - @NotNull R build(); - } -} diff --git a/api/src/main/java/net/kyori/adventure/util/Codec.java b/api/src/main/java/net/kyori/adventure/util/Codec.java index a47f473dd..5eaec8ca7 100644 --- a/api/src/main/java/net/kyori/adventure/util/Codec.java +++ b/api/src/main/java/net/kyori/adventure/util/Codec.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.util; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -62,35 +61,6 @@ public interface Codec { }; } - /** - * Creates a codec. - * - * @param decoder the decoder - * @param encoder the encoder - * @param the decoded type - * @param the encoded type - * @param the decode exception type - * @param the encode exception type - * @return a codec - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #codec(Codec.Decoder, Codec.Encoder)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull Codec of(final @NotNull Decoder decoder, final @NotNull Encoder encoder) { - return new Codec() { - @Override - public @NotNull D decode(final @NotNull E encoded) throws DX { - return decoder.decode(encoded); - } - - @Override - public @NotNull E encode(final @NotNull D decoded) throws EX { - return encoder.encode(decoded); - } - }; - } - /** * Decodes. * diff --git a/api/src/main/java/net/kyori/adventure/util/HSVLike.java b/api/src/main/java/net/kyori/adventure/util/HSVLike.java index 5a08d14c1..97a416ed2 100644 --- a/api/src/main/java/net/kyori/adventure/util/HSVLike.java +++ b/api/src/main/java/net/kyori/adventure/util/HSVLike.java @@ -26,7 +26,6 @@ import java.util.stream.Stream; import net.kyori.examination.Examinable; import net.kyori.examination.ExaminableProperty; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Range; @@ -51,22 +50,6 @@ public interface HSVLike extends Examinable { return new HSVLikeImpl(h, s, v); } - /** - * Creates a new HSVLike. - * - * @param h hue color component - * @param s saturation color component - * @param v value color component - * @return a new HSVLike - * @since 4.6.0 - * @deprecated for removal since 4.10.0, use {@link #hsvLike(float, float, float)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull HSVLike of(final float h, final float s, final float v) { - return new HSVLikeImpl(h, s, v); - } - /** * Creates a new HSVLike from the given red, green, and blue color components. * diff --git a/api/src/main/java/net/kyori/adventure/util/HSVLikeImpl.java b/api/src/main/java/net/kyori/adventure/util/HSVLikeImpl.java index ed5cbf8a0..fbe89bfd4 100644 --- a/api/src/main/java/net/kyori/adventure/util/HSVLikeImpl.java +++ b/api/src/main/java/net/kyori/adventure/util/HSVLikeImpl.java @@ -23,37 +23,14 @@ */ package net.kyori.adventure.util; -import java.util.Objects; import net.kyori.adventure.internal.Internals; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; -final class HSVLikeImpl implements HSVLike { - private final float h; - private final float s; - private final float v; - - HSVLikeImpl(final float h, final float s, final float v) { +record HSVLikeImpl(float h, float s, float v) implements HSVLike { + HSVLikeImpl { requireInsideRange(h, "h"); requireInsideRange(s, "s"); requireInsideRange(v, "v"); - this.h = h; - this.s = s; - this.v = v; - } - - @Override - public float h() { - return this.h; - } - - @Override - public float s() { - return this.s; - } - - @Override - public float v() { - return this.v; } private static void requireInsideRange(final float number, final String name) throws IllegalArgumentException { @@ -64,20 +41,7 @@ private static void requireInsideRange(final float number, final String name) th } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof HSVLikeImpl)) return false; - final HSVLikeImpl that = (HSVLikeImpl) other; - return ShadyPines.equals(that.h, this.h) && ShadyPines.equals(that.s, this.s) && ShadyPines.equals(that.v, this.v); - } - - @Override - public int hashCode() { - return Objects.hash(this.h, this.s, this.v); - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } } diff --git a/api/src/main/java/net/kyori/adventure/util/Nag.java b/api/src/main/java/net/kyori/adventure/util/Nag.java index 50ad21476..76777d3d1 100644 --- a/api/src/main/java/net/kyori/adventure/util/Nag.java +++ b/api/src/main/java/net/kyori/adventure/util/Nag.java @@ -23,6 +23,7 @@ */ package net.kyori.adventure.util; +import java.io.Serial; import org.jetbrains.annotations.NotNull; /** @@ -31,7 +32,7 @@ * @since 4.7.0 */ public abstract class Nag extends RuntimeException { - private static final long serialVersionUID = -695562541413409498L; + @Serial private static final long serialVersionUID = -695562541413409498L; /** * Prints a nag. diff --git a/api/src/main/java/net/kyori/adventure/util/ShadyPines.java b/api/src/main/java/net/kyori/adventure/util/ShadyPines.java index ea27674a3..e1d2c621f 100644 --- a/api/src/main/java/net/kyori/adventure/util/ShadyPines.java +++ b/api/src/main/java/net/kyori/adventure/util/ShadyPines.java @@ -23,10 +23,6 @@ */ package net.kyori.adventure.util; -import java.util.Set; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; - /** * Various utilities. * @@ -36,24 +32,6 @@ public final class ShadyPines { private ShadyPines() { } - /** - * Creates a set from an array of enum constants. - * - * @param type the enum type - * @param constants the enum constants - * @param the enum type - * @return the set - * @since 4.0.0 - * @deprecated for removal since 4.8.0, use {@link MonkeyBars#enumSet(Class, Enum[])} - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @SafeVarargs - @SuppressWarnings("varargs") - public static > @NotNull Set enumSet(final Class type, final E@NotNull... constants) { - return MonkeyBars.enumSet(type, constants); - } - /** * Checks if {@code a} is equal to {@code b}. * diff --git a/api/src/main/java/net/kyori/adventure/util/TriState.java b/api/src/main/java/net/kyori/adventure/util/TriState.java index 4219e0749..4b7a10d34 100644 --- a/api/src/main/java/net/kyori/adventure/util/TriState.java +++ b/api/src/main/java/net/kyori/adventure/util/TriState.java @@ -59,11 +59,11 @@ public enum TriState { * @since 4.10.0 */ public @Nullable Boolean toBoolean() { - switch (this) { - case TRUE: return Boolean.TRUE; - case FALSE: return Boolean.FALSE; - default: return null; - } + return switch (this) { + case TRUE -> Boolean.TRUE; + case FALSE -> Boolean.FALSE; + default -> null; + }; } /** @@ -79,11 +79,11 @@ public enum TriState { * @since 4.10.0 */ public boolean toBooleanOrElse(final boolean other) { - switch (this) { - case TRUE: return true; - case FALSE: return false; - default: return other; - } + return switch (this) { + case TRUE -> true; + case FALSE -> false; + default -> other; + }; } /** @@ -99,11 +99,11 @@ public boolean toBooleanOrElse(final boolean other) { * @since 4.10.0 */ public boolean toBooleanOrElseGet(final @NotNull BooleanSupplier supplier) { - switch (this) { - case TRUE: return true; - case FALSE: return false; - default: return supplier.getAsBoolean(); - } + return switch (this) { + case TRUE -> true; + case FALSE -> false; + default -> supplier.getAsBoolean(); + }; } /** diff --git a/api/src/test/java/net/kyori/adventure/inventory/BookTest.java b/api/src/test/java/net/kyori/adventure/inventory/BookTest.java index 31d8e5858..d64eb0ecb 100644 --- a/api/src/test/java/net/kyori/adventure/inventory/BookTest.java +++ b/api/src/test/java/net/kyori/adventure/inventory/BookTest.java @@ -79,12 +79,6 @@ void testPages() { assertEquals(listOfPages(2), b1.pages()); } - @Test - void testRebuild() { - final Book book = Book.book(TITLE, AUTHOR, arrayOfPages(1)); - assertEquals(book, book.toBuilder().build()); - } - @Test void testBuild() { final Book b0 = Book.builder() diff --git a/api/src/test/java/net/kyori/adventure/pointer/PointersTest.java b/api/src/test/java/net/kyori/adventure/pointer/PointersTest.java index 08ab2a766..beb6a7e17 100644 --- a/api/src/test/java/net/kyori/adventure/pointer/PointersTest.java +++ b/api/src/test/java/net/kyori/adventure/pointer/PointersTest.java @@ -85,10 +85,6 @@ public void ofPointersSuppliers() { final Pointers childPointers = child.view(10); assertEquals("0", childPointers.get(p0).get()); assertEquals("1", childPointers.get(p1).get()); - - final Pointers rebuilt = childPointers.toBuilder().withStatic(p0, "1").build(); - assertEquals("1", rebuilt.get(p0).get()); - assertEquals("1", rebuilt.get(p1).get()); } @Test @@ -106,9 +102,5 @@ public void ofPointersSuppliersWithNoParent() { final Pointers pointer = supplier.view(10); assertFalse(pointer.get(p0).isPresent()); assertEquals("1", pointer.get(p1).get()); - - final Pointers rebuilt = pointer.toBuilder().withStatic(p0, "1").build(); - assertEquals("1", rebuilt.get(p0).get()); - assertEquals("1", rebuilt.get(p1).get()); } } diff --git a/api/src/test/java/net/kyori/adventure/text/title/TitleTest.java b/api/src/test/java/net/kyori/adventure/text/title/TitleTest.java index 043d39316..925d3cb76 100644 --- a/api/src/test/java/net/kyori/adventure/text/title/TitleTest.java +++ b/api/src/test/java/net/kyori/adventure/text/title/TitleTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; public class TitleTest { @@ -63,20 +62,6 @@ void testGetTitleParts() { assertEquals(this.times, title.part(TitlePart.TIMES)); } - @Test - void testIllegalTitleParts() { - final Title title = Title.title(this.foo, this.bar); - final TitlePart unknownPart = new TitlePart() { - @Override - public String toString() { - return "TitlePart.CAT"; - } - }; - - assertThrows(IllegalArgumentException.class, () -> title.part(unknownPart)); - assertThrows(NullPointerException.class, () -> title.part(null)); - } - @Test void testEquality() { final Title title = Title.title(this.foo, this.bar, this.times); diff --git a/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/GsonComponentSerializer.java b/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/GsonComponentSerializer.java index 9a88e6d93..3834ec78e 100644 --- a/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/GsonComponentSerializer.java +++ b/text-serializer-gson/src/main/java/net/kyori/adventure/text/serializer/gson/GsonComponentSerializer.java @@ -32,7 +32,6 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; import net.kyori.adventure.text.serializer.json.JSONOptions; -import net.kyori.adventure.util.Buildable; import net.kyori.adventure.util.PlatformAPI; import net.kyori.option.OptionState; import org.jetbrains.annotations.ApiStatus; diff --git a/text-serializer-legacy/src/main/java/net/kyori/adventure/text/serializer/legacy/LegacyComponentSerializer.java b/text-serializer-legacy/src/main/java/net/kyori/adventure/text/serializer/legacy/LegacyComponentSerializer.java index 9865494b6..951224300 100644 --- a/text-serializer-legacy/src/main/java/net/kyori/adventure/text/serializer/legacy/LegacyComponentSerializer.java +++ b/text-serializer-legacy/src/main/java/net/kyori/adventure/text/serializer/legacy/LegacyComponentSerializer.java @@ -35,7 +35,6 @@ import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.serializer.ComponentSerializer; -import net.kyori.adventure.util.Buildable; import net.kyori.adventure.util.PlatformAPI; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; diff --git a/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainComponentSerializer.java b/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainComponentSerializer.java index f2f0b48a3..d8d7bb8c4 100644 --- a/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainComponentSerializer.java +++ b/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainComponentSerializer.java @@ -33,7 +33,6 @@ import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.serializer.ComponentSerializer; -import net.kyori.adventure.util.Buildable; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainTextComponentSerializer.java b/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainTextComponentSerializer.java index 695cb1c4d..7c96bbdc8 100644 --- a/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainTextComponentSerializer.java +++ b/text-serializer-plain/src/main/java/net/kyori/adventure/text/serializer/plain/PlainTextComponentSerializer.java @@ -31,7 +31,6 @@ import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.serializer.ComponentSerializer; -import net.kyori.adventure.util.Buildable; import net.kyori.adventure.util.PlatformAPI; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; From d3168986e44f2b8db061f897eaeed2c499bd367a Mon Sep 17 00:00:00 2001 From: Kieran Wallbanks Date: Fri, 10 Oct 2025 14:05:43 +0100 Subject: [PATCH 05/91] chore(api): Further refactor (including `text` package) to remove deprecations and use modern language features --- .../kyori/adventure/bossbar/BossBarImpl.java | 6 +- .../kyori/adventure/identity/NilIdentity.java | 3 + .../net/kyori/adventure/inventory/Book.java | 3 +- .../kyori/adventure/inventory/BookImpl.java | 10 +- .../permission/PermissionCheckers.java | 3 +- .../net/kyori/adventure/pointer/Pointers.java | 3 +- .../kyori/adventure/pointer/PointersImpl.java | 11 +- .../pointer/PointersSupplierImpl.java | 55 +- .../resource/ResourcePackInfoImpl.java | 2 +- .../kyori/adventure/sound/SoundStopImpl.java | 8 - .../adventure/text/AbstractComponent.java | 90 --- .../text/AbstractComponentBuilder.java | 26 +- .../text/AbstractNBTComponentBuilder.java | 4 +- .../adventure/text/BlockNBTComponent.java | 52 +- .../adventure/text/BlockNBTComponentImpl.java | 172 +----- .../net/kyori/adventure/text/Component.java | 232 +------- .../adventure/text/ComponentBuilder.java | 9 +- .../adventure/text/ComponentCompaction.java | 10 +- .../adventure/text/ComponentInternals.java | 31 -- .../adventure/text/ComponentIteratorFlag.java | 7 +- .../adventure/text/ComponentIteratorType.java | 55 +- .../text/ComponentIteratorTypeImpl.java | 69 +++ .../adventure/text/EntityNBTComponent.java | 4 +- .../text/EntityNBTComponentImpl.java | 50 +- .../adventure/text/JoinConfiguration.java | 6 +- .../adventure/text/JoinConfigurationImpl.java | 88 +-- .../adventure/text/KeybindComponent.java | 6 +- .../adventure/text/KeybindComponentImpl.java | 34 +- .../text/LegacyFormattingDetected.java | 2 + .../adventure/text/LinearComponents.java | 17 +- .../kyori/adventure/text/NBTComponent.java | 11 +- .../adventure/text/NBTComponentBuilder.java | 2 +- .../adventure/text/NBTComponentImpl.java | 72 --- .../kyori/adventure/text/ObjectComponent.java | 6 +- .../adventure/text/ObjectComponentImpl.java | 47 +- .../kyori/adventure/text/ScopedComponent.java | 4 +- .../kyori/adventure/text/ScoreComponent.java | 44 +- .../adventure/text/ScoreComponentImpl.java | 87 +-- .../adventure/text/SelectorComponent.java | 6 +- .../adventure/text/SelectorComponentImpl.java | 42 +- .../adventure/text/StorageNBTComponent.java | 4 +- .../text/StorageNBTComponentImpl.java | 50 +- .../kyori/adventure/text/TextComponent.java | 20 +- .../adventure/text/TextComponentImpl.java | 23 +- .../adventure/text/TextReplacementConfig.java | 4 +- .../text/TextReplacementConfigImpl.java | 37 +- .../adventure/text/TranslatableComponent.java | 129 +---- .../text/TranslatableComponentImpl.java | 66 +-- .../adventure/text/TranslationArgument.java | 4 +- .../text/TranslationArgumentImpl.java | 30 +- .../adventure/text/VirtualComponent.java | 4 +- .../adventure/text/VirtualComponentImpl.java | 3 +- .../adventure/text/event/ClickCallback.java | 8 +- .../text/event/ClickCallbackInternals.java | 2 +- .../text/event/ClickCallbackOptionsImpl.java | 24 +- .../adventure/text/event/ClickEvent.java | 427 +++++--------- .../adventure/text/event/ClickEventImpl.java | 64 +++ .../DataComponentValueConversionImpl.java | 39 +- .../DataComponentValueConverterRegistry.java | 24 +- .../adventure/text/event/HoverEvent.java | 524 ++++-------------- .../adventure/text/event/HoverEventImpl.java | 190 +++++++ .../adventure/text/event/PayloadImpl.java | 123 +--- .../text/flattener/ComponentFlattener.java | 4 +- .../flattener/ComponentFlattenerImpl.java | 52 +- .../adventure/text/format/DecorationMap.java | 6 +- .../text/format/MutableStyleSetter.java | 4 +- .../adventure/text/format/NamedTextColor.java | 176 ++---- .../text/format/NamedTextColorImpl.java | 66 +++ .../adventure/text/format/ShadowColor.java | 3 +- .../text/format/ShadowColorImpl.java | 31 +- .../kyori/adventure/text/format/Style.java | 32 +- .../text/format/StyleBuilderApplicable.java | 1 - .../adventure/text/format/StyleImpl.java | 3 +- .../adventure/text/format/StyleSetter.java | 6 +- .../adventure/text/format/TextColor.java | 5 +- .../adventure/text/format/TextColorImpl.java | 28 +- .../adventure/text/format/TextDecoration.java | 42 +- .../text/format/TextDecorationAndState.java | 4 +- .../format/TextDecorationAndStateImpl.java | 33 +- .../adventure/text/object/ObjectContents.java | 3 +- .../text/object/PlayerHeadObjectContents.java | 5 +- .../object/PlayerHeadObjectContentsImpl.java | 135 +---- .../text/object/SpriteObjectContents.java | 4 +- .../text/object/SpriteObjectContentsImpl.java | 40 +- .../renderer/AbstractComponentRenderer.java | 39 +- .../TranslatableComponentRenderer.java | 3 +- .../text/serializer/ComponentSerializer.java | 18 - .../kyori/adventure/title/TitlePartImpl.java | 4 +- .../Buildable.java} | 15 +- .../net/kyori/adventure/util/MonkeyBars.java | 8 +- .../util/UTF8ResourceBundleControl.java | 12 - .../adventure/text/event/HoverEventTest.java | 48 +- .../configurate4/ComponentTypeSerializer.java | 1 - .../ConfigurateComponentSerializerImpl.java | 12 +- .../HoverEventShowEntitySerializer.java | 10 +- .../HoverEventShowItemSerializer.java | 12 +- .../configurate4/StyleSerializer.java | 34 +- .../configurate4/TextColorSerializer.java | 3 +- .../HoverEventSerializersTest.java | 9 +- .../minimessage/tag/standard/ClickTag.java | 12 +- .../tag/standard/ColorTagResolver.java | 3 +- .../minimessage/tag/standard/GradientTag.java | 3 +- .../minimessage/tag/standard/HoverTag.java | 41 +- .../tag/standard/StandardTags.java | 4 +- .../NBTLegacyHoverEventSerializer.java | 8 +- .../NBTLegacyHoverEventSerializerImpl.java | 10 +- .../gson/ClickEventActionSerializer.java | 4 +- .../gson/ComponentSerializerImpl.java | 1 - .../gson/GsonComponentSerializer.java | 5 +- .../gson/HoverEventActionSerializer.java | 4 +- .../serializer/gson/SerializerFactory.java | 12 +- .../serializer/gson/ShowEntitySerializer.java | 12 +- .../serializer/gson/ShowItemSerializer.java | 16 +- .../text/serializer/gson/StyleSerializer.java | 14 +- .../serializer/gson/TextColorSerializer.java | 3 +- .../NBTLegacyHoverEventSerializer.java | 8 +- .../NBTLegacyHoverEventSerializerImpl.java | 14 +- .../json/JSONComponentSerializer.java | 5 +- .../json/LegacyHoverEventSerializer.java | 10 +- .../text/serializer/json/SerializerTest.java | 12 +- .../json/ShowItemSerializerTest.java | 9 +- .../text/serializer/json/StyleTest.java | 8 +- .../serializer/json/TextComponentTest.java | 3 +- .../json/TranslatableComponentTest.java | 8 +- .../serializer/legacy/CharacterAndFormat.java | 33 +- .../legacy/LegacyComponentSerializer.java | 14 +- .../legacy/LegacyComponentSerializerImpl.java | 7 +- .../plain/PlainComponentSerializer.java | 6 +- .../plain/PlainTextComponentSerializer.java | 6 +- 129 files changed, 1293 insertions(+), 3101 deletions(-) delete mode 100644 api/src/main/java/net/kyori/adventure/text/AbstractComponent.java delete mode 100644 api/src/main/java/net/kyori/adventure/text/ComponentInternals.java create mode 100644 api/src/main/java/net/kyori/adventure/text/ComponentIteratorTypeImpl.java delete mode 100644 api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java create mode 100644 api/src/main/java/net/kyori/adventure/text/event/ClickEventImpl.java create mode 100644 api/src/main/java/net/kyori/adventure/text/event/HoverEventImpl.java create mode 100644 api/src/main/java/net/kyori/adventure/text/format/NamedTextColorImpl.java rename api/src/main/java/net/kyori/adventure/{text/BuildableComponent.java => util/Buildable.java} (80%) diff --git a/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java b/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java index 1862b942a..f7d7bce01 100644 --- a/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java +++ b/api/src/main/java/net/kyori/adventure/bossbar/BossBarImpl.java @@ -210,12 +210,12 @@ public boolean hasFlag(final @NotNull Flag flag) { private @NotNull BossBar editFlags(final Flag[] flags, final BiPredicate, Flag> predicate, final BiConsumer> onChange) { if (flags.length == 0) return this; Set changes = null; - for (int i = 0, length = flags.length; i < length; i++) { - if (predicate.test(this.flags, flags[i])) { + for (final Flag flag : flags) { + if (predicate.test(this.flags, flag)) { if (changes == null) { changes = EnumSet.noneOf(Flag.class); } - changes.add(flags[i]); + changes.add(flag); } } if (changes != null) { diff --git a/api/src/main/java/net/kyori/adventure/identity/NilIdentity.java b/api/src/main/java/net/kyori/adventure/identity/NilIdentity.java index 68236e4e7..800f448a4 100644 --- a/api/src/main/java/net/kyori/adventure/identity/NilIdentity.java +++ b/api/src/main/java/net/kyori/adventure/identity/NilIdentity.java @@ -31,6 +31,9 @@ final class NilIdentity implements Identity { static final UUID NIL_UUID = new UUID(0, 0); static final Identity INSTANCE = new NilIdentity(); + private NilIdentity() { + } + @Override public @NotNull UUID uuid() { return NIL_UUID; diff --git a/api/src/main/java/net/kyori/adventure/inventory/Book.java b/api/src/main/java/net/kyori/adventure/inventory/Book.java index 1ba204a21..1f64c6c1e 100644 --- a/api/src/main/java/net/kyori/adventure/inventory/Book.java +++ b/api/src/main/java/net/kyori/adventure/inventory/Book.java @@ -30,6 +30,7 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.builder.AbstractBuilder; import net.kyori.adventure.text.Component; +import net.kyori.adventure.util.Buildable; import net.kyori.examination.Examinable; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -45,7 +46,7 @@ * @see Audience#openBook(Book) * @since 4.0.0 */ -public sealed interface Book extends Examinable permits BookImpl { +public sealed interface Book extends Buildable, Examinable permits BookImpl { /** * Creates a book. * diff --git a/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java b/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java index 6a21cdc0f..8582409e5 100644 --- a/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java +++ b/api/src/main/java/net/kyori/adventure/inventory/BookImpl.java @@ -86,6 +86,14 @@ record BookImpl(Component title, Component author, List pages) implem return Internals.toString(this); } + @Override + public @NotNull Builder toBuilder() { + return new BuilderImpl() + .title(this.title) + .author(this.author) + .pages(this.pages); + } + static final class BuilderImpl implements Builder { private Component title = Component.empty(); private Component author = Component.empty(); @@ -123,7 +131,7 @@ static final class BuilderImpl implements Builder { @Override public @NotNull Book build() { - return new BookImpl(this.title, this.author, new ArrayList<>(this.pages)); + return new BookImpl(this.title, this.author, List.copyOf(this.pages)); } } } diff --git a/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java b/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java index a5fcc56e7..0aa38f109 100644 --- a/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java +++ b/api/src/main/java/net/kyori/adventure/permission/PermissionCheckers.java @@ -35,8 +35,7 @@ private PermissionCheckers() { } private record Always(TriState value) implements PermissionChecker { - - @Override + @Override public @NotNull TriState value(final @NotNull String permission) { return this.value; } diff --git a/api/src/main/java/net/kyori/adventure/pointer/Pointers.java b/api/src/main/java/net/kyori/adventure/pointer/Pointers.java index b13e5b644..2216c8b50 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/Pointers.java +++ b/api/src/main/java/net/kyori/adventure/pointer/Pointers.java @@ -26,6 +26,7 @@ import java.util.Optional; import java.util.function.Supplier; import net.kyori.adventure.builder.AbstractBuilder; +import net.kyori.adventure.util.Buildable; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,7 +37,7 @@ * * @since 4.8.0 */ -public sealed interface Pointers permits PointersImpl, PointersSupplierImpl.ForwardingPointers { +public sealed interface Pointers extends Buildable permits PointersImpl, PointersSupplierImpl.ForwardingPointers { /** * Gets an empty pointers collection. * diff --git a/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java b/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java index 5d55ea33c..5b13058c2 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java +++ b/api/src/main/java/net/kyori/adventure/pointer/PointersImpl.java @@ -35,7 +35,7 @@ record PointersImpl(Map, Supplier> pointers) implements Pointers { static final PointersImpl EMPTY = new PointersImpl(Map.of()); PointersImpl(final @NotNull BuilderImpl pointers) { - this(new HashMap<>(pointers.pointers)); + this(Map.copyOf(pointers.pointers)); } @Override @@ -56,6 +56,11 @@ public boolean supports(final @NotNull Pointer pointer) { return this.pointers.containsKey(pointer); } + @Override + public @NotNull Builder toBuilder() { + return new BuilderImpl(this); + } + static final class BuilderImpl implements Builder { private final Map, Supplier> pointers; @@ -63,6 +68,10 @@ static final class BuilderImpl implements Builder { this.pointers = new HashMap<>(); } + BuilderImpl(final @NotNull PointersImpl pointers) { + this.pointers = new HashMap<>(pointers.pointers); + } + @Override public @NotNull Builder withDynamic(final @NotNull Pointer pointer, final @NotNull Supplier<@Nullable T> value) { this.pointers.put(Objects.requireNonNull(pointer, "pointer"), Objects.requireNonNull(value, "value")); diff --git a/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java b/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java index bf0a391dc..80449a384 100644 --- a/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java +++ b/api/src/main/java/net/kyori/adventure/pointer/PointersSupplierImpl.java @@ -28,6 +28,7 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Function; +import java.util.function.Supplier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +38,7 @@ final class PointersSupplierImpl implements PointersSupplier { PointersSupplierImpl(final @NotNull BuilderImpl builder) { this.parent = builder.parent; - this.resolvers = new HashMap<>(builder.resolvers); + this.resolvers = Map.copyOf(builder.resolvers); } @Override @@ -71,32 +72,44 @@ public

boolean supports(final @NotNull Pointer

pointer) { } record ForwardingPointers(U instance, PointersSupplierImpl supplier) implements Pointers { - @Override - @SuppressWarnings("unchecked") // all values are checked on entry - public @NotNull Optional get(final @NotNull Pointer pointer) { - Function resolver = this.supplier.resolvers.get(Objects.requireNonNull(pointer, "pointer")); - - // Fallback to the parent. - if (resolver == null) { - final PointersSupplier parent = this.supplier.parent; - if (parent != null) { - resolver = parent.resolver(pointer); - } + @Override + @SuppressWarnings("unchecked") // all values are checked on entry + public @NotNull Optional get(final @NotNull Pointer pointer) { + Function resolver = this.supplier.resolvers.get(Objects.requireNonNull(pointer, "pointer")); + + // Fallback to the parent. + if (resolver == null) { + final PointersSupplier parent = this.supplier.parent; + if (parent != null) { + resolver = parent.resolver(pointer); } + } - // Finally, wrap in an optional. - if (resolver == null) { - return Optional.empty(); - } else { - return Optional.ofNullable((T) resolver.apply(this.instance)); - } + // Finally, wrap in an optional. + if (resolver == null) { + return Optional.empty(); + } else { + return Optional.ofNullable((T) resolver.apply(this.instance)); } + } - @Override - public boolean supports(final @NotNull Pointer pointer) { - return this.supplier.supports(pointer); + @Override + public boolean supports(final @NotNull Pointer pointer) { + return this.supplier.supports(pointer); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) // all values are checked on entry + public @NotNull Builder toBuilder() { + final Pointers.Builder builder = this.supplier.parent == null ? Pointers.builder() : this.supplier.parent.view(this.instance).toBuilder(); + + for (final Map.Entry, Function> entry : this.supplier.resolvers.entrySet()) { + builder.withDynamic(entry.getKey(), (Supplier) () -> entry.getValue().apply(this.instance)); } + + return builder; } + } static final class BuilderImpl implements Builder { private @Nullable PointersSupplier parent = null; diff --git a/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java b/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java index 27d45f696..c57db4f0e 100644 --- a/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java +++ b/api/src/main/java/net/kyori/adventure/resource/ResourcePackInfoImpl.java @@ -136,7 +136,7 @@ static CompletableFuture computeHash(final URI uri, final Executor exec) static String bytesToString(final byte[] arr) { final StringBuilder builder = new StringBuilder(arr.length * 2); final Formatter fmt = new Formatter(builder, Locale.ROOT); - for (byte b : arr) { + for (final byte b : arr) { fmt.format("%02x", b & 0xff); } return builder.toString(); diff --git a/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java b/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java index 5cb3e7966..9043705d2 100644 --- a/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java +++ b/api/src/main/java/net/kyori/adventure/sound/SoundStopImpl.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.sound; -import java.util.Objects; import java.util.stream.Stream; import net.kyori.adventure.internal.Internals; import net.kyori.adventure.key.Key; @@ -34,13 +33,6 @@ record SoundStopImpl(@Nullable Key sound, Sound.@Nullable Source source) implements SoundStop { static final SoundStopImpl ALL = new SoundStopImpl(null, null); - @Override - public int hashCode() { - int result = Objects.hashCode(this.sound()); - result = (31 * result) + Objects.hashCode(this.source); - return result; - } - @Override public @NotNull Stream examinableProperties() { return Stream.of( diff --git a/api/src/main/java/net/kyori/adventure/text/AbstractComponent.java b/api/src/main/java/net/kyori/adventure/text/AbstractComponent.java deleted file mode 100644 index 937b6e5df..000000000 --- a/api/src/main/java/net/kyori/adventure/text/AbstractComponent.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.text; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; -import net.kyori.adventure.text.format.Style; -import net.kyori.examination.ExaminableProperty; -import net.kyori.examination.string.StringExaminer; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Debug; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * An abstract implementation of a text component. - * - * @since 4.0.0 - * @deprecated for removal since 4.10.0 - */ -@ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") -@Debug.Renderer(text = "this.debuggerString()", childrenArray = "this.children().toArray()", hasChildren = "!this.children().isEmpty()") -@Deprecated -public abstract class AbstractComponent implements Component { - protected final List children; - protected final Style style; - - protected AbstractComponent(final @NotNull List children, final @NotNull Style style) { - this.children = ComponentLike.asComponents(children, IS_NOT_EMPTY); - this.style = style; - } - - @Override - public final @NotNull List children() { - return this.children; - } - - @Override - public final @NotNull Style style() { - return this.style; - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof AbstractComponent)) return false; - final AbstractComponent that = (AbstractComponent) other; - return Objects.equals(this.children, that.children) - && Objects.equals(this.style, that.style); - } - - @Override - public int hashCode() { - int result = this.children.hashCode(); - result = (31 * result) + this.style.hashCode(); - return result; - } - - @Override - public abstract String toString(); - - @SuppressWarnings("unused") - private String debuggerString() { - final Stream examinablePropertiesWithoutChildren = this.examinableProperties() - .filter(property -> !property.name().equals(ComponentInternals.CHILDREN_PROPERTY)); - return StringExaminer.simpleEscaping().examine(this.examinableName(), examinablePropertiesWithoutChildren); - } -} diff --git a/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java index 300ab50e6..6a85ab642 100644 --- a/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java @@ -48,7 +48,7 @@ * @param the component type * @param the builder type */ -abstract class AbstractComponentBuilder, B extends ComponentBuilder> implements ComponentBuilder { +abstract sealed class AbstractComponentBuilder> implements ComponentBuilder permits AbstractNBTComponentBuilder, KeybindComponentImpl.BuilderImpl, ObjectComponentImpl.BuilderImpl, ScoreComponentImpl.BuilderImpl, SelectorComponentImpl.BuilderImpl, TextComponentImpl.BuilderImpl, TranslatableComponentImpl.BuilderImpl { // We use an empty list by default to prevent unnecessary list creation for components with no children protected List children = Collections.emptyList(); /* @@ -91,8 +91,8 @@ protected AbstractComponentBuilder(final @NotNull C component) { public @NotNull B append(final @NotNull ComponentLike@NotNull... components) { requireNonNull(components, "components"); boolean prepared = false; - for (int i = 0, length = components.length; i < length; i++) { - final Component component = requireNonNull(components[i], "components[?]").asComponent(); + for (final ComponentLike componentLike : components) { + final Component component = requireNonNull(componentLike, "components[?]").asComponent(); if (component != Component.empty()) { if (!prepared) { this.prepareChildren(); @@ -137,11 +137,7 @@ private void prepareChildren() { } final ListIterator it = this.children.listIterator(); while (it.hasNext()) { - final Component child = it.next(); - if (!(child instanceof BuildableComponent)) { - continue; - } - final ComponentBuilder childBuilder = ((BuildableComponent) child).toBuilder(); + final ComponentBuilder childBuilder = it.next().toBuilder(); childBuilder.applyDeep(consumer); it.set(childBuilder.build()); } @@ -150,17 +146,14 @@ private void prepareChildren() { @Override @SuppressWarnings("unchecked") - public @NotNull B mapChildren(final @NotNull Function, ? extends BuildableComponent> function) { + public @NotNull B mapChildren(final @NotNull Function function) { if (this.children == Collections.emptyList()) { return (B) this; } final ListIterator it = this.children.listIterator(); while (it.hasNext()) { final Component child = it.next(); - if (!(child instanceof BuildableComponent)) { - continue; - } - final BuildableComponent mappedChild = requireNonNull(function.apply((BuildableComponent) child), "mappedChild"); + final Component mappedChild = requireNonNull(function.apply(child), "mappedChild"); if (child == mappedChild) { continue; } @@ -171,17 +164,14 @@ private void prepareChildren() { @Override @SuppressWarnings("unchecked") - public @NotNull B mapChildrenDeep(final @NotNull Function, ? extends BuildableComponent> function) { + public @NotNull B mapChildrenDeep(final @NotNull Function function) { if (this.children == Collections.emptyList()) { return (B) this; } final ListIterator it = this.children.listIterator(); while (it.hasNext()) { final Component child = it.next(); - if (!(child instanceof BuildableComponent)) { - continue; - } - final BuildableComponent mappedChild = requireNonNull(function.apply((BuildableComponent) child), "mappedChild"); + final Component mappedChild = requireNonNull(function.apply(child), "mappedChild"); if (mappedChild.children().isEmpty()) { if (child == mappedChild) { continue; diff --git a/api/src/main/java/net/kyori/adventure/text/AbstractNBTComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/AbstractNBTComponentBuilder.java index 9a1c1ec37..637726374 100644 --- a/api/src/main/java/net/kyori/adventure/text/AbstractNBTComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/AbstractNBTComponentBuilder.java @@ -28,9 +28,9 @@ import static java.util.Objects.requireNonNull; -abstract class AbstractNBTComponentBuilder, B extends NBTComponentBuilder> extends AbstractComponentBuilder implements NBTComponentBuilder { +abstract sealed class AbstractNBTComponentBuilder, B extends NBTComponentBuilder> extends AbstractComponentBuilder implements NBTComponentBuilder permits EntityNBTComponentImpl.BuilderImpl, StorageNBTComponentImpl.BuilderImpl { protected @Nullable String nbtPath; - protected boolean interpret = NBTComponentImpl.INTERPRET_DEFAULT; + protected boolean interpret = NBTComponent.INTERPRET_DEFAULT; protected @Nullable Component separator; AbstractNBTComponentBuilder() { diff --git a/api/src/main/java/net/kyori/adventure/text/BlockNBTComponent.java b/api/src/main/java/net/kyori/adventure/text/BlockNBTComponent.java index 795547eec..d16e667f9 100644 --- a/api/src/main/java/net/kyori/adventure/text/BlockNBTComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/BlockNBTComponent.java @@ -27,7 +27,6 @@ import java.util.stream.Stream; import net.kyori.examination.Examinable; import net.kyori.examination.ExaminableProperty; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -46,7 +45,7 @@ * @since 4.0.0 * @sinceMinecraft 1.14 */ -public interface BlockNBTComponent extends NBTComponent, ScopedComponent { +public sealed interface BlockNBTComponent extends NBTComponent, ScopedComponent permits BlockNBTComponentImpl { /** * Gets the block position. * @@ -136,7 +135,7 @@ public interface BlockNBTComponent extends NBTComponent { + sealed interface Builder extends NBTComponentBuilder permits BlockNBTComponentImpl.BuilderImpl { /** * Sets the block position. * @@ -273,22 +272,6 @@ interface LocalPos extends Pos { return new BlockNBTComponentImpl.LocalPosImpl(left, up, forwards); } - /** - * Creates a local position with the given values. - * - * @param left the left value - * @param up the up value - * @param forwards the forwards value - * @return a local position - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #localPos(double, double, double)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull LocalPos of(final double left, final double up, final double forwards) { - return new BlockNBTComponentImpl.LocalPosImpl(left, up, forwards); - } - /** * Gets the left value. * @@ -333,22 +316,6 @@ interface WorldPos extends Pos { return new BlockNBTComponentImpl.WorldPosImpl(x, y, z); } - /** - * Creates a world position with the given coordinates. - * - * @param x the x coordinate - * @param y the y coordinate - * @param z the z coordinate - * @return a world position - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #worldPos(WorldPos.Coordinate, WorldPos.Coordinate, WorldPos.Coordinate)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull WorldPos of(final @NotNull Coordinate x, final @NotNull Coordinate y, final @NotNull Coordinate z) { - return new BlockNBTComponentImpl.WorldPosImpl(x, y, z); - } - /** * Gets the x coordinate. * @@ -413,21 +380,6 @@ interface Coordinate extends Examinable { return new BlockNBTComponentImpl.WorldPosImpl.CoordinateImpl(value, type); } - /** - * Creates a coordinate with the given value and type. - * - * @param value the value - * @param type the type - * @return a coordinate - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #coordinate(int, Coordinate.Type)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - static @NotNull Coordinate of(final int value, final @NotNull Type type) { - return new BlockNBTComponentImpl.WorldPosImpl.CoordinateImpl(value, type); - } - /** * Gets the value. * diff --git a/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java index 375a1b28c..ef5e7fb05 100644 --- a/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java @@ -29,16 +29,20 @@ import java.util.stream.Stream; import net.kyori.adventure.internal.Internals; import net.kyori.adventure.text.format.Style; -import net.kyori.adventure.util.ShadyPines; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static java.util.Objects.requireNonNull; -final class BlockNBTComponentImpl extends NBTComponentImpl implements BlockNBTComponent { - private final Pos pos; - +record BlockNBTComponentImpl( + List children, + Style style, + String nbtPath, + boolean interpret, + @Nullable Component separator, + Pos pos +) implements BlockNBTComponent { static BlockNBTComponent create(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator, final @NotNull Pos pos) { return new BlockNBTComponentImpl( ComponentLike.asComponents(children, IS_NOT_EMPTY), @@ -50,11 +54,6 @@ static BlockNBTComponent create(final @NotNull List chi ); } - BlockNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable Component separator, final @NotNull Pos pos) { - super(children, style, nbtPath, interpret, separator); - this.pos = pos; - } - @Override public @NotNull BlockNBTComponent nbtPath(final @NotNull String nbtPath) { if (Objects.equals(this.nbtPath, nbtPath)) return this; @@ -67,21 +66,11 @@ static BlockNBTComponent create(final @NotNull List chi return create(this.children, this.style, this.nbtPath, interpret, this.separator, this.pos); } - @Override - public @Nullable Component separator() { - return this.separator; - } - @Override public @NotNull BlockNBTComponent separator(final @Nullable ComponentLike separator) { return create(this.children, this.style, this.nbtPath, this.interpret, separator, this.pos); } - @Override - public @NotNull Pos pos() { - return this.pos; - } - @Override public @NotNull BlockNBTComponent pos(final @NotNull Pos pos) { return create(this.children, this.style, this.nbtPath, this.interpret, this.separator, pos); @@ -98,32 +87,16 @@ static BlockNBTComponent create(final @NotNull List chi } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof BlockNBTComponent)) return false; - if (!super.equals(other)) return false; - final BlockNBTComponent that = (BlockNBTComponent) other; - return Objects.equals(this.pos, that.pos()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.pos.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @Override - public BlockNBTComponent.@NotNull Builder toBuilder() { + public @NotNull Builder toBuilder() { return new BuilderImpl(this); } - static final class BuilderImpl extends AbstractNBTComponentBuilder implements BlockNBTComponent.Builder { + static final class BuilderImpl extends AbstractNBTComponentBuilder implements Builder { private @Nullable Pos pos; BuilderImpl() { @@ -135,7 +108,7 @@ static final class BuilderImpl extends AbstractNBTComponentBuilder examinableProperties() { return Stream.of( @@ -184,25 +132,7 @@ public double forwards() { } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof LocalPos)) return false; - final LocalPos that = (LocalPos) other; - return ShadyPines.equals(that.left(), this.left()) - && ShadyPines.equals(that.up(), this.up()) - && ShadyPines.equals(that.forwards(), this.forwards()); - } - - @Override - public int hashCode() { - int result = Double.hashCode(this.left); - result = (31 * result) + Double.hashCode(this.up); - result = (31 * result) + Double.hashCode(this.forwards); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return String.format("^%f ^%f ^%f", this.left, this.up, this.forwards); } @@ -212,32 +142,13 @@ public String toString() { } } - static final class WorldPosImpl implements WorldPos { - private final Coordinate x; - private final Coordinate y; - private final Coordinate z; - + record WorldPosImpl(Coordinate x, Coordinate y, Coordinate z) implements WorldPos { WorldPosImpl(final Coordinate x, final Coordinate y, final Coordinate z) { this.x = requireNonNull(x, "x"); this.y = requireNonNull(y, "y"); this.z = requireNonNull(z, "z"); } - @Override - public @NotNull Coordinate x() { - return this.x; - } - - @Override - public @NotNull Coordinate y() { - return this.y; - } - - @Override - public @NotNull Coordinate z() { - return this.z; - } - @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -248,25 +159,7 @@ static final class WorldPosImpl implements WorldPos { } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof WorldPos)) return false; - final WorldPos that = (WorldPos) other; - return this.x.equals(that.x()) - && this.y.equals(that.y()) - && this.z.equals(that.z()); - } - - @Override - public int hashCode() { - int result = this.x.hashCode(); - result = (31 * result) + this.y.hashCode(); - result = (31 * result) + this.z.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return this.x.toString() + ' ' + this.y.toString() + ' ' + this.z.toString(); } @@ -275,25 +168,12 @@ public String toString() { return Tokens.serializeCoordinate(this.x()) + ' ' + Tokens.serializeCoordinate(this.y()) + ' ' + Tokens.serializeCoordinate(this.z()); } - static final class CoordinateImpl implements Coordinate { - private final int value; - private final Type type; - + record CoordinateImpl(int value, Type type) implements Coordinate { CoordinateImpl(final int value, final @NotNull Type type) { this.value = value; this.type = requireNonNull(type, "type"); } - @Override - public int value() { - return this.value; - } - - @Override - public @NotNull Type type() { - return this.type; - } - @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -303,23 +183,7 @@ public int value() { } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof Coordinate)) return false; - final Coordinate that = (Coordinate) other; - return this.value() == that.value() - && this.type() == that.type(); - } - - @Override - public int hashCode() { - int result = this.value; - result = (31 * result) + this.type.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return (this.type == Type.RELATIVE ? "~" : "") + this.value; } } diff --git a/api/src/main/java/net/kyori/adventure/text/Component.java b/api/src/main/java/net/kyori/adventure/text/Component.java index 22d224fb4..38f0817d3 100644 --- a/api/src/main/java/net/kyori/adventure/text/Component.java +++ b/api/src/main/java/net/kyori/adventure/text/Component.java @@ -35,10 +35,8 @@ import java.util.Spliterators; import java.util.function.BiPredicate; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; -import java.util.regex.Pattern; import java.util.stream.Collector; import java.util.stream.Stream; import net.kyori.adventure.builder.AbstractBuilder; @@ -58,11 +56,9 @@ import net.kyori.adventure.translation.Translatable; import net.kyori.adventure.util.ARGBLike; import net.kyori.adventure.util.ForwardingIterator; -import net.kyori.adventure.util.IntFunction2; import net.kyori.adventure.util.MonkeyBars; import net.kyori.examination.Examinable; import net.kyori.examination.ExaminableProperty; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -110,8 +106,7 @@ * @see LinearComponents * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface Component extends ComponentBuilderApplicable, ComponentLike, Examinable, HoverEventSource, StyleGetter, StyleSetter { +public sealed interface Component extends ComponentBuilderApplicable, ComponentLike, Examinable, HoverEventSource, StyleGetter, StyleSetter permits NBTComponent, ScopedComponent { /** * A predicate that checks equality of two {@code Component}s using {@link Objects#equals(Object, Object)}. * @@ -161,41 +156,6 @@ public interface Component extends ComponentBuilderApplicable, ComponentLike, Ex return TextComponentImpl.SPACE; } - /** - * Joins {@code components} using {@code separator}. - * - * @param separator the separator - * @param components the components - * @return a text component - * @since 4.0.0 - * @deprecated for removal since 4.9.0, use {@link #join(JoinConfiguration, ComponentLike...)} with {@link JoinConfiguration#separator(ComponentLike)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @Contract(value = "_, _ -> new", pure = true) - static @NotNull TextComponent join(final @NotNull ComponentLike separator, final @NotNull ComponentLike@NotNull... components) { - return join(separator, Arrays.asList(components)); - } - - /** - * Joins {@code components} using {@code separator}. - * - * @param separator the separator - * @param components the components - * @return a text component - * @since 4.0.0 - * @deprecated for removal since 4.9.0, use {@link #join(JoinConfiguration, Iterable)} with {@link JoinConfiguration#separator(ComponentLike)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - @Contract(value = "_, _ -> new", pure = true) - static @NotNull TextComponent join(final @NotNull ComponentLike separator, final Iterable components) { - final Component component = join(JoinConfiguration.separator(separator), components); - - if (component instanceof TextComponent) return (TextComponent) component; - return Component.text().append(component).build(); - } - /** * Joins {@code components} using the configuration in {@code configBuilder}. * @@ -337,7 +297,7 @@ public interface Component extends ComponentBuilderApplicable, ComponentLike, Ex */ @Contract(value = "_, _ -> new", pure = true) static @NotNull BlockNBTComponent blockNBT(final @NotNull String nbtPath, final BlockNBTComponent.@NotNull Pos pos) { - return blockNBT(nbtPath, NBTComponentImpl.INTERPRET_DEFAULT, pos); + return blockNBT(nbtPath, NBTComponent.INTERPRET_DEFAULT, pos); } /** @@ -652,23 +612,7 @@ public interface Component extends ComponentBuilderApplicable, ComponentLike, Ex */ @Contract(value = "_, _ -> new", pure = true) static @NotNull ScoreComponent score(final @NotNull String name, final @NotNull String objective) { - return score(name, objective, null); - } - - /** - * Creates a score component with a name, objective, and optional value. - * - * @param name the score name - * @param objective the score objective - * @param value the value - * @return a score component - * @since 4.0.0 - * @deprecated since 4.7.0, not for removal, with no replacement. The {@code value} field is no longer supported in 1.16.5. - */ - @Contract(value = "_, _, _ -> new", pure = true) - @Deprecated - static @NotNull ScoreComponent score(final @NotNull String name, final @NotNull String objective, final @Nullable String value) { - return ScoreComponentImpl.create(Collections.emptyList(), Style.empty(), name, objective, value); + return ScoreComponentImpl.create(Collections.emptyList(), Style.empty(), name, objective); } /* @@ -764,7 +708,7 @@ public interface Component extends ComponentBuilderApplicable, ComponentLike, Ex */ @Contract(value = "_, _ -> new", pure = true) static @NotNull StorageNBTComponent storageNBT(final @NotNull String nbtPath, final @NotNull Key storage) { - return storageNBT(nbtPath, NBTComponentImpl.INTERPRET_DEFAULT, storage); + return storageNBT(nbtPath, NBTComponent.INTERPRET_DEFAULT, storage); } /** @@ -2061,8 +2005,8 @@ default boolean contains(final @NotNull Component that, final @NotNull BiPredica Component component = null; if (value instanceof Component) { component = (Component) hoverEvent.value(); - } else if (value instanceof HoverEvent.ShowEntity) { - component = ((HoverEvent.ShowEntity) value).name(); + } else if (value instanceof HoverEvent.ShowEntity se) { + component = se.name(); } if (component != null) { if (equals.test(that, component)) return true; @@ -2074,21 +2018,6 @@ default boolean contains(final @NotNull Component that, final @NotNull BiPredica return false; } - /** - * Prevents a cycle between this component and the provided component. - * - * @param that the other component - * @since 4.0.0 - * @deprecated for removal since 4.7.0, with no replacement - this method is not necessary due to the fact {@code Component}s are immutable - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - default void detectCycle(final @NotNull Component that) { - if (that.contains(this)) { - throw new IllegalStateException("Component cycle detected between " + this + " and " + that); - } - } - /** * Appends a component to this component. * @@ -2494,9 +2423,9 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) { } /** - * Gets a set of decorations this component has. + * Gets a map of decorations this component has. * - * @return a set of decorations this component has + * @return a map of decorations this component has * @since 4.0.0 */ @Override @@ -2526,7 +2455,7 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) { * @since 4.0.0 */ @Override - default @Nullable ClickEvent clickEvent() { + default @Nullable ClickEvent clickEvent() { return this.style().clickEvent(); } @@ -2539,7 +2468,7 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) { */ @Contract(pure = true) @Override - default @NotNull Component clickEvent(final @Nullable ClickEvent event) { + default @NotNull Component clickEvent(final @Nullable ClickEvent event) { return this.style(this.style().clickEvent(event)); } @@ -2627,9 +2556,6 @@ default boolean hasStyling() { @ScopedComponentOverrideNotRequired default @NotNull Component replaceText(final @NotNull TextReplacementConfig config) { requireNonNull(config, "replacement"); - if (!(config instanceof TextReplacementConfigImpl)) { - throw new IllegalArgumentException("Provided replacement was a custom TextReplacementConfig implementation, which is not supported."); - } return TextReplacementRenderer.INSTANCE.render(this, ((TextReplacementConfigImpl) config).createState()); } @@ -2740,140 +2666,12 @@ default boolean hasStyling() { } /** - * Finds and replaces text within any {@link Component}s using a string literal. - * - * @param search a string literal - * @param replacement a {@link ComponentLike} to replace each match - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceText(final @NotNull String search, final @Nullable ComponentLike replacement) { - return this.replaceText(b -> b.matchLiteral(search).replacement(replacement)); - } - - /** - * Finds and replaces text within any {@link TextComponent}s using a regex pattern. - * - * @param pattern a regex pattern - * @param replacement a function to replace each match - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceText(final @NotNull Pattern pattern, final @NotNull Function replacement) { - return this.replaceText(b -> b.match(pattern).replacement(replacement)); - } - - /** - * Finds and replaces the first occurrence of text within any {@link Component}s using a string literal. - * - * @param search a string literal - * @param replacement a {@link ComponentLike} to replace the first match - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceFirstText(final @NotNull String search, final @Nullable ComponentLike replacement) { - return this.replaceText(b -> b.matchLiteral(search).once().replacement(replacement)); - } - - /** - * Finds and replaces the first occurrence of text within any {@link TextComponent}s using a regex pattern. + * Returns a builder for this component. * - * @param pattern a regex pattern - * @param replacement a function to replace the first match - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. + * @return the builder + * @since 5.0.0 */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceFirstText(final @NotNull Pattern pattern, final @NotNull Function replacement) { - return this.replaceText(b -> b.match(pattern).once().replacement(replacement)); - } - - /** - * Finds and replaces {@code n} instances of text within any {@link TextComponent}s using a string literal. - * - * @param search a string literal - * @param replacement a {@link ComponentLike} to replace the first match - * @param numberOfReplacements the amount of matches that should be replaced - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceText(final @NotNull String search, final @Nullable ComponentLike replacement, final int numberOfReplacements) { - return this.replaceText(b -> b.matchLiteral(search).times(numberOfReplacements).replacement(replacement)); - } - - /** - * Finds and replaces {@code n} instances of text within any {@link TextComponent}s using a regex pattern. - * - * @param pattern a regex pattern - * @param replacement a function to replace each match - * @param numberOfReplacements the amount of matches that should be replaced - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceText(final @NotNull Pattern pattern, final @NotNull Function replacement, final int numberOfReplacements) { - return this.replaceText(b -> b.match(pattern).times(numberOfReplacements).replacement(replacement)); - } - - /** - * Finds and replaces {@code n} instances of text within any {@link TextComponent}s using a string literal. - * - *

Utilises an {@link IntFunction2} to determine if each instance should be replaced.

- * - * @param search a string literal - * @param replacement a {@link ComponentLike} to replace the first match - * @param fn a function of (index, replaced) used to determine if matches should be replaced, where "replaced" is the number of successful replacements - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceText(final @NotNull String search, final @Nullable ComponentLike replacement, final @NotNull IntFunction2 fn) { - return this.replaceText(b -> b.matchLiteral(search).replacement(replacement).condition(fn)); - } - - /** - * Finds and replaces text using a regex pattern. - * - *

Utilises an {@link IntFunction2} to determine if each instance should be replaced.

- * - * @param pattern a regex pattern - * @param replacement a function to replace the first match - * @param fn a function of (index, replaced) used to determine if matches should be replaced, where "replaced" is the number of successful replacements - * @return a modified copy of this component - * @since 4.0.0 - * @deprecated for removal since 4.2.0, use {@link #replaceText(Consumer)} or {@link #replaceText(TextReplacementConfig)} instead. - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Contract(pure = true) - @Deprecated - default @NotNull Component replaceText(final @NotNull Pattern pattern, final @NotNull Function replacement, final @NotNull IntFunction2 fn) { - return this.replaceText(b -> b.match(pattern).replacement(replacement).condition(fn)); - } + @NotNull ComponentBuilder toBuilder(); @Override default void componentBuilderApply(final @NotNull ComponentBuilder component) { @@ -2894,7 +2692,7 @@ default void componentBuilderApply(final @NotNull ComponentBuilder compone default @NotNull Stream examinableProperties() { return Stream.of( ExaminableProperty.of("style", this.style()), - ExaminableProperty.of(ComponentInternals.CHILDREN_PROPERTY, this.children()) + ExaminableProperty.of("children", this.children()) ); } } diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java index d554d3bd7..52a9dca95 100644 --- a/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java @@ -49,7 +49,7 @@ * @since 4.0.0 */ @ApiStatus.NonExtendable -public interface ComponentBuilder, B extends ComponentBuilder> extends AbstractBuilder, Buildable.Builder, ComponentBuilderApplicable, ComponentLike, MutableStyleSetter { +public sealed interface ComponentBuilder> extends AbstractBuilder, ComponentBuilderApplicable, ComponentLike, MutableStyleSetter permits AbstractComponentBuilder, KeybindComponent.Builder, NBTComponentBuilder, ObjectComponent.Builder, ScoreComponent.Builder, SelectorComponent.Builder, TextComponent.Builder, TranslatableComponent.Builder { /** * Appends a component to this component. * @@ -149,8 +149,7 @@ public interface ComponentBuilder, B extends } /** - * Applies an action to this component and all child components if they are - * an instance of {@link BuildableComponent}. + * Applies an action to this component and all child components. * * @param action the action * @return this builder @@ -167,7 +166,7 @@ public interface ComponentBuilder, B extends * @since 4.0.0 */ @Contract("_ -> this") - @NotNull B mapChildren(final @NotNull Function, ? extends BuildableComponent> function); + @NotNull B mapChildren(final @NotNull Function function); /** * Replaces each child and sub-child of this component with the resultant @@ -178,7 +177,7 @@ public interface ComponentBuilder, B extends * @since 4.0.0 */ @Contract("_ -> this") - @NotNull B mapChildrenDeep(final @NotNull Function, ? extends BuildableComponent> function); + @NotNull B mapChildrenDeep(final @NotNull Function function); /** * Get an unmodifiable list containing all children currently in this builder. diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentCompaction.java b/api/src/main/java/net/kyori/adventure/text/ComponentCompaction.java index 06ce93c2e..b81dd8e67 100644 --- a/api/src/main/java/net/kyori/adventure/text/ComponentCompaction.java +++ b/api/src/main/java/net/kyori/adventure/text/ComponentCompaction.java @@ -64,7 +64,7 @@ static Component compact(final @NotNull Component self, final @Nullable Style pa final TextComponent textComponent = (TextComponent) optimized; if (textComponent.content().isEmpty()) { - final Component child = children.get(0); + final Component child = children.getFirst(); // merge the updated/parent style into the child before we return return child.style(child.style().merge(optimized.style(), Style.Merge.Strategy.IF_ABSENT_ON_TARGET)).compact(); @@ -80,9 +80,7 @@ static Component compact(final @NotNull Component self, final @Nullable Style pa // optimize all children final List childrenToAppend = new ArrayList<>(children.size()); - for (int i = 0; i < children.size(); ++i) { - Component child = children.get(i); - + for (Component child : children) { // compact child recursively child = compact(child, childParentStyle); @@ -101,14 +99,14 @@ static Component compact(final @NotNull Component self, final @Nullable Style pa // try to merge children into this parent component if (isText(optimized)) { while (!childrenToAppend.isEmpty()) { - final Component child = childrenToAppend.get(0); + final Component child = childrenToAppend.getFirst(); final Style childStyle = child.style().merge(childParentStyle, Style.Merge.Strategy.IF_ABSENT_ON_TARGET); if (isText(child) && Objects.equals(childStyle, childParentStyle)) { // merge child components into the parent if they are a text component with the same effective style // in context of their parent style optimized = joinText((TextComponent) optimized, (TextComponent) child); - childrenToAppend.remove(0); + childrenToAppend.removeFirst(); // if the merged child had any children, retain them childrenToAppend.addAll(0, child.children()); diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentInternals.java b/api/src/main/java/net/kyori/adventure/text/ComponentInternals.java deleted file mode 100644 index 14be9c1f3..000000000 --- a/api/src/main/java/net/kyori/adventure/text/ComponentInternals.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.text; - -final class ComponentInternals { - static final String CHILDREN_PROPERTY = "children"; - - private ComponentInternals() { - } -} diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentIteratorFlag.java b/api/src/main/java/net/kyori/adventure/text/ComponentIteratorFlag.java index 8a31dfac9..7b6e948c5 100644 --- a/api/src/main/java/net/kyori/adventure/text/ComponentIteratorFlag.java +++ b/api/src/main/java/net/kyori/adventure/text/ComponentIteratorFlag.java @@ -23,7 +23,7 @@ */ package net.kyori.adventure.text; -import org.jetbrains.annotations.ApiStatus; +import net.kyori.adventure.text.event.HoverEvent; /** * Flags to modify the behaviour of a component iterator. @@ -33,16 +33,15 @@ * @see Component#spliterator(ComponentIteratorType, java.util.Set) * @since 4.9.0 */ -@ApiStatus.NonExtendable public enum ComponentIteratorFlag { /** - * Includes the name of entities inside {@link net.kyori.adventure.text.event.HoverEvent.Action#SHOW_ENTITY entity} hover events. + * Includes the name of entities inside {@link HoverEvent.Action#SHOW_ENTITY entity} hover events. * * @since 4.9.0 */ INCLUDE_HOVER_SHOW_ENTITY_NAME, /** - * Includes the components inside {@link net.kyori.adventure.text.event.HoverEvent.Action#SHOW_TEXT text} hover events. + * Includes the components inside {@link HoverEvent.Action#SHOW_TEXT text} hover events. * * @since 4.9.0 */ diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentIteratorType.java b/api/src/main/java/net/kyori/adventure/text/ComponentIteratorType.java index a33795aa8..574048f6b 100644 --- a/api/src/main/java/net/kyori/adventure/text/ComponentIteratorType.java +++ b/api/src/main/java/net/kyori/adventure/text/ComponentIteratorType.java @@ -24,10 +24,7 @@ package net.kyori.adventure.text; import java.util.Deque; -import java.util.List; import java.util.Set; -import net.kyori.adventure.text.event.HoverEvent; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -38,65 +35,19 @@ * @see Component#spliterator(ComponentIteratorType, Set) * @since 4.9.0 */ -@ApiStatus.NonExtendable -@FunctionalInterface -public interface ComponentIteratorType { +public sealed interface ComponentIteratorType permits ComponentIteratorTypeImpl.BreadthFirst, ComponentIteratorTypeImpl.DepthFirst { /** * A depth-first iteration. * * @since 4.9.0 */ - ComponentIteratorType DEPTH_FIRST = (component, deque, flags) -> { - if (flags.contains(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS) && component instanceof TranslatableComponent) { - final TranslatableComponent translatable = (TranslatableComponent) component; - final List args = translatable.arguments(); - - for (int i = args.size() - 1; i >= 0; i--) { - deque.addFirst(args.get(i).asComponent()); - } - } - - final HoverEvent hoverEvent = component.hoverEvent(); - if (hoverEvent != null) { - final HoverEvent.Action action = hoverEvent.action(); - - if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_ENTITY_NAME) && action == HoverEvent.Action.SHOW_ENTITY) { - deque.addFirst(((HoverEvent.ShowEntity) hoverEvent.value()).name()); - } else if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_TEXT_COMPONENT) && action == HoverEvent.Action.SHOW_TEXT) { - deque.addFirst((Component) hoverEvent.value()); - } - } - - final List children = component.children(); - for (int i = children.size() - 1; i >= 0; i--) { - deque.addFirst(children.get(i)); - } - }; + ComponentIteratorType DEPTH_FIRST = ComponentIteratorTypeImpl.DepthFirst.INSTANCE; /** * A breadth-first iteration. * * @since 4.9.0 */ - ComponentIteratorType BREADTH_FIRST = (component, deque, flags) -> { - if (flags.contains(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS) && component instanceof TranslatableComponent) { - for (final TranslationArgument argument : ((TranslatableComponent) component).arguments()) { - deque.add(argument.asComponent()); - } - } - - final HoverEvent hoverEvent = component.hoverEvent(); - if (hoverEvent != null) { - final HoverEvent.Action action = hoverEvent.action(); - - if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_ENTITY_NAME) && action == HoverEvent.Action.SHOW_ENTITY) { - deque.addLast(((HoverEvent.ShowEntity) hoverEvent.value()).name()); - } else if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_TEXT_COMPONENT) && action == HoverEvent.Action.SHOW_TEXT) { - deque.addLast((Component) hoverEvent.value()); - } - } - - deque.addAll(component.children()); - }; + ComponentIteratorType BREADTH_FIRST = ComponentIteratorTypeImpl.BreadthFirst.INSTANCE; /** * Populates a deque with the children of the provided component, based on the iterator type and flags. diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentIteratorTypeImpl.java b/api/src/main/java/net/kyori/adventure/text/ComponentIteratorTypeImpl.java new file mode 100644 index 000000000..a27db1fd1 --- /dev/null +++ b/api/src/main/java/net/kyori/adventure/text/ComponentIteratorTypeImpl.java @@ -0,0 +1,69 @@ +package net.kyori.adventure.text; + +import java.util.Deque; +import java.util.List; +import java.util.Set; +import net.kyori.adventure.text.event.HoverEvent; +import org.jetbrains.annotations.NotNull; + +class ComponentIteratorTypeImpl { + private ComponentIteratorTypeImpl() { + } + + static final class DepthFirst implements ComponentIteratorType { + static final ComponentIteratorType INSTANCE = new DepthFirst(); + + @Override + public void populate(@NotNull Component component, @NotNull Deque deque, @NotNull Set flags) { + if (flags.contains(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS) && component instanceof TranslatableComponent translatable) { + final List args = translatable.arguments(); + + for (int i = args.size() - 1; i >= 0; i--) { + deque.addFirst(args.get(i).asComponent()); + } + } + + final HoverEvent hoverEvent = component.hoverEvent(); + if (hoverEvent != null) { + final HoverEvent.Action action = hoverEvent.action(); + + if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_ENTITY_NAME) && action == HoverEvent.Action.SHOW_ENTITY) { + deque.addFirst(((HoverEvent.ShowEntity) hoverEvent.value()).name()); + } else if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_TEXT_COMPONENT) && action == HoverEvent.Action.SHOW_TEXT) { + deque.addFirst((Component) hoverEvent.value()); + } + } + + final List children = component.children(); + for (int i = children.size() - 1; i >= 0; i--) { + deque.addFirst(children.get(i)); + } + } + } + + static final class BreadthFirst implements ComponentIteratorType { + static final ComponentIteratorType INSTANCE = new BreadthFirst(); + + @Override + public void populate(@NotNull Component component, @NotNull Deque deque, @NotNull Set flags) { + if (flags.contains(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS) && component instanceof TranslatableComponent) { + for (final TranslationArgument argument : ((TranslatableComponent) component).arguments()) { + deque.add(argument.asComponent()); + } + } + + final HoverEvent hoverEvent = component.hoverEvent(); + if (hoverEvent != null) { + final HoverEvent.Action action = hoverEvent.action(); + + if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_ENTITY_NAME) && action == HoverEvent.Action.SHOW_ENTITY) { + deque.addLast(((HoverEvent.ShowEntity) hoverEvent.value()).name()); + } else if (flags.contains(ComponentIteratorFlag.INCLUDE_HOVER_SHOW_TEXT_COMPONENT) && action == HoverEvent.Action.SHOW_TEXT) { + deque.addLast((Component) hoverEvent.value()); + } + } + + deque.addAll(component.children()); + } + } +} diff --git a/api/src/main/java/net/kyori/adventure/text/EntityNBTComponent.java b/api/src/main/java/net/kyori/adventure/text/EntityNBTComponent.java index 38a0838e7..2b522f5a1 100644 --- a/api/src/main/java/net/kyori/adventure/text/EntityNBTComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/EntityNBTComponent.java @@ -43,7 +43,7 @@ * @since 4.0.0 * @sinceMinecraft 1.14 */ -public interface EntityNBTComponent extends NBTComponent, ScopedComponent { +public sealed interface EntityNBTComponent extends NBTComponent, ScopedComponent permits EntityNBTComponentImpl { /** * Gets the entity selector. * @@ -77,7 +77,7 @@ public interface EntityNBTComponent extends NBTComponent { + sealed interface Builder extends NBTComponentBuilder permits EntityNBTComponentImpl.BuilderImpl { /** * Sets the entity selector. * diff --git a/api/src/main/java/net/kyori/adventure/text/EntityNBTComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/EntityNBTComponentImpl.java index e15553ab9..254df406b 100644 --- a/api/src/main/java/net/kyori/adventure/text/EntityNBTComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/EntityNBTComponentImpl.java @@ -32,9 +32,14 @@ import static java.util.Objects.requireNonNull; -final class EntityNBTComponentImpl extends NBTComponentImpl implements EntityNBTComponent { - private final String selector; - +record EntityNBTComponentImpl( + List children, + Style style, + String nbtPath, + boolean interpret, + Component separator, + String selector +) implements EntityNBTComponent { static EntityNBTComponent create(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator, final String selector) { return new EntityNBTComponentImpl( ComponentLike.asComponents(children, IS_NOT_EMPTY), @@ -46,11 +51,6 @@ static EntityNBTComponent create(final @NotNull List ch ); } - EntityNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable Component separator, final String selector) { - super(children, style, nbtPath, interpret, separator); - this.selector = selector; - } - @Override public @NotNull EntityNBTComponent nbtPath(final @NotNull String nbtPath) { if (Objects.equals(this.nbtPath, nbtPath)) return this; @@ -63,21 +63,11 @@ static EntityNBTComponent create(final @NotNull List ch return create(this.children, this.style, this.nbtPath, interpret, this.separator, this.selector); } - @Override - public @Nullable Component separator() { - return this.separator; - } - @Override public @NotNull EntityNBTComponent separator(final @Nullable ComponentLike separator) { return create(this.children, this.style, this.nbtPath, this.interpret, separator, this.selector); } - @Override - public @NotNull String selector() { - return this.selector; - } - @Override public @NotNull EntityNBTComponent selector(final @NotNull String selector) { if (Objects.equals(this.selector, selector)) return this; @@ -95,32 +85,16 @@ static EntityNBTComponent create(final @NotNull List ch } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof EntityNBTComponent)) return false; - if (!super.equals(other)) return false; - final EntityNBTComponentImpl that = (EntityNBTComponentImpl) other; - return Objects.equals(this.selector, that.selector()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.selector.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @Override - public EntityNBTComponent.@NotNull Builder toBuilder() { + public @NotNull Builder toBuilder() { return new BuilderImpl(this); } - static final class BuilderImpl extends AbstractNBTComponentBuilder implements EntityNBTComponent.Builder { + static final class BuilderImpl extends AbstractNBTComponentBuilder implements Builder { private @Nullable String selector; BuilderImpl() { @@ -132,7 +106,7 @@ static final class BuilderImpl extends AbstractNBTComponentBuilder, Examinable { +public sealed interface JoinConfiguration extends Examinable permits JoinConfigurationImpl { /** * Creates a new builder. * @@ -258,7 +256,7 @@ public interface JoinConfiguration extends Buildable, Buildable.Builder { + sealed interface Builder extends AbstractBuilder permits JoinConfigurationImpl.BuilderImpl { /** * Sets the prefix of this join configuration builder. * diff --git a/api/src/main/java/net/kyori/adventure/text/JoinConfigurationImpl.java b/api/src/main/java/net/kyori/adventure/text/JoinConfigurationImpl.java index b1d2e307e..bbf199208 100644 --- a/api/src/main/java/net/kyori/adventure/text/JoinConfigurationImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/JoinConfigurationImpl.java @@ -35,10 +35,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -final class JoinConfigurationImpl implements JoinConfiguration { +record JoinConfigurationImpl(Component prefix, Component suffix, Component separator, Component lastSeparator, Component lastSeparatorIfSerial, Function convertor, Predicate predicate, Style parentStyle) implements JoinConfiguration { static final Function DEFAULT_CONVERTOR = ComponentLike::asComponent; static final Predicate DEFAULT_PREDICATE = componentLike -> true; - static final JoinConfigurationImpl NULL = new JoinConfigurationImpl(); + static final JoinConfigurationImpl NULL = new JoinConfigurationImpl(null, null, null, null, null, DEFAULT_CONVERTOR, DEFAULT_PREDICATE, Style.empty()); static final JoinConfiguration STANDARD_NEW_LINES = JoinConfiguration.separator(Component.newline()); static final JoinConfiguration STANDARD_SPACES = JoinConfiguration.separator(Component.space()); @@ -50,80 +50,8 @@ final class JoinConfigurationImpl implements JoinConfiguration { .suffix(Component.text("]")) .build(); - private final Component prefix; - private final Component suffix; - private final Component separator; - private final Component lastSeparator; - private final Component lastSeparatorIfSerial; - private final Function convertor; - private final Predicate predicate; - private final Style rootStyle; - - private JoinConfigurationImpl() { - this.prefix = null; - this.suffix = null; - this.separator = null; - this.lastSeparator = null; - this.lastSeparatorIfSerial = null; - this.convertor = DEFAULT_CONVERTOR; - this.predicate = DEFAULT_PREDICATE; - this.rootStyle = Style.empty(); - } - private JoinConfigurationImpl(final @NotNull BuilderImpl builder) { - this.prefix = ComponentLike.unbox(builder.prefix); - this.suffix = ComponentLike.unbox(builder.suffix); - this.separator = ComponentLike.unbox(builder.separator); - this.lastSeparator = ComponentLike.unbox(builder.lastSeparator); - this.lastSeparatorIfSerial = ComponentLike.unbox(builder.lastSeparatorIfSerial); - this.convertor = builder.convertor; - this.predicate = builder.predicate; - this.rootStyle = builder.rootStyle; - } - - @Override - public @Nullable Component prefix() { - return this.prefix; - } - - @Override - public @Nullable Component suffix() { - return this.suffix; - } - - @Override - public @Nullable Component separator() { - return this.separator; - } - - @Override - public @Nullable Component lastSeparator() { - return this.lastSeparator; - } - - @Override - public @Nullable Component lastSeparatorIfSerial() { - return this.lastSeparatorIfSerial; - } - - @Override - public @NotNull Function convertor() { - return this.convertor; - } - - @Override - public @NotNull Predicate predicate() { - return this.predicate; - } - - @Override - public @NotNull Style parentStyle() { - return this.rootStyle; - } - - @Override - public JoinConfiguration.@NotNull Builder toBuilder() { - return new BuilderImpl(this); + this(ComponentLike.unbox(builder.prefix), ComponentLike.unbox(builder.suffix), ComponentLike.unbox(builder.separator), ComponentLike.unbox(builder.lastSeparator), ComponentLike.unbox(builder.lastSeparatorIfSerial), builder.convertor, builder.predicate, builder.parentStyle); } @Override @@ -136,12 +64,12 @@ private JoinConfigurationImpl(final @NotNull BuilderImpl builder) { ExaminableProperty.of("lastSeparatorIfSerial", this.lastSeparatorIfSerial), ExaminableProperty.of("convertor", this.convertor), ExaminableProperty.of("predicate", this.predicate), - ExaminableProperty.of("rootStyle", this.rootStyle) + ExaminableProperty.of("parentStyle", this.parentStyle) ); } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @@ -251,7 +179,7 @@ static final class BuilderImpl implements JoinConfiguration.Builder { private ComponentLike lastSeparatorIfSerial; private Function convertor; private Predicate predicate; - private Style rootStyle; + private Style parentStyle; BuilderImpl() { this(JoinConfigurationImpl.NULL); @@ -265,7 +193,7 @@ private BuilderImpl(final @NotNull JoinConfigurationImpl joinConfig) { this.convertor = joinConfig.convertor; this.lastSeparatorIfSerial = joinConfig.lastSeparatorIfSerial; this.predicate = joinConfig.predicate; - this.rootStyle = joinConfig.rootStyle; + this.parentStyle = joinConfig.parentStyle; } @Override @@ -312,7 +240,7 @@ private BuilderImpl(final @NotNull JoinConfigurationImpl joinConfig) { @Override public @NotNull Builder parentStyle(final @NotNull Style parentStyle) { - this.rootStyle = Objects.requireNonNull(parentStyle, "rootStyle"); + this.parentStyle = Objects.requireNonNull(parentStyle, "parentStyle"); return this; } diff --git a/api/src/main/java/net/kyori/adventure/text/KeybindComponent.java b/api/src/main/java/net/kyori/adventure/text/KeybindComponent.java index 46181cc56..347d6931b 100644 --- a/api/src/main/java/net/kyori/adventure/text/KeybindComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/KeybindComponent.java @@ -41,7 +41,7 @@ * @since 4.0.0 * @sinceMinecraft 1.12 */ -public interface KeybindComponent extends BuildableComponent, ScopedComponent { +public sealed interface KeybindComponent extends ScopedComponent permits KeybindComponentImpl { /** * Gets the keybind. * @@ -78,7 +78,7 @@ public interface KeybindComponent extends BuildableComponent { + sealed interface Builder extends ComponentBuilder permits KeybindComponentImpl.BuilderImpl { /** * Sets the keybind. * diff --git a/api/src/main/java/net/kyori/adventure/text/KeybindComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/KeybindComponentImpl.java index 19f1dd860..5a76a5a87 100644 --- a/api/src/main/java/net/kyori/adventure/text/KeybindComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/KeybindComponentImpl.java @@ -32,9 +32,7 @@ import static java.util.Objects.requireNonNull; -final class KeybindComponentImpl extends AbstractComponent implements KeybindComponent { - private final String keybind; - +record KeybindComponentImpl(List children, Style style, String keybind) implements KeybindComponent { static KeybindComponent create(final @NotNull List children, final @NotNull Style style, final @NotNull String keybind) { return new KeybindComponentImpl( ComponentLike.asComponents(children, IS_NOT_EMPTY), @@ -43,16 +41,6 @@ static KeybindComponent create(final @NotNull List chil ); } - KeybindComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String keybind) { - super(children, style); - this.keybind = keybind; - } - - @Override - public @NotNull String keybind() { - return this.keybind; - } - @Override public @NotNull KeybindComponent keybind(final @NotNull String keybind) { if (Objects.equals(this.keybind, keybind)) return this; @@ -70,23 +58,7 @@ static KeybindComponent create(final @NotNull List chil } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof KeybindComponent)) return false; - if (!super.equals(other)) return false; - final KeybindComponent that = (KeybindComponent) other; - return Objects.equals(this.keybind, that.keybind()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.keybind.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @@ -95,7 +67,7 @@ public String toString() { return new BuilderImpl(this); } - static final class BuilderImpl extends AbstractComponentBuilder implements KeybindComponent.Builder { + static final class BuilderImpl extends AbstractComponentBuilder implements Builder { private @Nullable String keybind; BuilderImpl() { diff --git a/api/src/main/java/net/kyori/adventure/text/LegacyFormattingDetected.java b/api/src/main/java/net/kyori/adventure/text/LegacyFormattingDetected.java index 19b64d2c2..c347630f7 100644 --- a/api/src/main/java/net/kyori/adventure/text/LegacyFormattingDetected.java +++ b/api/src/main/java/net/kyori/adventure/text/LegacyFormattingDetected.java @@ -23,9 +23,11 @@ */ package net.kyori.adventure.text; +import java.io.Serial; import net.kyori.adventure.util.Nag; final class LegacyFormattingDetected extends Nag { + @Serial private static final long serialVersionUID = -947793022628807411L; LegacyFormattingDetected(final Component component) { diff --git a/api/src/main/java/net/kyori/adventure/text/LinearComponents.java b/api/src/main/java/net/kyori/adventure/text/LinearComponents.java index c4b2176ee..315c58f07 100644 --- a/api/src/main/java/net/kyori/adventure/text/LinearComponents.java +++ b/api/src/main/java/net/kyori/adventure/text/LinearComponents.java @@ -56,22 +56,21 @@ private LinearComponents() { if (length == 0) return Component.empty(); if (length == 1) { final ComponentBuilderApplicable ap0 = applicables[0]; - if (ap0 instanceof ComponentLike) { - return ((ComponentLike) ap0).asComponent(); + if (ap0 instanceof ComponentLike cl) { + return cl.asComponent(); } throw nothingComponentLike(); } final TextComponentImpl.BuilderImpl builder = new TextComponentImpl.BuilderImpl(); Style.Builder style = null; - for (int i = 0; i < length; i++) { - final ComponentBuilderApplicable applicable = applicables[i]; - if (applicable instanceof StyleBuilderApplicable) { + for (final ComponentBuilderApplicable applicable : applicables) { + if (applicable instanceof StyleBuilderApplicable sba) { if (style == null) { style = Style.style(); } - style.apply((StyleBuilderApplicable) applicable); - } else if (style != null && applicable instanceof ComponentLike) { - builder.applicableApply(((ComponentLike) applicable).asComponent().style(style)); + style.apply(sba); + } else if (style != null && applicable instanceof ComponentLike cl) { + builder.applicableApply(cl.asComponent().style(style)); } else { builder.applicableApply(applicable); } @@ -80,7 +79,7 @@ private LinearComponents() { if (size == 0) { throw nothingComponentLike(); } else if (size == 1 && !builder.hasStyle()) { - return builder.children.get(0); + return builder.children.getFirst(); } else { return builder.build(); } diff --git a/api/src/main/java/net/kyori/adventure/text/NBTComponent.java b/api/src/main/java/net/kyori/adventure/text/NBTComponent.java index 0a62640e2..96051507c 100644 --- a/api/src/main/java/net/kyori/adventure/text/NBTComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/NBTComponent.java @@ -51,7 +51,14 @@ * @since 4.0.0 * @sinceMinecraft 1.14 */ -public interface NBTComponent, B extends NBTComponentBuilder> extends BuildableComponent { +public sealed interface NBTComponent> extends Component permits BlockNBTComponent, EntityNBTComponent, StorageNBTComponent { + /** + * The default value for {@link #interpret()}. + * + * @since 5.0.0 + */ + boolean INTERPRET_DEFAULT = true; + /** * Gets the NBT path. * @@ -113,7 +120,7 @@ public interface NBTComponent, B extends NBTCompone ExaminableProperty.of("interpret", this.interpret()), ExaminableProperty.of("separator", this.separator()) ), - BuildableComponent.super.examinableProperties() + ScopedComponent.super.examinableProperties() ); } } diff --git a/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java index b7bd7f1bc..9d1a9a982 100644 --- a/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java @@ -38,7 +38,7 @@ * @param builder type * @since 4.0.0 */ -public interface NBTComponentBuilder, B extends NBTComponentBuilder> extends ComponentBuilder { +public sealed interface NBTComponentBuilder, B extends NBTComponentBuilder> extends ComponentBuilder permits AbstractNBTComponentBuilder, BlockNBTComponent.Builder, EntityNBTComponent.Builder, StorageNBTComponent.Builder { /** * Sets the NBT path content. * diff --git a/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java deleted file mode 100644 index 00f1750f3..000000000 --- a/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of adventure, licensed under the MIT License. - * - * Copyright (c) 2017-2025 KyoriPowered - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package net.kyori.adventure.text; - -import java.util.List; -import java.util.Objects; -import net.kyori.adventure.text.format.Style; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -abstract class NBTComponentImpl, B extends NBTComponentBuilder> extends AbstractComponent implements NBTComponent { - static final boolean INTERPRET_DEFAULT = false; - final String nbtPath; - final boolean interpret; - final @Nullable Component separator; - - NBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable Component separator) { - super(children, style); - this.nbtPath = nbtPath; - this.interpret = interpret; - this.separator = separator; - } - - @Override - public @NotNull String nbtPath() { - return this.nbtPath; - } - - @Override - public boolean interpret() { - return this.interpret; - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof NBTComponent)) return false; - if (!super.equals(other)) return false; - final NBTComponent that = (NBTComponent) other; - return Objects.equals(this.nbtPath, that.nbtPath()) && this.interpret == that.interpret() && Objects.equals(this.separator, that.separator()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.nbtPath.hashCode(); - result = (31 * result) + Boolean.hashCode(this.interpret); - result = (31 * result) + Objects.hashCode(this.separator); - return result; - } -} diff --git a/api/src/main/java/net/kyori/adventure/text/ObjectComponent.java b/api/src/main/java/net/kyori/adventure/text/ObjectComponent.java index b540b92b1..a6b9e2dc4 100644 --- a/api/src/main/java/net/kyori/adventure/text/ObjectComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/ObjectComponent.java @@ -34,7 +34,7 @@ * @since 4.25.0 * @sinceMinecraft 1.21.9 */ -public interface ObjectComponent extends BuildableComponent, ScopedComponent { +public sealed interface ObjectComponent extends ScopedComponent permits ObjectComponentImpl { /** * Gets the contents of this object component. * @@ -56,7 +56,7 @@ public interface ObjectComponent extends BuildableComponent examinableProperties() { return Stream.concat( Stream.of(ExaminableProperty.of("contents", this.contents())), - BuildableComponent.super.examinableProperties() + ScopedComponent.super.examinableProperties() ); } @@ -65,7 +65,7 @@ public interface ObjectComponent extends BuildableComponent { + sealed interface Builder extends ComponentBuilder permits ObjectComponentImpl.BuilderImpl { /** * Sets the contents of this object component builder. * diff --git a/api/src/main/java/net/kyori/adventure/text/ObjectComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/ObjectComponentImpl.java index 2060be0ee..08858d616 100644 --- a/api/src/main/java/net/kyori/adventure/text/ObjectComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/ObjectComponentImpl.java @@ -24,26 +24,21 @@ package net.kyori.adventure.text; import java.util.List; -import java.util.Objects; import net.kyori.adventure.internal.Internals; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.object.ObjectContents; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import static java.util.Objects.requireNonNull; -final class ObjectComponentImpl extends AbstractComponent implements ObjectComponent { - private final ObjectContents contents; +record ObjectComponentImpl(List children, Style style, ObjectContents contents) implements ObjectComponent { - private ObjectComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull ObjectContents contents) { - super(children, style); - this.contents = contents; - } - - @Override - public @NotNull ObjectContents contents() { - return this.contents; + static @NotNull ObjectComponentImpl create(final @NotNull List children, final @NotNull Style style, final @NotNull ObjectContents objectContents) { + return new ObjectComponentImpl( + ComponentLike.asComponents(children, IS_NOT_EMPTY), + requireNonNull(style, "style"), + requireNonNull(objectContents, "contents") + ); } @Override @@ -52,23 +47,7 @@ private ObjectComponentImpl(final @NotNull List children, final @NotN } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof ObjectComponent)) return false; - if (!super.equals(other)) return false; - final ObjectComponentImpl that = (ObjectComponentImpl) other; - return Objects.equals(this.contents, that.contents()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.contents.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @@ -77,14 +56,6 @@ public String toString() { return new BuilderImpl(this); } - static @NotNull ObjectComponentImpl create(final @NotNull List children, final @NotNull Style style, final @NotNull ObjectContents objectContents) { - return new ObjectComponentImpl( - ComponentLike.asComponents(children, IS_NOT_EMPTY), - requireNonNull(style, "style"), - requireNonNull(objectContents, "contents") - ); - } - @Override public @NotNull ObjectComponent children(final @NotNull List children) { return create(children, this.style, this.contents); @@ -95,7 +66,7 @@ public String toString() { return create(this.children, style, this.contents); } - static final class BuilderImpl extends AbstractComponentBuilder implements ObjectComponent.Builder { + static final class BuilderImpl extends AbstractComponentBuilder implements Builder { private ObjectContents objectContents; BuilderImpl() { diff --git a/api/src/main/java/net/kyori/adventure/text/ScopedComponent.java b/api/src/main/java/net/kyori/adventure/text/ScopedComponent.java index ba1573947..cbc166698 100644 --- a/api/src/main/java/net/kyori/adventure/text/ScopedComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/ScopedComponent.java @@ -44,7 +44,7 @@ * @param the component type * @since 4.0.0 */ -public interface ScopedComponent extends Component { +public sealed interface ScopedComponent extends Component permits BlockNBTComponent, EntityNBTComponent, KeybindComponent, ObjectComponent, ScoreComponent, SelectorComponent, StorageNBTComponent, TextComponent, TranslatableComponent { @Override @SuppressWarnings("unchecked") default @NotNull C asComponent() { @@ -203,7 +203,7 @@ public interface ScopedComponent extends Component { @Override @SuppressWarnings("unchecked") - default @NotNull C clickEvent(final @Nullable ClickEvent event) { + default @NotNull C clickEvent(final @Nullable ClickEvent event) { return (C) Component.super.clickEvent(event); } diff --git a/api/src/main/java/net/kyori/adventure/text/ScoreComponent.java b/api/src/main/java/net/kyori/adventure/text/ScoreComponent.java index 4bcf6f971..d72425dd4 100644 --- a/api/src/main/java/net/kyori/adventure/text/ScoreComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/ScoreComponent.java @@ -27,7 +27,6 @@ import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * A component that can display a player's score from a scoreboard objective, @@ -51,7 +50,7 @@ * * @since 4.0.0 */ -public interface ScoreComponent extends BuildableComponent, ScopedComponent { +public sealed interface ScoreComponent extends ScopedComponent permits ScoreComponentImpl { /** * Gets the score name. * @@ -88,37 +87,14 @@ public interface ScoreComponent extends BuildableComponent examinableProperties() { return Stream.concat( Stream.of( ExaminableProperty.of("name", this.name()), - ExaminableProperty.of("objective", this.objective()), - ExaminableProperty.of("value", this.value()) + ExaminableProperty.of("objective", this.objective()) ), - BuildableComponent.super.examinableProperties() + ScopedComponent.super.examinableProperties() ); } @@ -127,7 +103,7 @@ public interface ScoreComponent extends BuildableComponent { + sealed interface Builder extends ComponentBuilder permits ScoreComponentImpl.BuilderImpl { /** * Sets the score name. * @@ -147,17 +123,5 @@ interface Builder extends ComponentBuilder { */ @Contract("_ -> this") @NotNull Builder objective(final @NotNull String objective); - - /** - * Sets the value. - * - * @param value the value - * @return this builder - * @since 4.0.0 - * @deprecated since 4.7.0, not for removal, with no replacement. This field is no longer supported in 1.16.5. - */ - @Deprecated - @Contract("_ -> this") - @NotNull Builder value(final @Nullable String value); } } diff --git a/api/src/main/java/net/kyori/adventure/text/ScoreComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/ScoreComponentImpl.java index 1b6ab918c..7b7a23d51 100644 --- a/api/src/main/java/net/kyori/adventure/text/ScoreComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/ScoreComponentImpl.java @@ -32,97 +32,40 @@ import static java.util.Objects.requireNonNull; -final class ScoreComponentImpl extends AbstractComponent implements ScoreComponent { - private final String name; - private final String objective; - @Deprecated - private final @Nullable String value; - - static ScoreComponent create(final @NotNull List children, final @NotNull Style style, final @NotNull String name, final @NotNull String objective, final @Nullable String value) { +record ScoreComponentImpl(List children, Style style, String name, String objective) implements ScoreComponent { + static ScoreComponent create(final @NotNull List children, final @NotNull Style style, final @NotNull String name, final @NotNull String objective) { return new ScoreComponentImpl( ComponentLike.asComponents(children, IS_NOT_EMPTY), requireNonNull(style, "style"), requireNonNull(name, "name"), - requireNonNull(objective, "objective"), - value + requireNonNull(objective, "objective") ); } - ScoreComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String name, final @NotNull String objective, final @Nullable String value) { - super(children, style); - this.name = name; - this.objective = objective; - this.value = value; - } - - @Override - public @NotNull String name() { - return this.name; - } - @Override public @NotNull ScoreComponent name(final @NotNull String name) { if (Objects.equals(this.name, name)) return this; - return create(this.children, this.style, name, this.objective, this.value); - } - - @Override - public @NotNull String objective() { - return this.objective; + return create(this.children, this.style, name, this.objective); } @Override public @NotNull ScoreComponent objective(final @NotNull String objective) { if (Objects.equals(this.objective, objective)) return this; - return create(this.children, this.style, this.name, objective, this.value); - } - - @Override - @Deprecated - public @Nullable String value() { - return this.value; - } - - @Override - @Deprecated - public @NotNull ScoreComponent value(final @Nullable String value) { - if (Objects.equals(this.value, value)) return this; - return create(this.children, this.style, this.name, this.objective, value); + return create(this.children, this.style, this.name, objective); } @Override public @NotNull ScoreComponent children(final @NotNull List children) { - return create(children, this.style, this.name, this.objective, this.value); + return create(children, this.style, this.name, this.objective); } @Override public @NotNull ScoreComponent style(final @NotNull Style style) { - return create(this.children, style, this.name, this.objective, this.value); - } - - @Override - @SuppressWarnings("deprecation") - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof ScoreComponent)) return false; - if (!super.equals(other)) return false; - final ScoreComponent that = (ScoreComponent) other; - return Objects.equals(this.name, that.name()) - && Objects.equals(this.objective, that.objective()) - && Objects.equals(this.value, that.value()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.name.hashCode(); - result = (31 * result) + this.objective.hashCode(); - result = (31 * result) + Objects.hashCode(this.value); - return result; + return create(this.children, style, this.name, this.objective); } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @@ -131,20 +74,17 @@ public String toString() { return new BuilderImpl(this); } - static final class BuilderImpl extends AbstractComponentBuilder implements ScoreComponent.Builder { + static final class BuilderImpl extends AbstractComponentBuilder implements Builder { private @Nullable String name; private @Nullable String objective; - private @Nullable String value; BuilderImpl() { } - @SuppressWarnings("deprecation") BuilderImpl(final @NotNull ScoreComponent component) { super(component); this.name = component.name(); this.objective = component.objective(); - this.value = component.value(); } @Override @@ -159,18 +99,11 @@ static final class BuilderImpl extends AbstractComponentBuilder, ScopedComponent { +public sealed interface SelectorComponent extends ScopedComponent permits SelectorComponentImpl { /** * Gets the selector pattern. * @@ -87,7 +87,7 @@ public interface SelectorComponent extends BuildableComponent { + sealed interface Builder extends ComponentBuilder permits SelectorComponentImpl.BuilderImpl { /** * Sets the selector pattern. * diff --git a/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java index 666a0574e..15f68200f 100644 --- a/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java @@ -32,10 +32,7 @@ import static java.util.Objects.requireNonNull; -final class SelectorComponentImpl extends AbstractComponent implements SelectorComponent { - private final String pattern; - private final @Nullable Component separator; - +record SelectorComponentImpl(List children, Style style, String pattern, @Nullable Component separator) implements SelectorComponent { static SelectorComponent create(final @NotNull List children, final @NotNull Style style, final @NotNull String pattern, final @Nullable ComponentLike separator) { return new SelectorComponentImpl( ComponentLike.asComponents(children, IS_NOT_EMPTY), @@ -45,28 +42,12 @@ static SelectorComponent create(final @NotNull List chi ); } - SelectorComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String pattern, final @Nullable Component separator) { - super(children, style); - this.pattern = pattern; - this.separator = separator; - } - - @Override - public @NotNull String pattern() { - return this.pattern; - } - @Override public @NotNull SelectorComponent pattern(final @NotNull String pattern) { if (Objects.equals(this.pattern, pattern)) return this; return create(this.children, this.style, pattern, this.separator); } - @Override - public @Nullable Component separator() { - return this.separator; - } - @Override public @NotNull SelectorComponent separator(final @Nullable ComponentLike separator) { return create(this.children, this.style, this.pattern, separator); @@ -83,24 +64,7 @@ static SelectorComponent create(final @NotNull List chi } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof SelectorComponent)) return false; - if (!super.equals(other)) return false; - final SelectorComponent that = (SelectorComponent) other; - return Objects.equals(this.pattern, that.pattern()) && Objects.equals(this.separator, that.separator()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.pattern.hashCode(); - result = (31 * result) + Objects.hashCode(this.separator); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @@ -109,7 +73,7 @@ public String toString() { return new BuilderImpl(this); } - static final class BuilderImpl extends AbstractComponentBuilder implements SelectorComponent.Builder { + static final class BuilderImpl extends AbstractComponentBuilder implements Builder { private @Nullable String pattern; private @Nullable Component separator; diff --git a/api/src/main/java/net/kyori/adventure/text/StorageNBTComponent.java b/api/src/main/java/net/kyori/adventure/text/StorageNBTComponent.java index 95384d101..0d8f41faa 100644 --- a/api/src/main/java/net/kyori/adventure/text/StorageNBTComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/StorageNBTComponent.java @@ -44,7 +44,7 @@ * @since 4.0.0 * @sinceMinecraft 1.15 */ -public interface StorageNBTComponent extends NBTComponent, ScopedComponent { +public interface StorageNBTComponent extends NBTComponent, ScopedComponent { /** * Gets the NBT storage's ID. * @@ -78,7 +78,7 @@ public interface StorageNBTComponent extends NBTComponent { + sealed interface Builder extends NBTComponentBuilder permits StorageNBTComponentImpl.BuilderImpl { /** * Sets the NBT storage. * diff --git a/api/src/main/java/net/kyori/adventure/text/StorageNBTComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/StorageNBTComponentImpl.java index ce3234722..62d0bb06b 100644 --- a/api/src/main/java/net/kyori/adventure/text/StorageNBTComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/StorageNBTComponentImpl.java @@ -33,9 +33,14 @@ import static java.util.Objects.requireNonNull; -final class StorageNBTComponentImpl extends NBTComponentImpl implements StorageNBTComponent { - private final Key storage; - +record StorageNBTComponentImpl( + List children, + Style style, + String nbtPath, + boolean interpret, + @Nullable Component separator, + Key storage +) implements StorageNBTComponent { static @NotNull StorageNBTComponent create(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator, final @NotNull Key storage) { return new StorageNBTComponentImpl( ComponentLike.asComponents(children, IS_NOT_EMPTY), @@ -47,11 +52,6 @@ final class StorageNBTComponentImpl extends NBTComponentImpl children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable Component separator, final Key storage) { - super(children, style, nbtPath, interpret, separator); - this.storage = storage; - } - @Override public @NotNull StorageNBTComponent nbtPath(final @NotNull String nbtPath) { if (Objects.equals(this.nbtPath, nbtPath)) return this; @@ -64,21 +64,11 @@ final class StorageNBTComponentImpl extends NBTComponentImpl implements StorageNBTComponent.Builder { + static final class BuilderImpl extends AbstractNBTComponentBuilder implements Builder { private @Nullable Key storage; BuilderImpl() { @@ -133,7 +107,7 @@ static class BuilderImpl extends AbstractNBTComponentBuilder, ScopedComponent { - /** - * Creates a component with {@code components} as the children. - * - * @param components the children - * @return a text component - * @since 4.0.0 - * @deprecated for removal since 4.9.0, use {@link Component#textOfChildren(ComponentLike...)} instead - */ - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - @Deprecated - static @NotNull TextComponent ofChildren(final @NotNull ComponentLike@NotNull... components) { - return Component.textOfChildren(components); - } - +public sealed interface TextComponent extends ScopedComponent permits TextComponentImpl, VirtualComponent { /** * Gets the plain text content. * @@ -79,7 +65,7 @@ public interface TextComponent extends BuildableComponent { + sealed interface Builder extends ComponentBuilder permits TextComponentImpl.BuilderImpl { /** * Gets the plain text content. * diff --git a/api/src/main/java/net/kyori/adventure/text/TextComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/TextComponentImpl.java index c20b8afd6..38438a09d 100644 --- a/api/src/main/java/net/kyori/adventure/text/TextComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/TextComponentImpl.java @@ -32,11 +32,12 @@ import net.kyori.adventure.util.Nag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.VisibleForTesting; import static java.util.Objects.requireNonNull; -class TextComponentImpl extends AbstractComponent implements TextComponent { +sealed class TextComponentImpl implements TextComponent permits VirtualComponentImpl { private static final boolean WARN_WHEN_LEGACY_FORMATTING_DETECTED = Boolean.TRUE.equals(AdventureProperties.TEXT_WARN_WHEN_LEGACY_FORMATTING_DETECTED.value()); @VisibleForTesting static final char SECTION_CHAR = '§'; @@ -65,10 +66,13 @@ TextComponent create0(final @NotNull List children, fin } private final String content; + private final List children; + private final Style style; TextComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String content) { - super(children, style); this.content = content; + this.children = children; + this.style = style; if (WARN_WHEN_LEGACY_FORMATTING_DETECTED) { final LegacyFormattingDetected nag = this.warnWhenLegacyFormattingDetected(); @@ -86,6 +90,16 @@ TextComponent create0(final @NotNull List children, fin return null; } + @Override + public @Unmodifiable @NotNull List children() { + return this.children; + } + + @Override + public @NotNull Style style() { + return this.style; + } + @Override public @NotNull String content() { return this.content; @@ -110,9 +124,8 @@ TextComponent create0(final @NotNull List children, fin @Override public boolean equals(final @Nullable Object other) { if (this == other) return true; - if (!(other instanceof TextComponentImpl)) return false; + if (!(other instanceof final TextComponentImpl that)) return false; if (!super.equals(other)) return false; - final TextComponentImpl that = (TextComponentImpl) other; return Objects.equals(this.content, that.content); } @@ -133,7 +146,7 @@ public String toString() { return new BuilderImpl(this); } - static class BuilderImpl extends AbstractComponentBuilder implements TextComponent.Builder { + static sealed class BuilderImpl extends AbstractComponentBuilder implements TextComponent.Builder permits VirtualComponentImpl.BuilderImpl { /* * We default to an empty string to avoid needing to manually set the * content of a newly-created builder when we only want to append other diff --git a/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java b/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java index 26f5de4f7..82c69f60f 100644 --- a/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java +++ b/api/src/main/java/net/kyori/adventure/text/TextReplacementConfig.java @@ -46,7 +46,7 @@ * * @since 4.2.0 */ -public interface TextReplacementConfig extends Buildable, Examinable { +public sealed interface TextReplacementConfig extends Examinable permits TextReplacementConfigImpl { /** * Create a new builder. * @@ -70,7 +70,7 @@ public interface TextReplacementConfig extends Buildable, Buildable.Builder { + sealed interface Builder extends AbstractBuilder permits TextReplacementConfigImpl.Builder { /* * ------------------- * ---- Patterns ----- diff --git a/api/src/main/java/net/kyori/adventure/text/TextReplacementConfigImpl.java b/api/src/main/java/net/kyori/adventure/text/TextReplacementConfigImpl.java index fd937f28e..50d6865f8 100644 --- a/api/src/main/java/net/kyori/adventure/text/TextReplacementConfigImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/TextReplacementConfigImpl.java @@ -34,18 +34,12 @@ import static java.util.Objects.requireNonNull; -final class TextReplacementConfigImpl implements TextReplacementConfig { - private final Pattern matchPattern; - private final BiFunction replacement; - private final Condition continuer; - private final boolean replaceInsideHoverEvents; - - TextReplacementConfigImpl(final Builder builder) { - this.matchPattern = builder.matchPattern; - this.replacement = builder.replacement; - this.continuer = builder.continuer; - this.replaceInsideHoverEvents = builder.replaceInsideHoverEvents; - } +record TextReplacementConfigImpl( + Pattern matchPattern, + BiFunction replacement, + Condition continuer, + boolean replaceInsideHoverEvents +) implements TextReplacementConfig { @Override public @NotNull Pattern matchPattern() { @@ -56,11 +50,6 @@ TextReplacementRenderer.State createState() { return new TextReplacementRenderer.State(this.matchPattern, this.replacement, this.continuer, this.replaceInsideHoverEvents); } - @Override - public TextReplacementConfig.@NotNull Builder toBuilder() { - return new Builder(this); - } - @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -71,25 +60,19 @@ TextReplacementRenderer.State createState() { } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } static final class Builder implements TextReplacementConfig.Builder { @Nullable Pattern matchPattern; @Nullable BiFunction replacement; - TextReplacementConfig.Condition continuer = (matchResult, index, replacement) -> PatternReplacementResult.REPLACE; + Condition continuer = (matchResult, index, replacement) -> PatternReplacementResult.REPLACE; boolean replaceInsideHoverEvents = true; Builder() { } - Builder(final TextReplacementConfigImpl instance) { - this.matchPattern = instance.matchPattern; - this.replacement = instance.replacement; - this.continuer = instance.continuer; - } - @Override public @NotNull Builder match(final @NotNull Pattern pattern) { this.matchPattern = requireNonNull(pattern, "pattern"); @@ -97,7 +80,7 @@ static final class Builder implements TextReplacementConfig.Builder { } @Override - public @NotNull Builder condition(final TextReplacementConfig.@NotNull Condition condition) { + public @NotNull Builder condition(final @NotNull Condition condition) { this.continuer = requireNonNull(condition, "continuation"); return this; } @@ -118,7 +101,7 @@ static final class Builder implements TextReplacementConfig.Builder { public @NotNull TextReplacementConfig build() { if (this.matchPattern == null) throw new IllegalStateException("A pattern must be provided to match against"); if (this.replacement == null) throw new IllegalStateException("A replacement action must be provided"); - return new TextReplacementConfigImpl(this); + return new TextReplacementConfigImpl(this.matchPattern, this.replacement, this.continuer, this.replaceInsideHoverEvents); } } } diff --git a/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java b/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java index 0e22a5d3a..919875d3a 100644 --- a/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java @@ -30,6 +30,7 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.translation.GlobalTranslator; import net.kyori.adventure.translation.Translatable; +import net.kyori.adventure.translation.TranslationStore; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -50,17 +51,17 @@ *

Displaying this component through an {@link Audience} will run it through the {@link GlobalTranslator} by default, * rendering the key as translated text if a translation with a key matching this components key is found in the viewers locale, * optionally switching arguments with any placeholders in the discovered translation. If no translation is registered for the viewers locale - * adventure will first try to find similar locales that has a valid translation, and then find a translation in the default language({@link TranslationRegistry#defaultLocale(Locale) relevant method}).

+ * adventure will first try to find similar locales that has a valid translation, and then find a translation in the default language({@link TranslationStore#defaultLocale(Locale) relevant method}).

* *

In addition to the initial attempts, if no translation is found in the serverside registry, * the translation key and arguments will be passed through to the client which will perform translation using any * keys defined in an active resource pack. (Hint: vanilla Minecraft is also considered a resource pack)

* * @see GlobalTranslator - * @see TranslationRegistry + * @see TranslationStore * @since 4.0.0 */ -public interface TranslatableComponent extends BuildableComponent, ScopedComponent { +public sealed interface TranslatableComponent extends ScopedComponent permits TranslatableComponentImpl { /** * Gets the translation key. * @@ -91,49 +92,6 @@ public interface TranslatableComponent extends BuildableComponent args(); - - /** - * Sets the translation arguments for this component. - * - *

Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.

- * - * @param args the translation arguments - * @return a translatable component - * @see TranslationArgument - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead - */ - @Deprecated - @Contract(pure = true) - default @NotNull TranslatableComponent args(final @NotNull ComponentLike@NotNull... args) { - return this.arguments(args); - } - - /** - * Sets the translation arguments for this component. - * - *

Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.

- * - * @param args the translation arguments - * @return a translatable component - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(List)} instead - */ - @Deprecated - @Contract(pure = true) - default @NotNull TranslatableComponent args(final @NotNull List args) { - return this.arguments(args); - } - /** * Gets the unmodifiable list of translation arguments. * @@ -199,7 +157,7 @@ public interface TranslatableComponent extends BuildableComponent { + sealed interface Builder extends ComponentBuilder permits TranslatableComponentImpl.BuilderImpl { /** * Sets the translation key. * @@ -231,81 +189,6 @@ interface Builder extends ComponentBuilder { @Contract("_ -> this") @NotNull Builder key(final @NotNull String key); - /** - * Sets the translation args. - * - * @param arg the translation arg - * @return this builder - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead - */ - @Deprecated - @Contract("_ -> this") - default @NotNull Builder args(final @NotNull ComponentBuilder arg) { - return this.arguments(arg); - } - - /** - * Sets the translation args. - * - * @param args the translation args - * @return this builder - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead - */ - @Deprecated - @Contract("_ -> this") - @SuppressWarnings("checkstyle:GenericWhitespace") - default @NotNull Builder args(final @NotNull ComponentBuilder@NotNull... args) { - return this.arguments(args); - } - - /** - * Sets the translation args. - * - * @param arg the translation arg - * @return this builder - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead - */ - @Deprecated - @Contract("_ -> this") - default @NotNull Builder args(final @NotNull Component arg) { - return this.arguments(arg); - } - - /** - * Sets the translation args. - * - *

Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.

- * - * @param args the translation args - * @return this builder - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead - */ - @Deprecated - @Contract("_ -> this") - default @NotNull Builder args(final @NotNull ComponentLike@NotNull... args) { - return this.arguments(args); - } - - /** - * Sets the translation args. - * - *

Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.

- * - * @param args the translation args - * @return this builder - * @since 4.0.0 - * @deprecated for removal since 4.15.0, use {@link #arguments(List)} instead - */ - @Deprecated - @Contract("_ -> this") - default @NotNull Builder args(final @NotNull List args) { - return this.arguments(args); - } - /** * Sets the translation args. * diff --git a/api/src/main/java/net/kyori/adventure/text/TranslatableComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/TranslatableComponentImpl.java index a4bda0c90..42871e257 100644 --- a/api/src/main/java/net/kyori/adventure/text/TranslatableComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/TranslatableComponentImpl.java @@ -35,8 +35,8 @@ import static java.util.Objects.requireNonNull; -final class TranslatableComponentImpl extends AbstractComponent implements TranslatableComponent { - static TranslatableComponent create(final @NotNull List children, final @NotNull Style style, final @NotNull String key, final @Nullable String fallback, final @NotNull ComponentLike@NotNull[] args) { +record TranslatableComponentImpl(List children, Style style, String key, @Nullable String fallback, List args) implements TranslatableComponent { + static TranslatableComponent create(final @NotNull List children, final @NotNull Style style, final @NotNull String key, final @Nullable String fallback, final @NotNull ComponentLike @NotNull [] args) { requireNonNull(args, "args"); return create(children, style, key, fallback, Arrays.asList(args)); } @@ -51,17 +51,6 @@ static TranslatableComponent create(final @NotNull List ); } - private final String key; - private final @Nullable String fallback; - private final List args; - - TranslatableComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String key, final @Nullable String fallback, final @NotNull List args) { - super(children, style); - this.key = key; - this.fallback = fallback; - this.args = args; - } - @Override public @NotNull String key() { return this.key; @@ -73,19 +62,13 @@ static TranslatableComponent create(final @NotNull List return create(this.children, this.style, key, this.fallback, this.args); } - @Override - @Deprecated - public @NotNull List args() { - return ComponentLike.asComponents(this.args); // eww - } - @Override public @NotNull List arguments() { return this.args; } @Override - public @NotNull TranslatableComponent arguments(final @NotNull ComponentLike@NotNull... args) { + public @NotNull TranslatableComponent arguments(final @NotNull ComponentLike @NotNull ... args) { return create(this.children, this.style, this.key, this.fallback, args); } @@ -94,11 +77,6 @@ static TranslatableComponent create(final @NotNull List return create(this.children, this.style, this.key, this.fallback, args); } - @Override - public @Nullable String fallback() { - return this.fallback; - } - @Override public @NotNull TranslatableComponent fallback(final @Nullable String fallback) { return create(this.children, this.style, this.key, fallback, this.args); @@ -115,25 +93,7 @@ static TranslatableComponent create(final @NotNull List } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (!(other instanceof TranslatableComponent)) return false; - if (!super.equals(other)) return false; - final TranslatableComponent that = (TranslatableComponent) other; - return Objects.equals(this.key, that.key()) && Objects.equals(this.fallback, that.fallback()) && Objects.equals(this.args, that.arguments()); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = (31 * result) + this.key.hashCode(); - result = (31 * result) + Objects.hashCode(this.fallback); - result = (31 * result) + this.args.hashCode(); - return result; - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } @@ -142,7 +102,7 @@ public String toString() { return new BuilderImpl(this); } - static final class BuilderImpl extends AbstractComponentBuilder implements TranslatableComponent.Builder { + static final class BuilderImpl extends AbstractComponentBuilder implements Builder { private @Nullable String key; private @Nullable String fallback; private List args = Collections.emptyList(); @@ -164,7 +124,7 @@ static final class BuilderImpl extends AbstractComponentBuilder asArguments(final @NotNull List ret = new ArrayList<>(likes.size()); for (int i = 0; i < likes.size(); i++) { final ComponentLike like = likes.get(i); - if (like == null) { - throw new NullPointerException("likes[" + i + "]"); - } - if (like instanceof TranslationArgument) { - ret.add((TranslationArgument) like); - } else if (like instanceof TranslationArgumentLike) { - ret.add(requireNonNull(((TranslationArgumentLike) like).asTranslationArgument(), "likes[" + i + "].asTranslationArgument()")); - } else { - ret.add(TranslationArgument.component(like)); + switch (like) { + case null -> throw new NullPointerException("likes[" + i + "]"); + case TranslationArgument translationArgument -> ret.add(translationArgument); + case TranslationArgumentLike translationArgumentLike -> ret.add(requireNonNull(translationArgumentLike.asTranslationArgument(), "likes[" + i + "].asTranslationArgument()")); + default -> ret.add(TranslationArgument.component(like)); } } diff --git a/api/src/main/java/net/kyori/adventure/text/TranslationArgument.java b/api/src/main/java/net/kyori/adventure/text/TranslationArgument.java index 6c7f9b896..5bfcc6f69 100644 --- a/api/src/main/java/net/kyori/adventure/text/TranslationArgument.java +++ b/api/src/main/java/net/kyori/adventure/text/TranslationArgument.java @@ -24,7 +24,6 @@ package net.kyori.adventure.text; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import static java.util.Objects.requireNonNull; @@ -34,8 +33,7 @@ * * @since 4.15.0 */ -@ApiStatus.NonExtendable -public interface TranslationArgument extends TranslationArgumentLike, Examinable { +public sealed interface TranslationArgument extends TranslationArgumentLike, Examinable permits TranslationArgumentImpl { /** * Create a boolean argument. * diff --git a/api/src/main/java/net/kyori/adventure/text/TranslationArgumentImpl.java b/api/src/main/java/net/kyori/adventure/text/TranslationArgumentImpl.java index a139d567e..36f487884 100644 --- a/api/src/main/java/net/kyori/adventure/text/TranslationArgumentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/TranslationArgumentImpl.java @@ -23,28 +23,15 @@ */ package net.kyori.adventure.text; -import java.util.Objects; import java.util.stream.Stream; import net.kyori.adventure.internal.Internals; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -final class TranslationArgumentImpl implements TranslationArgument { +record TranslationArgumentImpl(Object value) implements TranslationArgument { private static final Component TRUE = Component.text("true"); private static final Component FALSE = Component.text("false"); - private final Object value; - - TranslationArgumentImpl(final Object value) { - this.value = value; - } - - @Override - public @NotNull Object value() { - return this.value; - } - @Override public @NotNull Component asComponent() { if (this.value instanceof Component) { @@ -57,20 +44,7 @@ final class TranslationArgumentImpl implements TranslationArgument { } @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final TranslationArgumentImpl that = (TranslationArgumentImpl) other; - return Objects.equals(this.value, that.value); - } - - @Override - public int hashCode() { - return Objects.hash(this.value); - } - - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } diff --git a/api/src/main/java/net/kyori/adventure/text/VirtualComponent.java b/api/src/main/java/net/kyori/adventure/text/VirtualComponent.java index a2f24b66d..e19475fbf 100644 --- a/api/src/main/java/net/kyori/adventure/text/VirtualComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/VirtualComponent.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.text; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -34,8 +33,7 @@ * @see Component#virtual(Class, VirtualComponentRenderer) * @since 4.18.0 */ -@ApiStatus.NonExtendable -public interface VirtualComponent extends TextComponent { +public sealed interface VirtualComponent extends TextComponent permits VirtualComponentImpl { /** * Gets the renderer context type. * diff --git a/api/src/main/java/net/kyori/adventure/text/VirtualComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/VirtualComponentImpl.java index 7ca84c3e4..f8331e145 100644 --- a/api/src/main/java/net/kyori/adventure/text/VirtualComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/VirtualComponentImpl.java @@ -78,9 +78,8 @@ VirtualComponent create0(final @NotNull List children, @Override public boolean equals(final @Nullable Object other) { if (this == other) return true; - if (!(other instanceof VirtualComponentImpl)) return false; + if (!(other instanceof final VirtualComponentImpl that)) return false; if (!super.equals(other)) return false; - final VirtualComponentImpl that = (VirtualComponentImpl) other; return Objects.equals(this.contextType, that.contextType) && Objects.equals(this.renderer, that.renderer); } diff --git a/api/src/main/java/net/kyori/adventure/text/event/ClickCallback.java b/api/src/main/java/net/kyori/adventure/text/event/ClickCallback.java index 202155e93..c6dd5efd8 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/ClickCallback.java +++ b/api/src/main/java/net/kyori/adventure/text/event/ClickCallback.java @@ -182,8 +182,7 @@ public interface ClickCallback { * * @since 4.13.0 */ - @ApiStatus.NonExtendable - interface Options extends Examinable { + sealed interface Options extends Examinable permits ClickCallbackOptionsImpl { /** * Create a new builder. * @@ -230,8 +229,7 @@ interface Options extends Examinable { * * @since 4.13.0 */ - @ApiStatus.NonExtendable - interface Builder extends AbstractBuilder { + sealed interface Builder extends AbstractBuilder permits ClickCallbackOptionsImpl.BuilderImpl { /** * Set the number of uses allowed for this callback. * @@ -268,6 +266,6 @@ interface Provider { * @return a created click event that will execute the provided callback with options * @since 4.13.0 */ - @NotNull ClickEvent create(final @NotNull ClickCallback callback, final @NotNull Options options); + @NotNull ClickEvent create(final @NotNull ClickCallback callback, final @NotNull Options options); } } diff --git a/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackInternals.java b/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackInternals.java index 498d69e0a..8a6194e1e 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackInternals.java +++ b/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackInternals.java @@ -40,7 +40,7 @@ private ClickCallbackInternals() { static final class Fallback implements ClickCallback.Provider { @Override - public @NotNull ClickEvent create(final @NotNull ClickCallback callback, final ClickCallback.@NotNull Options options) { + public @NotNull ClickEvent create(final @NotNull ClickCallback callback, final ClickCallback.@NotNull Options options) { return ClickEvent.suggestCommand("Callbacks are not supported on this platform!"); } } diff --git a/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackOptionsImpl.java b/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackOptionsImpl.java index 839ecd2b3..b80266e30 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackOptionsImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/event/ClickCallbackOptionsImpl.java @@ -32,26 +32,8 @@ import static java.util.Objects.requireNonNull; -final class ClickCallbackOptionsImpl implements ClickCallback.Options { - static final ClickCallback.Options DEFAULT = new ClickCallbackOptionsImpl.BuilderImpl().build(); - - private final int uses; - private final Duration lifetime; - - ClickCallbackOptionsImpl(final int uses, final Duration lifetime) { - this.uses = uses; - this.lifetime = lifetime; - } - - @Override - public int uses() { - return this.uses; - } - - @Override - public @NotNull Duration lifetime() { - return this.lifetime; - } +record ClickCallbackOptionsImpl(int uses, Duration lifetime) implements ClickCallback.Options { + static final ClickCallback.Options DEFAULT = new BuilderImpl().build(); @Override public @NotNull Stream examinableProperties() { @@ -62,7 +44,7 @@ public int uses() { } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } diff --git a/api/src/main/java/net/kyori/adventure/text/event/ClickEvent.java b/api/src/main/java/net/kyori/adventure/text/event/ClickEvent.java index 805ab1fdb..cc4d3b048 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/ClickEvent.java +++ b/api/src/main/java/net/kyori/adventure/text/event/ClickEvent.java @@ -24,23 +24,17 @@ package net.kyori.adventure.text.event; import java.net.URL; -import java.util.Objects; import java.util.function.Consumer; -import java.util.stream.Stream; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.builder.AbstractBuilder; import net.kyori.adventure.dialog.DialogLike; -import net.kyori.adventure.internal.Internals; import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Keyed; import net.kyori.adventure.nbt.api.BinaryTagHolder; -import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.StyleBuilderApplicable; import net.kyori.adventure.util.Index; import net.kyori.examination.Examinable; -import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import static java.util.Objects.requireNonNull; @@ -49,9 +43,10 @@ * *

A click event processes an {@link Action} when clicked on.

* + * @param the payload type * @since 4.0.0 */ -public final class ClickEvent implements Examinable, StyleBuilderApplicable { +public sealed interface ClickEvent extends Examinable, StyleBuilderApplicable permits ClickEventImpl { /** * Creates a click event that opens a url. * @@ -61,8 +56,8 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a click event * @since 4.0.0 */ - public static @NotNull ClickEvent openUrl(final @NotNull String url) { - return new ClickEvent(Action.OPEN_URL, Payload.string(url)); + static @NotNull ClickEvent openUrl(@NotNull String url) { + return ClickEventImpl.create(Action.OPEN_URL, Payload.string(url)); } /** @@ -72,7 +67,7 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a click event * @since 4.0.0 */ - public static @NotNull ClickEvent openUrl(final @NotNull URL url) { + static @NotNull ClickEvent openUrl(@NotNull URL url) { return openUrl(url.toExternalForm()); } @@ -85,8 +80,8 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a click event * @since 4.0.0 */ - public static @NotNull ClickEvent openFile(final @NotNull String file) { - return new ClickEvent(Action.OPEN_FILE, Payload.string(file)); + static @NotNull ClickEvent openFile(@NotNull String file) { + return ClickEventImpl.create(Action.OPEN_FILE, Payload.string(file)); } /** @@ -96,8 +91,8 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a click event * @since 4.0.0 */ - public static @NotNull ClickEvent runCommand(final @NotNull String command) { - return new ClickEvent(Action.RUN_COMMAND, Payload.string(command)); + static @NotNull ClickEvent runCommand(@NotNull String command) { + return ClickEventImpl.create(Action.RUN_COMMAND, Payload.string(command)); } /** @@ -107,8 +102,8 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a click event * @since 4.0.0 */ - public static @NotNull ClickEvent suggestCommand(final @NotNull String command) { - return new ClickEvent(Action.SUGGEST_COMMAND, Payload.string(command)); + static @NotNull ClickEvent suggestCommand(@NotNull String command) { + return ClickEventImpl.create(Action.SUGGEST_COMMAND, Payload.string(command)); } /** @@ -116,25 +111,10 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * * @param page the page to change to * @return a click event - * @throws IllegalArgumentException if the page cannot be represented as an integer using * @since 4.0.0 - * @deprecated For removal since 4.22.0, pages are integers, use {@link #changePage(int)} */ - @Deprecated - public static @NotNull ClickEvent changePage(final @NotNull String page) { - requireNonNull(page, "page"); - return new ClickEvent(Action.CHANGE_PAGE, Payload.integer(Integer.parseInt(page))); - } - - /** - * Creates a click event that changes to a page. - * - * @param page the page to change to - * @return a click event - * @since 4.0.0 - */ - public static @NotNull ClickEvent changePage(final int page) { - return new ClickEvent(Action.CHANGE_PAGE, Payload.integer(page)); + static @NotNull ClickEvent changePage(int page) { + return ClickEventImpl.create(Action.CHANGE_PAGE, Payload.integer(page)); } /** @@ -142,11 +122,11 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * * @param text the text to copy to the clipboard * @return a click event - * @since 4.0.0 * @sinceMinecraft 1.15 + * @since 4.0.0 */ - public static @NotNull ClickEvent copyToClipboard(final @NotNull String text) { - return new ClickEvent(Action.COPY_TO_CLIPBOARD, Payload.string(text)); + static @NotNull ClickEvent copyToClipboard(@NotNull String text) { + return ClickEventImpl.create(Action.COPY_TO_CLIPBOARD, Payload.string(text)); } /** @@ -158,7 +138,7 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a callback click event * @since 4.13.0 */ - public static @NotNull ClickEvent callback(final @NotNull ClickCallback function) { + static @NotNull ClickEvent callback(@NotNull ClickCallback function) { return ClickCallbackInternals.PROVIDER.create(requireNonNull(function, "function"), ClickCallbackOptionsImpl.DEFAULT); } @@ -170,7 +150,7 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a callback click event * @since 4.13.0 */ - public static @NotNull ClickEvent callback(final @NotNull ClickCallback function, final ClickCallback.@NotNull Options options) { + static @NotNull ClickEvent callback(@NotNull ClickCallback function, ClickCallback.@NotNull Options options) { return ClickCallbackInternals.PROVIDER.create(requireNonNull(function, "function"), requireNonNull(options, "options")); } @@ -182,7 +162,7 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return a callback click event * @since 4.13.0 */ - public static @NotNull ClickEvent callback(final @NotNull ClickCallback function, final @NotNull Consumer optionsBuilder) { + static @NotNull ClickEvent callback(@NotNull ClickCallback function, @NotNull Consumer optionsBuilder) { return ClickCallbackInternals.PROVIDER.create( requireNonNull(function, "function"), AbstractBuilder.configureAndBuild(ClickCallback.Options.builder(), requireNonNull(optionsBuilder, "optionsBuilder")) @@ -196,24 +176,9 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return the click event * @since 4.22.0 */ - public static @NotNull ClickEvent showDialog(final @NotNull DialogLike dialog) { + static @NotNull ClickEvent showDialog(@NotNull DialogLike dialog) { requireNonNull(dialog, "dialog"); - return new ClickEvent(Action.SHOW_DIALOG, Payload.dialog(dialog)); - } - - /** - * Creates a click event sends a custom event to the server. - * - * @param key the key - * @param data the data - * @return the click event - * @since 4.22.0 - * @deprecated For removal since 4.23.0, payloads hold NBT data, use {@link #custom(Key, BinaryTagHolder)} instead. - * This method will create NBT using {@link BinaryTagHolder#binaryTagHolder(String)}. - */ - @Deprecated - public static @NotNull ClickEvent custom(final @NotNull Key key, final @NotNull String data) { - return custom(key, BinaryTagHolder.binaryTagHolder(data)); + return ClickEventImpl.create(Action.SHOW_DIALOG, Payload.dialog(dialog)); } /** @@ -227,29 +192,10 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @return the click event * @since 4.23.0 */ - public static @NotNull ClickEvent custom(final @NotNull Key key, final @NotNull BinaryTagHolder nbt) { + static @NotNull ClickEvent custom(@NotNull Key key, @NotNull BinaryTagHolder nbt) { requireNonNull(key, "key"); requireNonNull(nbt, "nbt"); - return new ClickEvent(Action.CUSTOM, Payload.custom(key, nbt)); - } - - /** - * Creates a click event with a {@link Payload.Text string payload}. - * - * @param action the action - * @param value the value - * @return a click event - * @throws IllegalArgumentException if the action does not support a string payload - * @since 4.0.0 - * @deprecated For removal since 4.22.0, not all actions support string payloads. - * Use {@link #clickEvent(Action, Payload)} or the event-specific methods. - */ - @Deprecated - public static @NotNull ClickEvent clickEvent(final @NotNull Action action, final @NotNull String value) { - // A special case here to ensure that page can still accept a string. - if (action == Action.CHANGE_PAGE) return changePage(value); - if (!action.payloadType().equals(Payload.Text.class)) throw new IllegalArgumentException("Action " + action + " does not support string payloads"); - return new ClickEvent(action, Payload.string(value)); + return ClickEventImpl.create(Action.CUSTOM, Payload.custom(key, nbt)); } /** @@ -261,17 +207,8 @@ public final class ClickEvent implements Examinable, StyleBuilderApplicable { * @throws IllegalArgumentException if the action does not support that payload * @since 4.25.0 */ - public static @NotNull ClickEvent clickEvent(final @NotNull Action action, final @NotNull Payload payload) { - return new ClickEvent(action, payload); - } - - private final Action action; - private final Payload payload; - - private ClickEvent(final @NotNull Action action, final @NotNull Payload payload) { - if (!action.supports(payload)) throw new IllegalArgumentException("Action " + action + " does not support payload " + payload); - this.action = requireNonNull(action, "action"); - this.payload = requireNonNull(payload, "payload"); + static @NotNull ClickEvent clickEvent(final @NotNull Action action, final @NotNull T payload) { + return ClickEventImpl.create(action, payload); } /** @@ -280,70 +217,120 @@ private ClickEvent(final @NotNull Action action, final @NotNull Payload payload) * @return the click event action * @since 4.0.0 */ - public @NotNull Action action() { - return this.action; - } + @NotNull Action action(); /** - * Gets the click event value if the payload is a {@link Payload.Text string payload}. + * Gets the payload associated with this click event. * - * @return the click event value - * @throws IllegalStateException if the payload is not a string payload - * @since 4.0.0 - * @deprecated For removal since 4.22.0, click events can hold more than just strings, see {@link #payload()} + * @return the payload + * @since 4.22.0 */ - @Deprecated - public @NotNull String value() { - if (this.payload instanceof Payload.Text) { - return ((Payload.Text) this.payload).value(); - } else if (this.action == Action.CHANGE_PAGE) { // Special case for page. - return String.valueOf(((Payload.Int) this.payload).integer()); - } else { - throw new IllegalStateException("Payload is not a string payload, is " + this.payload); - } - } + @NotNull Payload payload(); /** - * Gets the payload associated with this click event. + * An enumeration of click event actions. * - * @return the payload - * @since 4.22.0 + * @param the payload type + * @since 4.0.0 */ - public @NotNull Payload payload() { - return this.payload; - } + sealed interface Action permits ClickEventImpl.ActionImpl { + /** + * Opens a url when clicked. + * + * @since 4.0.0 + */ + Action OPEN_URL = new ClickEventImpl.ActionImpl<>("open_url", true, Payload.Text.class); - @Override - public void styleApply(final Style.@NotNull Builder style) { - style.clickEvent(this); - } + /** + * Opens a file when clicked. + * + *

This action is not readable, and may only be used locally on the client.

+ * + * @since 4.0.0 + */ + Action OPEN_FILE = new ClickEventImpl.ActionImpl<>("open_file", false, Payload.Text.class); - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final ClickEvent that = (ClickEvent) other; - return this.action == that.action && Objects.equals(this.payload, that.payload); - } + /** + * Runs a command when clicked. + * + * @since 4.0.0 + */ + Action RUN_COMMAND = new ClickEventImpl.ActionImpl<>("run_command", true, Payload.Text.class); - @Override - public int hashCode() { - int result = this.action.hashCode(); - result = (31 * result) + this.payload.hashCode(); - return result; - } + /** + * Suggests a command into the chat box. + * + * @since 4.0.0 + */ + Action SUGGEST_COMMAND = new ClickEventImpl.ActionImpl<>("suggest_command", true, Payload.Text.class); - @Override - public @NotNull Stream examinableProperties() { - return Stream.of( - ExaminableProperty.of("action", this.action), - ExaminableProperty.of("payload", this.payload) - ); - } + /** + * Changes the page of a book. + * + * @since 4.0.0 + */ + Action CHANGE_PAGE = new ClickEventImpl.ActionImpl<>("change_page", true, Payload.Int.class); + + /** + * Copies text to the clipboard. + * + * @sinceMinecraft 1.15 + * @since 4.0.0 + */ + Action COPY_TO_CLIPBOARD = new ClickEventImpl.ActionImpl<>("copy_to_clipboard", true, Payload.Text.class); + + /** + * Shows a dialog. + * + *

This action is not readable at this time until Adventure has a full Dialog API.

+ * + * @sinceMinecraft 1.21.6 + * @since 4.22.0 + */ + Action SHOW_DIALOG = new ClickEventImpl.ActionImpl<>("show_dialog", false, Payload.Dialog.class); + + /** + * Sends a custom event to the server. + * + * @sinceMinecraft 1.21.6 + * @since 4.22.0 + */ + Action CUSTOM = new ClickEventImpl.ActionImpl<>("custom", true, Payload.Custom.class); + + /** + * The name map. + * + * @since 4.0.0 + */ + Index> NAMES = Index.create(Action::toString, OPEN_URL, OPEN_FILE, RUN_COMMAND, SUGGEST_COMMAND, CHANGE_PAGE, COPY_TO_CLIPBOARD, SHOW_DIALOG, CUSTOM); + + /** + * Tests if this action is readable. + * + * @return {@code true} if this action is readable, {@code false} if this + * action is not readable + * @since 4.0.0 + */ + boolean readable(); + + /** + * Returns if this action supports the provided payload. + * + * @param payload the payload + * @return {@code true} if this action supports the payload + * @since 4.22.0 + */ + boolean supports(final @NotNull Payload payload); - @Override - public String toString() { - return Internals.toString(this); + /** + * The type of the payload this click event supports. + * + * @return the payload type + * @since 4.22.0 + * @deprecated For removal, action now supports generics. + */ + @Deprecated(since = "5.0.0", forRemoval = true) + @NotNull Class payloadType(); } /** @@ -351,7 +338,7 @@ public String toString() { * * @since 4.22.0 */ - public /* sealed */ interface Payload /* permits String, Dialog, Custom */ extends Examinable { + sealed interface Payload extends Examinable permits ClickEventImpl.Payload.Custom, ClickEventImpl.Payload.Dialog, ClickEventImpl.Payload.Int, ClickEventImpl.Payload.Text { /** * Creates a text payload. * @@ -382,26 +369,11 @@ public String toString() { * @return the payload * @since 4.22.0 */ - static Payload.@NotNull Dialog dialog(final @NotNull DialogLike dialog) { + static ClickEventImpl.Payload.@NotNull Dialog dialog(final @NotNull DialogLike dialog) { requireNonNull(dialog, "dialog"); return new PayloadImpl.DialogImpl(dialog); } - /** - * Creates a custom payload. - * - * @param key the key identifying the payload - * @param data the payload data - * @return the payload - * @since 4.22.0 - * @deprecated For removal since 4.23.0, payloads hold NBT data, use {@link #custom(Key, BinaryTagHolder)} instead. - * This method will create NBT using {@link BinaryTagHolder#binaryTagHolder(String)}. - */ - @Deprecated - static Payload.@NotNull Custom custom(final @NotNull Key key, final @NotNull String data) { - return Payload.custom(key, BinaryTagHolder.binaryTagHolder(data)); - } - /** * Creates a custom payload. * @@ -413,7 +385,7 @@ public String toString() { * @return the payload * @since 4.23.0 */ - static Payload.@NotNull Custom custom(final @NotNull Key key, final @NotNull BinaryTagHolder nbt) { + static ClickEventImpl.Payload.@NotNull Custom custom(final @NotNull Key key, final @NotNull BinaryTagHolder nbt) { requireNonNull(key, "key"); requireNonNull(nbt, "nbt"); return new PayloadImpl.CustomImpl(key, nbt); @@ -424,7 +396,7 @@ public String toString() { * * @since 4.22.0 */ - interface Text extends Payload { + sealed interface Text extends Payload permits PayloadImpl.TextImpl { /** * The string value for this payload. * @@ -439,7 +411,7 @@ interface Text extends Payload { * * @since 4.22.0 */ - interface Int extends Payload { + sealed interface Int extends Payload permits PayloadImpl.IntImpl { /** * The integer value for this payload. * @@ -455,7 +427,7 @@ interface Int extends Payload { * @see Action#SHOW_DIALOG * @since 4.22.0 */ - interface Dialog extends Payload { + sealed interface Dialog extends Payload permits PayloadImpl.DialogImpl { /** * The dialog. * @@ -471,18 +443,7 @@ interface Dialog extends Payload { * @see Action#CUSTOM * @since 4.22.0 */ - interface Custom extends Payload, Keyed { - /** - * The custom data. - * - * @return the data - * @since 4.22.0 - * @deprecated For removal since 4.23.0, custom payloads contain NBT data, use {@link #nbt()} instead. - * This method will return {@link BinaryTagHolder#string()} on the held NBT. - */ - @Deprecated - @NotNull String data(); - + sealed interface Custom extends Payload, Keyed permits PayloadImpl.CustomImpl { /** * The custom data. * @@ -494,126 +455,4 @@ interface Custom extends Payload, Keyed { @NotNull BinaryTagHolder nbt(); } } - - /** - * An enumeration of click event actions. - * - * @since 4.0.0 - */ - public enum Action { - /** - * Opens a url when clicked. - * - * @since 4.0.0 - */ - OPEN_URL("open_url", true, Payload.Text.class), - /** - * Opens a file when clicked. - * - *

This action is not readable, and may only be used locally on the client.

- * - * @since 4.0.0 - */ - OPEN_FILE("open_file", false, Payload.Text.class), - /** - * Runs a command when clicked. - * - * @since 4.0.0 - */ - RUN_COMMAND("run_command", true, Payload.Text.class), - /** - * Suggests a command into the chat box. - * - * @since 4.0.0 - */ - SUGGEST_COMMAND("suggest_command", true, Payload.Text.class), - /** - * Changes the page of a book. - * - * @since 4.0.0 - */ - CHANGE_PAGE("change_page", true, Payload.Int.class), - /** - * Copies text to the clipboard. - * - * @since 4.0.0 - * @sinceMinecraft 1.15 - */ - COPY_TO_CLIPBOARD("copy_to_clipboard", true, Payload.Text.class), - /** - * Shows a dialog. - * - *

This action is not readable at this time until Adventure has a full Dialog API.

- * - * @since 4.22.0 - * @sinceMinecraft 1.21.6 - */ - SHOW_DIALOG("show_dialog", false, Payload.Dialog.class), - /** - * Sends a custom event to the server. - * - * @since 4.22.0 - * @sinceMinecraft 1.21.6 - */ - CUSTOM("custom", true, Payload.Custom.class); - - /** - * The name map. - * - * @since 4.0.0 - */ - public static final Index NAMES = Index.create(Action.class, constant -> constant.name); - private final String name; - /** - * If this action is readable. - * - *

When an action is not readable it will not be deserialized.

- */ - private final boolean readable; - private final Class payloadType; - - Action(final @NotNull String name, final boolean readable, final @NotNull Class payloadType) { - this.name = name; - this.readable = readable; - this.payloadType = payloadType; - } - - /** - * Tests if this action is readable. - * - * @return {@code true} if this action is readable, {@code false} if this - * action is not readable - * @since 4.0.0 - */ - public boolean readable() { - return this.readable; - } - - /** - * Returns if this action supports the provided payload. - * - * @param payload the payload - * @return {@code true} if this action supports the payload - * @since 4.22.0 - */ - public boolean supports(final @NotNull Payload payload) { - requireNonNull(payload, "payload"); - return this.payloadType.isAssignableFrom(payload.getClass()); - } - - /** - * The type of the payload this click event supports. - * - * @return the payload type - * @since 4.22.0 - */ - public @NotNull Class payloadType() { - return this.payloadType; - } - - @Override - public @NotNull String toString() { - return this.name; - } - } } diff --git a/api/src/main/java/net/kyori/adventure/text/event/ClickEventImpl.java b/api/src/main/java/net/kyori/adventure/text/event/ClickEventImpl.java new file mode 100644 index 000000000..059df689e --- /dev/null +++ b/api/src/main/java/net/kyori/adventure/text/event/ClickEventImpl.java @@ -0,0 +1,64 @@ +/* + * This file is part of adventure, licensed under the MIT License. + * + * Copyright (c) 2017-2025 KyoriPowered + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package net.kyori.adventure.text.event; + +import java.util.stream.Stream; +import net.kyori.adventure.internal.Internals; +import net.kyori.adventure.text.format.Style; +import net.kyori.examination.ExaminableProperty; +import org.jetbrains.annotations.NotNull; + +import static java.util.Objects.requireNonNull; + +record ClickEventImpl(Action action, Payload payload) implements ClickEvent { + + static ClickEvent create(final @NotNull Action action, final @NotNull T payload) { + return new ClickEventImpl<>(requireNonNull(action, "action"), requireNonNull(payload, "payload")); + } + + @Override + public void styleApply(final Style.@NotNull Builder style) { + style.clickEvent(this); + } + + @Override + public @NotNull Stream examinableProperties() { + return Stream.of( + ExaminableProperty.of("action", this.action), + ExaminableProperty.of("payload", this.payload) + ); + } + + @Override + public @NotNull String toString() { + return Internals.toString(this); + } + + record ActionImpl(String name, boolean readable, Class payloadType) implements ClickEvent.Action { + @Override + public boolean supports(final @NotNull Payload payload) { + return payload.getClass() == this.payloadType; + } + } +} diff --git a/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConversionImpl.java b/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConversionImpl.java index d63d0ad97..195f52695 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConversionImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConversionImpl.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.text.event; -import java.util.Objects; import java.util.function.BiFunction; import java.util.stream.Stream; import net.kyori.adventure.internal.Internals; @@ -33,26 +32,7 @@ import static java.util.Objects.requireNonNull; -final class DataComponentValueConversionImpl implements DataComponentValueConverterRegistry.Conversion { - private final Class source; - private final Class destination; - private final BiFunction conversion; - - DataComponentValueConversionImpl(final @NotNull Class source, final @NotNull Class destination, final @NotNull BiFunction conversion) { - this.source = source; - this.destination = destination; - this.conversion = conversion; - } - - @Override - public @NotNull Class source() { - return this.source; - } - - @Override - public @NotNull Class destination() { - return this.destination; - } +record DataComponentValueConversionImpl(Class source, Class destination, BiFunction conversion) implements DataComponentValueConverterRegistry.Conversion { @Override public @NotNull O convert(final @NotNull Key key, final @NotNull I input) { @@ -69,22 +49,7 @@ final class DataComponentValueConversionImpl implements DataComponentValue } @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } - - @Override - public boolean equals(final Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final DataComponentValueConversionImpl that = (DataComponentValueConversionImpl) other; - return Objects.equals(this.source, that.source) - && Objects.equals(this.destination, that.destination) - && Objects.equals(this.conversion, that.conversion); - } - - @Override - public int hashCode() { - return Objects.hash(this.source, this.destination, this.conversion); - } } diff --git a/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConverterRegistry.java b/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConverterRegistry.java index d8d122523..9f2b74e69 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConverterRegistry.java +++ b/api/src/main/java/net/kyori/adventure/text/event/DataComponentValueConverterRegistry.java @@ -35,6 +35,7 @@ import java.util.function.BiFunction; import java.util.stream.Collectors; import net.kyori.adventure.key.Key; +import net.kyori.adventure.util.PlatformAPI; import net.kyori.adventure.util.Services; import net.kyori.examination.Examinable; import org.jetbrains.annotations.ApiStatus; @@ -63,10 +64,10 @@ private DataComponentValueConverterRegistry() { * @return an unmodifiable set of the known provider ids * @since 4.1.7.0 */ - public static Set knownProviders() { - return Collections.unmodifiableSet(PROVIDERS.stream() + public static @NotNull Set knownProviders() { + return PROVIDERS.stream() .map(Provider::id) - .collect(Collectors.toSet())); + .collect(Collectors.toUnmodifiableSet()); } /** @@ -102,6 +103,8 @@ public static Set knownProviders() { * * @since 4.17.0 */ + @ApiStatus.NonExtendable + @PlatformAPI public interface Provider { /** * An identifier for this provider. @@ -129,8 +132,7 @@ public interface Provider { * @param output type * @since 4.17.0 */ - @ApiStatus.NonExtendable - public interface Conversion extends Examinable { + public sealed interface Conversion extends Examinable permits DataComponentValueConversionImpl { /** * Create a new conversion. * @@ -246,15 +248,7 @@ private static void addSupertypes(final Class clazz, final Deque> qu } } - static final class RegisteredConversion { - static final RegisteredConversion NONE = new RegisteredConversion(null, null); - - final Key provider; - final Conversion conversion; - - RegisteredConversion(final Key provider, final Conversion conversion) { - this.provider = provider; - this.conversion = conversion; - } + record RegisteredConversion(Key provider, Conversion conversion) { + static final RegisteredConversion NONE = new RegisteredConversion(null, null); } } diff --git a/api/src/main/java/net/kyori/adventure/text/event/HoverEvent.java b/api/src/main/java/net/kyori/adventure/text/event/HoverEvent.java index 90c408f95..795106102 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/HoverEvent.java +++ b/api/src/main/java/net/kyori/adventure/text/event/HoverEvent.java @@ -24,25 +24,19 @@ package net.kyori.adventure.text.event; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import java.util.Objects; import java.util.UUID; -import java.util.function.UnaryOperator; -import java.util.stream.Stream; -import net.kyori.adventure.internal.Internals; import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Keyed; import net.kyori.adventure.nbt.api.BinaryTagHolder; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; -import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.StyleBuilderApplicable; import net.kyori.adventure.text.renderer.ComponentRenderer; import net.kyori.adventure.util.Index; import net.kyori.examination.Examinable; -import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Range; @@ -58,7 +52,7 @@ * @param the value type * @since 4.0.0 */ -public final class HoverEvent implements Examinable, HoverEventSource, StyleBuilderApplicable { +public sealed interface HoverEvent extends Examinable, HoverEventSource, StyleBuilderApplicable permits HoverEventImpl { /** * Creates a hover event that shows text on hover. * @@ -66,7 +60,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.2.0 */ - public static @NotNull HoverEvent showText(final @NotNull ComponentLike text) { + static @NotNull HoverEvent showText(@NotNull ComponentLike text) { return showText(text.asComponent()); } @@ -77,8 +71,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.0.0 */ - public static @NotNull HoverEvent showText(final @NotNull Component text) { - return new HoverEvent<>(Action.SHOW_TEXT, text); + static @NotNull HoverEvent showText(@NotNull Component text) { + return new HoverEventImpl<>(Action.SHOW_TEXT, text); } /** @@ -89,7 +83,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.0.0 */ - public static @NotNull HoverEvent showItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { + static @NotNull HoverEvent showItem(@NotNull Key item, @Range(from = 0, to = Integer.MAX_VALUE) int count) { return showItem(item, count, Collections.emptyMap()); } @@ -101,7 +95,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.6.0 */ - public static @NotNull HoverEvent showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { + static @NotNull HoverEvent showItem(@NotNull Keyed item, @Range(from = 0, to = Integer.MAX_VALUE) int count) { return showItem(item, count, Collections.emptyMap()); } @@ -113,9 +107,10 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @param nbt the nbt * @return a hover event * @since 4.0.0 + * @deprecated since Minecraft 1.20.5 and replaced with data components, not scheduled for removal */ @Deprecated - public static @NotNull HoverEvent showItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { + static @NotNull HoverEvent showItem(@NotNull Key item, @Range(from = 0, to = Integer.MAX_VALUE) int count, @Nullable BinaryTagHolder nbt) { return showItem(ShowItem.showItem(item, count, nbt)); } @@ -130,7 +125,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @deprecated since Minecraft 1.20.5 and replaced with data components, not scheduled for removal */ @Deprecated - public static @NotNull HoverEvent showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { + static @NotNull HoverEvent showItem(@NotNull Keyed item, @Range(from = 0, to = Integer.MAX_VALUE) int count, @Nullable BinaryTagHolder nbt) { return showItem(ShowItem.showItem(item, count, nbt)); } @@ -143,7 +138,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.17.0 */ - public static @NotNull HoverEvent showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @NotNull Map dataComponents) { + static @NotNull HoverEvent showItem(@NotNull Keyed item, @Range(from = 0, to = Integer.MAX_VALUE) int count, @NotNull Map dataComponents) { return showItem(ShowItem.showItem(item, count, dataComponents)); } @@ -154,8 +149,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.0.0 */ - public static @NotNull HoverEvent showItem(final @NotNull ShowItem item) { - return new HoverEvent<>(Action.SHOW_ITEM, item); + static @NotNull HoverEvent showItem(@NotNull ShowItem item) { + return new HoverEventImpl<>(Action.SHOW_ITEM, item); } /** @@ -168,7 +163,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a {@code ShowEntity} * @since 4.0.0 */ - public static @NotNull HoverEvent showEntity(final @NotNull Key type, final @NotNull UUID id) { + static @NotNull HoverEvent showEntity(@NotNull Key type, @NotNull UUID id) { return showEntity(type, id, null); } @@ -182,7 +177,7 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a {@code ShowEntity} * @since 4.6.0 */ - public static @NotNull HoverEvent showEntity(final @NotNull Keyed type, final @NotNull UUID id) { + static @NotNull HoverEvent showEntity(@NotNull Keyed type, @NotNull UUID id) { return showEntity(type, id, null); } @@ -197,8 +192,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a {@code ShowEntity} * @since 4.0.0 */ - public static @NotNull HoverEvent showEntity(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) { - return showEntity(ShowEntity.of(type, id, name)); + static @NotNull HoverEvent showEntity(@NotNull Key type, @NotNull UUID id, @Nullable Component name) { + return showEntity(ShowEntity.showEntity(type, id, name)); } /** @@ -212,8 +207,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a {@code ShowEntity} * @since 4.6.0 */ - public static @NotNull HoverEvent showEntity(final @NotNull Keyed type, final @NotNull UUID id, final @Nullable Component name) { - return showEntity(ShowEntity.of(type, id, name)); + static @NotNull HoverEvent showEntity(@NotNull Keyed type, @NotNull UUID id, @Nullable Component name) { + return showEntity(ShowEntity.showEntity(type, id, name)); } /** @@ -225,8 +220,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a hover event * @since 4.0.0 */ - public static @NotNull HoverEvent showEntity(final @NotNull ShowEntity entity) { - return new HoverEvent<>(Action.SHOW_ENTITY, entity); + static @NotNull HoverEvent showEntity(@NotNull ShowEntity entity) { + return new HoverEventImpl<>(Action.SHOW_ENTITY, entity); } /** @@ -238,8 +233,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @deprecated Removed in Vanilla 1.12, but we keep it for backwards compatibility */ @Deprecated - public static @NotNull HoverEvent showAchievement(final @NotNull String value) { - return new HoverEvent<>(Action.SHOW_ACHIEVEMENT, value); + static @NotNull HoverEvent showAchievement(@NotNull String value) { + return new HoverEventImpl<>(Action.SHOW_ACHIEVEMENT, value); } /** @@ -251,16 +246,8 @@ public final class HoverEvent implements Examinable, HoverEventSource, Sty * @return a click event * @since 4.0.0 */ - public static @NotNull HoverEvent hoverEvent(final @NotNull Action action, final @NotNull V value) { - return new HoverEvent<>(action, value); - } - - private final Action action; - private final V value; - - private HoverEvent(final @NotNull Action action, final @NotNull V value) { - this.action = requireNonNull(action, "action"); - this.value = requireNonNull(value, "value"); + static @NotNull HoverEvent hoverEvent(@NotNull Action action, @NotNull V value) { + return new HoverEventImpl<>(action, value); } /** @@ -269,9 +256,7 @@ private HoverEvent(final @NotNull Action action, final @NotNull V value) { * @return the hover event action * @since 4.0.0 */ - public @NotNull Action action() { - return this.action; - } + @NotNull Action action(); /** * Gets the hover event value. @@ -279,20 +264,17 @@ private HoverEvent(final @NotNull Action action, final @NotNull V value) { * @return the hover event value * @since 4.0.0 */ - public @NotNull V value() { - return this.value; - } + @NotNull V value(); /** * Sets the hover event value. * * @param value the hover event value - * @return a hover event + * @return a new hover event with the value set * @since 4.0.0 */ - public @NotNull HoverEvent value(final @NotNull V value) { - return new HoverEvent<>(this.action, value); - } + @Contract(pure = true) + @NotNull HoverEvent value(final @NotNull V value); /** * Returns a hover event with the value rendered using {@code renderer} when possible. @@ -303,68 +285,14 @@ private HoverEvent(final @NotNull Action action, final @NotNull V value) { * @return a hover event * @since 4.0.0 */ - public @NotNull HoverEvent withRenderedValue(final @NotNull ComponentRenderer renderer, final @NotNull C context) { - final V oldValue = this.value; - final V newValue = this.action.renderer.render(renderer, context, oldValue); - if (newValue != oldValue) return new HoverEvent<>(this.action, newValue); - return this; - } - - @Override - public @NotNull HoverEvent asHoverEvent() { - return this; // i already am a hover event! hehehehe - } - - @Override - public @NotNull HoverEvent asHoverEvent(final @NotNull UnaryOperator op) { - if (op == UnaryOperator.identity()) return this; // nothing to do, can return ourself - return new HoverEvent<>(this.action, op.apply(this.value)); - } - - @Override - public void styleApply(final Style.@NotNull Builder style) { - style.hoverEvent(this); - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final HoverEvent that = (HoverEvent) other; - return this.action == that.action && this.value.equals(that.value); - } - - @Override - public int hashCode() { - int result = this.action.hashCode(); - result = (31 * result) + this.value.hashCode(); - return result; - } - - @Override - public @NotNull Stream examinableProperties() { - return Stream.of( - ExaminableProperty.of("action", this.action), - ExaminableProperty.of("value", this.value) - ); - } - - @Override - public String toString() { - return Internals.toString(this); - } + @NotNull HoverEvent withRenderedValue(final @NotNull ComponentRenderer renderer, final @NotNull C context); /** * The value of a {@link Action#SHOW_ITEM show_item} hover event. * * @since 4.0.0 */ - public static final class ShowItem implements Examinable { - private final Key item; - private final int count; - private final @Nullable BinaryTagHolder nbt; - private final Map dataComponents; - + sealed interface ShowItem extends Examinable permits HoverEventImpl.ShowItemImpl { /** * Creates. * @@ -373,23 +301,8 @@ public static final class ShowItem implements Examinable { * @return a {@code ShowItem} * @since 4.14.0 */ - public static @NotNull ShowItem showItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { - return showItem(item, count, Collections.emptyMap()); - } - - /** - * Creates. - * - * @param item the item - * @param count the count - * @return a {@code ShowItem} - * @since 4.0.0 - * @deprecated for removal since 4.14.0, use {@link #showItem(Key, int)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowItem of(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { - return showItem(item, count, Collections.emptyMap()); + static @NotNull ShowItem showItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { + return ShowItem.showItem(item, count, Collections.emptyMap()); } /** @@ -400,23 +313,8 @@ public static final class ShowItem implements Examinable { * @return a {@code ShowItem} * @since 4.14.0 */ - public static @NotNull ShowItem showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { - return showItem(item, count, Collections.emptyMap()); - } - - /** - * Creates. - * - * @param item the item - * @param count the count - * @return a {@code ShowItem} - * @since 4.6.0 - * @deprecated for removal since 4.14.0, use {@link #showItem(Keyed, int)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowItem of(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { - return of(item, count, null); + static @NotNull ShowItem showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count) { + return ShowItem.showItem(item, count, Collections.emptyMap()); } /** @@ -430,24 +328,8 @@ public static final class ShowItem implements Examinable { * @deprecated since Minecraft 1.20.5 and replaced with data components, not scheduled for removal */ @Deprecated - public static @NotNull ShowItem showItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { - return new ShowItem(requireNonNull(item, "item"), count, nbt, Collections.emptyMap()); - } - - /** - * Creates. - * - * @param item the item - * @param count the count - * @param nbt the nbt - * @return a {@code ShowItem} - * @since 4.0.0 - * @deprecated for removal since 4.14.0, use {@link #showItem(Key, int, BinaryTagHolder)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowItem of(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { - return new ShowItem(requireNonNull(item, "item"), count, nbt, Collections.emptyMap()); + static @NotNull ShowItem showItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { + return new HoverEventImpl.ShowItemImpl(requireNonNull(item, "item"), count, nbt, Collections.emptyMap()); } /** @@ -461,24 +343,8 @@ public static final class ShowItem implements Examinable { * @deprecated since Minecraft 1.20.5 and replaced with data components, not scheduled for removal */ @Deprecated - public static @NotNull ShowItem showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { - return new ShowItem(requireNonNull(item, "item").key(), count, nbt, Collections.emptyMap()); - } - - /** - * Creates. - * - * @param item the item - * @param count the count - * @param nbt the nbt - * @return a {@code ShowItem} - * @since 4.6.0 - * @deprecated for removal since 4.14.0, use {@link #showItem(Keyed, int, BinaryTagHolder)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowItem of(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { - return new ShowItem(requireNonNull(item, "item").key(), count, nbt, Collections.emptyMap()); + static @NotNull ShowItem showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt) { + return new HoverEventImpl.ShowItemImpl(requireNonNull(item, "item").key(), count, nbt, Collections.emptyMap()); } /** @@ -488,18 +354,11 @@ public static final class ShowItem implements Examinable { * @param count the count * @param dataComponents the data components * @return a {@code ShowItem} - * @since 4.17.0 * @sinceMinecraft 1.20.5 + * @since 4.17.0 */ - public static @NotNull ShowItem showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @NotNull Map dataComponents) { - return new ShowItem(requireNonNull(item, "item").key(), count, null, dataComponents); - } - - private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @Nullable BinaryTagHolder nbt, final @NotNull Map dataComponents) { - this.item = item; - this.count = count; - this.nbt = nbt; - this.dataComponents = Collections.unmodifiableMap(new HashMap<>(dataComponents)); + static @NotNull ShowItem showItem(final @NotNull Keyed item, final @Range(from = 0, to = Integer.MAX_VALUE) int count, final @NotNull Map dataComponents) { + return new HoverEventImpl.ShowItemImpl(requireNonNull(item, "item").key(), count, null, Map.copyOf(requireNonNull(dataComponents, "dataComponents"))); } /** @@ -508,9 +367,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @return the item * @since 4.0.0 */ - public @NotNull Key item() { - return this.item; - } + @NotNull Key item(); /** * Sets the item. @@ -519,10 +376,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @return a {@code ShowItem} * @since 4.0.0 */ - public @NotNull ShowItem item(final @NotNull Key item) { - if (requireNonNull(item, "item").equals(this.item)) return this; - return new ShowItem(item, this.count, this.nbt, this.dataComponents); - } + @NotNull ShowItem item(final @NotNull Key item); /** * Gets the count. @@ -530,9 +384,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @return the count * @since 4.0.0 */ - public @Range(from = 0, to = Integer.MAX_VALUE) int count() { - return this.count; - } + @Range(from = 0, to = Integer.MAX_VALUE) int count(); /** * Sets the count. @@ -541,10 +393,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @return a {@code ShowItem} * @since 4.0.0 */ - public @NotNull ShowItem count(final @Range(from = 0, to = Integer.MAX_VALUE) int count) { - if (count == this.count) return this; - return new ShowItem(this.item, count, this.nbt, this.dataComponents); - } + @NotNull ShowItem count(final @Range(from = 0, to = Integer.MAX_VALUE) int count); /** * Gets the nbt. @@ -556,9 +405,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @deprecated since Minecraft 1.20.5 and replaced with data components, not scheduled for removal */ @Deprecated - public @Nullable BinaryTagHolder nbt() { - return this.nbt; - } + @Nullable BinaryTagHolder nbt(); /** * Sets the nbt. @@ -571,10 +418,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @deprecated since Minecraft 1.20.5 and replaced with data components, not scheduled for removal */ @Deprecated - public @NotNull ShowItem nbt(final @Nullable BinaryTagHolder nbt) { - if (Objects.equals(nbt, this.nbt)) return this; - return new ShowItem(this.item, this.count, nbt, Collections.emptyMap()); - } + @NotNull ShowItem nbt(final @Nullable BinaryTagHolder nbt); /** * Get the data components used for this item. @@ -582,12 +426,10 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA *

If there is NBT data on this item, it will never have any data components set.

* * @return an unmodifiable map of data components - * @since 4.17.0 * @sinceMinecraft 1.20.5 + * @since 4.17.0 */ - public @NotNull Map dataComponents() { - return this.dataComponents; - } + @NotNull Map dataComponents(); /** * Set the data components used on this item. @@ -596,13 +438,9 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * * @param holder the new data components to set * @return a show item data object that has the provided components - * @since 4.17.0 * @sinceMinecraft 1.20.5 */ - public @NotNull ShowItem dataComponents(final @NotNull Map holder) { - if (Objects.equals(this.dataComponents, holder)) return this; - return new ShowItem(this.item, this.count, null, holder.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(new HashMap<>(holder))); - } + @NotNull ShowItem dataComponents(final @NotNull Map holder); /** * Return an unmodifiable map of data components coerced to the target type. @@ -614,49 +452,7 @@ private ShowItem(final @NotNull Key item, final @Range(from = 0, to = Integer.MA * @return the unmodifiable map * @since 4.17.0 */ - public @NotNull Map dataComponentsAs(final @NotNull Class targetType) { - if (this.dataComponents.isEmpty()) { - return Collections.emptyMap(); - } else { - final Map results = new HashMap<>(this.dataComponents.size()); - for (final Map.Entry entry : this.dataComponents.entrySet()) { - results.put(entry.getKey(), DataComponentValueConverterRegistry.convert(targetType, entry.getKey(), entry.getValue())); - } - return Collections.unmodifiableMap(results); - } - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final ShowItem that = (ShowItem) other; - return this.item.equals(that.item) && this.count == that.count && Objects.equals(this.nbt, that.nbt) && Objects.equals(this.dataComponents, that.dataComponents); - } - - @Override - public int hashCode() { - int result = this.item.hashCode(); - result = (31 * result) + Integer.hashCode(this.count); - result = (31 * result) + Objects.hashCode(this.nbt); - result = (31 * result) + Objects.hashCode(this.dataComponents); - return result; - } - - @Override - public @NotNull Stream examinableProperties() { - return Stream.of( - ExaminableProperty.of("item", this.item), - ExaminableProperty.of("count", this.count), - ExaminableProperty.of("nbt", this.nbt), - ExaminableProperty.of("dataComponents", this.dataComponents) - ); - } - - @Override - public String toString() { - return Internals.toString(this); - } + @NotNull Map dataComponentsAs(final @NotNull Class targetType); } /** @@ -664,11 +460,7 @@ public String toString() { * * @since 4.0.0 */ - public static final class ShowEntity implements Examinable { - private final Key type; - private final UUID id; - private final Component name; - + sealed interface ShowEntity extends Examinable permits HoverEventImpl.ShowEntityImpl { /** * Creates. * @@ -677,23 +469,8 @@ public static final class ShowEntity implements Examinable { * @return a {@code ShowEntity} * @since 4.14.0 */ - public static @NotNull ShowEntity showEntity(final @NotNull Key type, final @NotNull UUID id) { - return showEntity(type, id, null); - } - - /** - * Creates. - * - * @param type the type - * @param id the id - * @return a {@code ShowEntity} - * @since 4.0.0 - * @deprecated for removal since 4.14.0, use {@link #showEntity(Key, UUID)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowEntity of(final @NotNull Key type, final @NotNull UUID id) { - return of(type, id, null); + static @NotNull ShowEntity showEntity(final @NotNull Key type, final @NotNull UUID id) { + return ShowEntity.showEntity(type, id, null); } /** @@ -704,23 +481,8 @@ public static final class ShowEntity implements Examinable { * @return a {@code ShowEntity} * @since 4.14.0 */ - public static @NotNull ShowEntity showEntity(final @NotNull Keyed type, final @NotNull UUID id) { - return showEntity(type, id, null); - } - - /** - * Creates. - * - * @param type the type - * @param id the id - * @return a {@code ShowEntity} - * @since 4.6.0 - * @deprecated for removal since 4.14.0, use {@link #showEntity(Keyed, UUID)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowEntity of(final @NotNull Keyed type, final @NotNull UUID id) { - return of(type, id, null); + static @NotNull ShowEntity showEntity(final @NotNull Keyed type, final @NotNull UUID id) { + return ShowEntity.showEntity(type, id, null); } /** @@ -732,24 +494,8 @@ public static final class ShowEntity implements Examinable { * @return a {@code ShowEntity} * @since 4.14.0 */ - public static @NotNull ShowEntity showEntity(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) { - return new ShowEntity(requireNonNull(type, "type"), requireNonNull(id, "id"), name); - } - - /** - * Creates. - * - * @param type the type - * @param id the id - * @param name the name - * @return a {@code ShowEntity} - * @since 4.0.0 - * @deprecated for removal since 4.14.0, use {@link #showEntity(Key, UUID, Component)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowEntity of(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) { - return new ShowEntity(requireNonNull(type, "type"), requireNonNull(id, "id"), name); + static @NotNull ShowEntity showEntity(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) { + return new HoverEventImpl.ShowEntityImpl(requireNonNull(type, "type"), requireNonNull(id, "id"), name); } /** @@ -761,30 +507,8 @@ public static final class ShowEntity implements Examinable { * @return a {@code ShowEntity} * @since 4.14.0 */ - public static @NotNull ShowEntity showEntity(final @NotNull Keyed type, final @NotNull UUID id, final @Nullable Component name) { - return new ShowEntity(requireNonNull(type, "type").key(), requireNonNull(id, "id"), name); - } - - /** - * Creates. - * - * @param type the type - * @param id the id - * @param name the name - * @return a {@code ShowEntity} - * @since 4.6.0 - * @deprecated for removal since 4.14.0, use {@link #showEntity(Keyed, UUID, Component)} instead. - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @NotNull ShowEntity of(final @NotNull Keyed type, final @NotNull UUID id, final @Nullable Component name) { - return new ShowEntity(requireNonNull(type, "type").key(), requireNonNull(id, "id"), name); - } - - private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nullable Component name) { - this.type = type; - this.id = id; - this.name = name; + static @NotNull ShowEntity showEntity(final @NotNull Keyed type, final @NotNull UUID id, final @Nullable Component name) { + return new HoverEventImpl.ShowEntityImpl(requireNonNull(type, "type").key(), requireNonNull(id, "id"), name); } /** @@ -793,9 +517,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return the type * @since 4.0.0 */ - public @NotNull Key type() { - return this.type; - } + @NotNull Key type(); /** * Sets the type. @@ -804,10 +526,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return a {@code ShowEntity} * @since 4.0.0 */ - public @NotNull ShowEntity type(final @NotNull Key type) { - if (requireNonNull(type, "type").equals(this.type)) return this; - return new ShowEntity(type, this.id, this.name); - } + @NotNull ShowEntity type(final @NotNull Key type); /** * Sets the type. @@ -816,7 +535,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return a {@code ShowEntity} * @since 4.6.0 */ - public @NotNull ShowEntity type(final @NotNull Keyed type) { + default @NotNull ShowEntity type(final @NotNull Keyed type) { return this.type(requireNonNull(type, "type").key()); } @@ -826,9 +545,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return the id * @since 4.0.0 */ - public @NotNull UUID id() { - return this.id; - } + @NotNull UUID id(); /** * Sets the id. @@ -837,10 +554,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return a {@code ShowEntity} * @since 4.0.0 */ - public @NotNull ShowEntity id(final @NotNull UUID id) { - if (requireNonNull(id).equals(this.id)) return this; - return new ShowEntity(this.type, id, this.name); - } + @NotNull ShowEntity id(final @NotNull UUID id); /** * Gets the name. @@ -848,9 +562,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return the name * @since 4.0.0 */ - public @Nullable Component name() { - return this.name; - } + @Nullable Component name(); /** * Sets the name. @@ -859,40 +571,7 @@ private ShowEntity(final @NotNull Key type, final @NotNull UUID id, final @Nulla * @return a {@code ShowEntity} * @since 4.0.0 */ - public @NotNull ShowEntity name(final @Nullable Component name) { - if (Objects.equals(name, this.name)) return this; - return new ShowEntity(this.type, this.id, name); - } - - @Override - public boolean equals(final @Nullable Object other) { - if (this == other) return true; - if (other == null || this.getClass() != other.getClass()) return false; - final ShowEntity that = (ShowEntity) other; - return this.type.equals(that.type) && this.id.equals(that.id) && Objects.equals(this.name, that.name); - } - - @Override - public int hashCode() { - int result = this.type.hashCode(); - result = (31 * result) + this.id.hashCode(); - result = (31 * result) + Objects.hashCode(this.name); - return result; - } - - @Override - public @NotNull Stream examinableProperties() { - return Stream.of( - ExaminableProperty.of("type", this.type), - ExaminableProperty.of("id", this.id), - ExaminableProperty.of("name", this.name) - ); - } - - @Override - public String toString() { - return Internals.toString(this); - } + @NotNull ShowEntity name(final @Nullable Component name); } /** @@ -901,13 +580,13 @@ public String toString() { * @param the value type an action handles * @since 4.0.0 */ - public static final class Action { + sealed interface Action permits HoverEventImpl.ActionImpl { /** * Shows a {@link Component} when hovered over. * * @since 4.0.0 */ - public static final Action SHOW_TEXT = new Action<>("show_text", Component.class, true, new Renderer() { + Action SHOW_TEXT = new HoverEventImpl.ActionImpl<>("show_text", Component.class, true, new Renderer<>() { @Override public @NotNull Component render(final @NotNull ComponentRenderer renderer, final @NotNull C context, final @NotNull Component value) { return renderer.render(value, context); @@ -918,7 +597,7 @@ public static final class Action { * * @since 4.0.0 */ - public static final Action SHOW_ITEM = new Action<>("show_item", ShowItem.class, true, new Renderer() { + Action SHOW_ITEM = new HoverEventImpl.ActionImpl<>("show_item", ShowItem.class, true, new Renderer<>() { @Override public @NotNull ShowItem render(final @NotNull ComponentRenderer renderer, final @NotNull C context, final @NotNull ShowItem value) { return value; @@ -929,11 +608,12 @@ public static final class Action { * * @since 4.0.0 */ - public static final Action SHOW_ENTITY = new Action<>("show_entity", ShowEntity.class, true, new Renderer() { + Action SHOW_ENTITY = new HoverEventImpl.ActionImpl<>("show_entity", ShowEntity.class, true, new Renderer<>() { @Override public @NotNull ShowEntity render(final @NotNull ComponentRenderer renderer, final @NotNull C context, final @NotNull ShowEntity value) { - if (value.name == null) return value; - return value.name(renderer.render(value.name, context)); + final Component name = value.name(); + if (name == null) return value; + return value.name(renderer.render(name, context)); } }); /** @@ -943,7 +623,7 @@ public static final class Action { * @deprecated Removed in Vanilla 1.12, but we keep it for backwards compat */ @Deprecated - public static final Action SHOW_ACHIEVEMENT = new Action<>("show_achievement", String.class, true, new Renderer() { + Action SHOW_ACHIEVEMENT = new HoverEventImpl.ActionImpl<>("show_achievement", String.class, true, new Renderer<>() { @Override public @NotNull String render(final @NotNull ComponentRenderer renderer, final @NotNull C context, final @NotNull String value) { return value; @@ -955,23 +635,7 @@ public static final class Action { * * @since 4.0.0 */ - public static final Index> NAMES = Index.create(constant -> constant.name, SHOW_TEXT, SHOW_ITEM, SHOW_ENTITY, SHOW_ACHIEVEMENT); - private final String name; - private final Class type; - /** - * If this action is readable. - * - *

When an action is not readable it will not be deserialized.

- */ - private final boolean readable; - private final Renderer renderer; - - Action(final String name, final Class type, final boolean readable, final Renderer renderer) { - this.name = name; - this.type = type; - this.readable = readable; - this.renderer = renderer; - } + Index> NAMES = Index.create(Action::toString, SHOW_TEXT, SHOW_ITEM, SHOW_ENTITY, SHOW_ACHIEVEMENT); /** * Gets the value type. @@ -979,25 +643,24 @@ public static final class Action { * @return the value type * @since 4.0.0 */ - public @NotNull Class type() { - return this.type; - } + @NotNull Class type(); /** * Tests if this action is readable. * * @return {@code true} if this action is readable, {@code false} if this - * action is not readable + * action is not readable * @since 4.0.0 */ - public boolean readable() { - return this.readable; - } + boolean readable(); - @Override - public @NotNull String toString() { - return this.name; - } + /** + * The renderer for this action. + * + * @return the renderer + * @since 5.0.0 + */ + @NotNull Renderer renderer(); /** * Type-specific renderer. @@ -1006,7 +669,18 @@ public boolean readable() { * @since 4.0.0 */ @FunctionalInterface + @ApiStatus.NonExtendable interface Renderer { + /** + * Renders a value. + * + * @param renderer the renderer + * @param context the context + * @param value the value + * @return the rendered value + * @param the type of the context + * @since 4.0.0 + */ @NotNull V render(final @NotNull ComponentRenderer renderer, final @NotNull C context, final @NotNull V value); } } diff --git a/api/src/main/java/net/kyori/adventure/text/event/HoverEventImpl.java b/api/src/main/java/net/kyori/adventure/text/event/HoverEventImpl.java new file mode 100644 index 000000000..12e09bbf1 --- /dev/null +++ b/api/src/main/java/net/kyori/adventure/text/event/HoverEventImpl.java @@ -0,0 +1,190 @@ +/* + * This file is part of adventure, licensed under the MIT License. + * + * Copyright (c) 2017-2025 KyoriPowered + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package net.kyori.adventure.text.event; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.function.UnaryOperator; +import java.util.stream.Stream; +import net.kyori.adventure.internal.Internals; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.api.BinaryTagHolder; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.renderer.ComponentRenderer; +import net.kyori.examination.ExaminableProperty; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Range; + +import static java.util.Objects.requireNonNull; + +record HoverEventImpl(Action action, V value) implements HoverEvent { + + public HoverEventImpl(final @NotNull Action action, final @NotNull V value) { + this.action = requireNonNull(action, "action"); + this.value = requireNonNull(value, "value"); + } + + @Override + public @NotNull HoverEvent value(final @NotNull V value) { + return new HoverEventImpl<>(this.action, value); + } + + /** + * Returns a hover event with the value rendered using {@code renderer} when possible. + * + * @param renderer the renderer + * @param context the render context + * @param the context type + * @return a hover event + * @since 4.0.0 + */ + @Override + public @NotNull HoverEvent withRenderedValue(final @NotNull ComponentRenderer renderer, final @NotNull C context) { + final V oldValue = this.value; + final V newValue = this.action.renderer().render(renderer, context, oldValue); + if (newValue != oldValue) return new HoverEventImpl<>(this.action, newValue); + return this; + } + + @Override + public @NotNull HoverEvent asHoverEvent() { + return this; // i already am a hover event! hehehehe + } + + @Override + public @NotNull HoverEvent asHoverEvent(final @NotNull UnaryOperator op) { + if (op == UnaryOperator.identity()) return this; // nothing to do, can return ourself + return new HoverEventImpl<>(this.action, op.apply(this.value)); + } + + @Override + public void styleApply(final Style.@NotNull Builder style) { + style.hoverEvent(this); + } + + @Override + public @NotNull String toString() { + return Internals.toString(this); + } + + record ShowItemImpl(Key item, int count, BinaryTagHolder nbt, Map dataComponents) implements ShowItem { + @Override + public @NotNull ShowItem item(final @NotNull Key item) { + if (requireNonNull(item, "item").equals(this.item)) return this; + return new ShowItemImpl(item, this.count, this.nbt, this.dataComponents); + } + + @Override + public @NotNull ShowItem count(final @Range(from = 0, to = Integer.MAX_VALUE) int count) { + if (count == this.count) return this; + return new ShowItemImpl(this.item, count, this.nbt, this.dataComponents); + } + + @Override + public @NotNull ShowItem nbt(final @Nullable BinaryTagHolder nbt) { + if (Objects.equals(nbt, this.nbt)) return this; + return new ShowItemImpl(this.item, this.count, nbt, Collections.emptyMap()); + } + + @Override + public @NotNull ShowItem dataComponents(final @NotNull Map holder) { + if (Objects.equals(this.dataComponents, holder)) return this; + return new ShowItemImpl(this.item, this.count, null, holder.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(new HashMap<>(holder))); + } + + @Override + public @NotNull Map dataComponentsAs(final @NotNull Class targetType) { + if (this.dataComponents.isEmpty()) { + return Collections.emptyMap(); + } else { + final Map results = new HashMap<>(this.dataComponents.size()); + for (final Map.Entry entry : this.dataComponents.entrySet()) { + results.put(entry.getKey(), DataComponentValueConverterRegistry.convert(targetType, entry.getKey(), entry.getValue())); + } + return Collections.unmodifiableMap(results); + } + } + + @Override + public @NotNull Stream examinableProperties() { + return Stream.of( + ExaminableProperty.of("item", this.item), + ExaminableProperty.of("count", this.count), + ExaminableProperty.of("nbt", this.nbt), + ExaminableProperty.of("dataComponents", this.dataComponents) + ); + } + + @Override + public @NotNull String toString() { + return Internals.toString(this); + } + } + + record ShowEntityImpl(Key type, UUID id, Component name) implements ShowEntity { + @Override + public @NotNull ShowEntity type(final @NotNull Key type) { + if (requireNonNull(type, "type").equals(this.type)) return this; + return new ShowEntityImpl(type, this.id, this.name); + } + + @Override + public @NotNull ShowEntity id(final @NotNull UUID id) { + if (requireNonNull(id).equals(this.id)) return this; + return new ShowEntityImpl(this.type, id, this.name); + } + + @Override + public @NotNull ShowEntity name(final @Nullable Component name) { + if (Objects.equals(name, this.name)) return this; + return new ShowEntityImpl(this.type, this.id, name); + } + + @Override + public @NotNull Stream examinableProperties() { + return Stream.of( + ExaminableProperty.of("type", this.type), + ExaminableProperty.of("id", this.id), + ExaminableProperty.of("name", this.name) + ); + } + + @Override + public @NotNull String toString() { + return Internals.toString(this); + } + } + + record ActionImpl(String name, Class type, boolean readable, Renderer renderer) implements Action { + @Override + public @NotNull String toString() { + return this.name; + } + } +} diff --git a/api/src/main/java/net/kyori/adventure/text/event/PayloadImpl.java b/api/src/main/java/net/kyori/adventure/text/event/PayloadImpl.java index 4d6b67970..5ff326f8f 100644 --- a/api/src/main/java/net/kyori/adventure/text/event/PayloadImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/event/PayloadImpl.java @@ -23,7 +23,6 @@ */ package net.kyori.adventure.text.event; -import java.util.Objects; import java.util.stream.Stream; import net.kyori.adventure.dialog.DialogLike; import net.kyori.adventure.internal.Internals; @@ -32,24 +31,11 @@ import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; -abstract class PayloadImpl implements ClickEvent.Payload { - @Override - public String toString() { - return Internals.toString(this); +final class PayloadImpl { + private PayloadImpl() { } - static final class TextImpl extends PayloadImpl implements ClickEvent.Payload.Text { - private final String value; - - TextImpl(final @NotNull String value) { - this.value = value; - } - - @Override - public @NotNull String value() { - return this.value; - } - + record TextImpl(String value) implements ClickEventImpl.Payload.Text { @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -58,31 +44,12 @@ static final class TextImpl extends PayloadImpl implements ClickEvent.Payload.Te } @Override - public boolean equals(final Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final TextImpl that = (TextImpl) other; - return Objects.equals(this.value, that.value); - } - - @Override - public int hashCode() { - return this.value.hashCode(); + public @NotNull String toString() { + return Internals.toString(this); } } - static final class IntImpl extends PayloadImpl implements ClickEvent.Payload.Int { - private final int integer; - - IntImpl(final int integer) { - this.integer = integer; - } - - @Override - public int integer() { - return this.integer; - } - + record IntImpl(int integer) implements ClickEventImpl.Payload.Int { @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -91,76 +58,26 @@ public int integer() { } @Override - public boolean equals(final Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final IntImpl that = (IntImpl) other; - return Objects.equals(this.integer, that.integer); - } - - @Override - public int hashCode() { - return this.integer; + public @NotNull String toString() { + return Internals.toString(this); } } - static final class DialogImpl extends PayloadImpl implements ClickEvent.Payload.Dialog { - private final DialogLike dialogLike; - - DialogImpl(final @NotNull DialogLike dialogLike) { - this.dialogLike = dialogLike; - } - - @Override - public @NotNull DialogLike dialog() { - return this.dialogLike; - } - + record DialogImpl(DialogLike dialog) implements ClickEventImpl.Payload.Dialog { @Override public @NotNull Stream examinableProperties() { return Stream.of( - ExaminableProperty.of("dialog", this.dialogLike) + ExaminableProperty.of("dialog", this.dialog) ); } @Override - public boolean equals(final Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final DialogImpl that = (DialogImpl) other; - return Objects.equals(this.dialogLike, that.dialogLike); - } - - @Override - public int hashCode() { - return this.dialogLike.hashCode(); + public @NotNull String toString() { + return Internals.toString(this); } } - static final class CustomImpl extends PayloadImpl implements ClickEvent.Payload.Custom { - private final Key key; - private final BinaryTagHolder nbt; - - CustomImpl(final @NotNull Key key, final @NotNull BinaryTagHolder nbt) { - this.key = key; - this.nbt = nbt; - } - - @Override - public @NotNull Key key() { - return this.key; - } - - @Override - public @NotNull String data() { - return this.nbt.string(); - } - - @Override - public @NotNull BinaryTagHolder nbt() { - return this.nbt; - } - + record CustomImpl(Key key, BinaryTagHolder nbt) implements ClickEventImpl.Payload.Custom { @Override public @NotNull Stream examinableProperties() { return Stream.of( @@ -170,18 +87,8 @@ static final class CustomImpl extends PayloadImpl implements ClickEvent.Payload. } @Override - public boolean equals(final Object other) { - if (this == other) return true; - if (other == null || getClass() != other.getClass()) return false; - final CustomImpl that = (CustomImpl) other; - return Objects.equals(this.key, that.key) && Objects.equals(this.nbt, that.nbt); - } - - @Override - public int hashCode() { - int result = this.key.hashCode(); - result = (31 * result) + this.nbt.hashCode(); - return result; + public @NotNull String toString() { + return Internals.toString(this); } } } diff --git a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java index c111706b2..94d96b7f8 100644 --- a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java +++ b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattener.java @@ -37,7 +37,7 @@ * * @since 4.7.0 */ -public interface ComponentFlattener extends Buildable { +public sealed interface ComponentFlattener permits ComponentFlattenerImpl { /** * A constant representing a flattener with no limit on nested flatten calls. * @@ -96,7 +96,7 @@ public interface ComponentFlattener extends Buildable, Buildable.Builder { + sealed interface Builder extends AbstractBuilder permits ComponentFlattenerImpl.BuilderImpl { /** * Register a type of component to be handled. * diff --git a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java index 9826797e2..bfe9a07c8 100644 --- a/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/flattener/ComponentFlattenerImpl.java @@ -34,7 +34,6 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.KeybindComponent; import net.kyori.adventure.text.ObjectComponent; -import net.kyori.adventure.text.ScoreComponent; import net.kyori.adventure.text.SelectorComponent; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; @@ -49,15 +48,10 @@ import static java.util.Objects.requireNonNull; -final class ComponentFlattenerImpl implements ComponentFlattener { +record ComponentFlattenerImpl(InheritanceAwareMap flatteners, Function unknownHandler, int maxNestedDepth) implements ComponentFlattener { @SuppressWarnings("deprecation") static final ComponentFlattener BASIC = new BuilderImpl() .mapper(KeybindComponent.class, component -> component.keybind()) // IntelliJ is wrong here, this is fine - .mapper(ScoreComponent.class, component -> { - // Removed in Vanilla 1.16, but we keep it for backwards compat - final @Nullable String value = component.value(); - return value != null ? value : ""; - }) .mapper(SelectorComponent.class, SelectorComponent::pattern) .mapper(TextComponent.class, TextComponent::content) .mapper(TranslatableComponent.class, component -> { @@ -66,15 +60,11 @@ final class ComponentFlattenerImpl implements ComponentFlattener { }) .mapper(ObjectComponent.class, component -> { final ObjectContents contents = component.contents(); - if (contents instanceof SpriteObjectContents) { - final SpriteObjectContents spriteContents = (SpriteObjectContents) contents; + if (contents instanceof final SpriteObjectContents spriteContents) { final Key atlas = spriteContents.atlas(); - return "[" + spriteContents.sprite().asMinimalString() - + (!atlas.equals(SpriteObjectContents.DEFAULT_ATLAS) ? "@" + atlas.asMinimalString() : "") - + "]"; - } else if (contents instanceof PlayerHeadObjectContents) { - final PlayerHeadObjectContents playerHeadContents = (PlayerHeadObjectContents) contents; - return "[" + (playerHeadContents.name() != null ? playerHeadContents.name() : "unknown player") + " head]"; + return String.format("[%s:%s]", spriteContents.sprite().asMinimalString(), !atlas.equals(SpriteObjectContents.DEFAULT_ATLAS) ? "@" + atlas.asMinimalString() : ""); + } else if (contents instanceof final PlayerHeadObjectContents playerHeadContents) { + return String.format("[%s head]", playerHeadContents.name() != null ? playerHeadContents.name() : "unknown player"); } return ""; }) @@ -86,26 +76,7 @@ final class ComponentFlattenerImpl implements ComponentFlattener { private static final int MAX_DEPTH = 512; - private final InheritanceAwareMap flatteners; - private final Function unknownHandler; - private final int maxNestedDepth; - - ComponentFlattenerImpl(final InheritanceAwareMap flatteners, final @Nullable Function unknownHandler, final int maxNestedDepth) { - this.flatteners = flatteners; - this.unknownHandler = unknownHandler; - this.maxNestedDepth = maxNestedDepth; - } - - private static final class StackEntry { - final Component component; - final int depth; - final int stylesToPop; - - StackEntry(final Component component, final int depth, final int stylesToPop) { - this.component = component; - this.depth = depth; - this.stylesToPop = stylesToPop; - } + private record StackEntry(Component component, int depth, int stylesToPop) { } @Override @@ -185,11 +156,6 @@ private void flatten0(final @NotNull Component input, final @NotNull FlattenerLi } } - @Override - public ComponentFlattener.@NotNull Builder toBuilder() { - return new BuilderImpl(this.flatteners, this.unknownHandler, this.maxNestedDepth); - } - // A function that allows nesting other flatten operations @FunctionalInterface interface Handler { @@ -218,20 +184,20 @@ static final class BuilderImpl implements Builder { @Override @SuppressWarnings("unchecked") - public ComponentFlattener.@NotNull Builder mapper(final @NotNull Class type, final @NotNull Function converter) { + public @NotNull Builder mapper(final @NotNull Class type, final @NotNull Function converter) { this.flatteners.put(type, (self, component, listener, depth, nestedDepth) -> listener.component(converter.apply((T) component))); return this; } @Override @SuppressWarnings("unchecked") - public ComponentFlattener.@NotNull Builder complexMapper(final @NotNull Class type, final @NotNull BiConsumer> converter) { + public @NotNull Builder complexMapper(final @NotNull Class type, final @NotNull BiConsumer> converter) { this.flatteners.put(type, (self, component, listener, depth, nestedDepth) -> converter.accept((T) component, c -> self.flatten0(c, listener, depth, nestedDepth + 1))); return this; } @Override - public ComponentFlattener.@NotNull Builder unknownMapper(final @Nullable Function converter) { + public @NotNull Builder unknownMapper(final @Nullable Function converter) { this.unknownHandler = converter; return this; } diff --git a/api/src/main/java/net/kyori/adventure/text/format/DecorationMap.java b/api/src/main/java/net/kyori/adventure/text/format/DecorationMap.java index 92080652a..4acd6e883 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/DecorationMap.java +++ b/api/src/main/java/net/kyori/adventure/text/format/DecorationMap.java @@ -141,8 +141,8 @@ private DecorationMap(final int bitSet) { @Override public TextDecoration.State get(final Object o) { - if (o instanceof TextDecoration) { - return STATES[(this.bitSet >> (((TextDecoration) o).ordinal() * 2)) & 0b11]; + if (o instanceof final TextDecoration textDecoration) { + return STATES[(this.bitSet >> (textDecoration.ordinal() * 2)) & 0b11]; } return null; } @@ -209,7 +209,7 @@ public int hashCode() { final class EntrySet extends AbstractSet> { @Override public @NotNull Iterator> iterator() { - return new Iterator>() { + return new Iterator<>() { private final Iterator decorations = KEY_SET.iterator(); private final Iterator states = DecorationMap.this.values().iterator(); diff --git a/api/src/main/java/net/kyori/adventure/text/format/MutableStyleSetter.java b/api/src/main/java/net/kyori/adventure/text/format/MutableStyleSetter.java index e1e4024df..8f8345cd3 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/MutableStyleSetter.java +++ b/api/src/main/java/net/kyori/adventure/text/format/MutableStyleSetter.java @@ -53,8 +53,8 @@ public interface MutableStyleSetter> extends Sty @Contract("_ -> this") @SuppressWarnings("unchecked") default @NotNull T decorate(final @NotNull TextDecoration@NotNull... decorations) { - for (int i = 0, length = decorations.length; i < length; i++) { - this.decorate(decorations[i]); + for (final TextDecoration decoration : decorations) { + this.decorate(decoration); } return (T) this; } diff --git a/api/src/main/java/net/kyori/adventure/text/format/NamedTextColor.java b/api/src/main/java/net/kyori/adventure/text/format/NamedTextColor.java index 4d09ec12e..af697c94f 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/NamedTextColor.java +++ b/api/src/main/java/net/kyori/adventure/text/format/NamedTextColor.java @@ -23,14 +23,7 @@ */ package net.kyori.adventure.text.format; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Stream; -import net.kyori.adventure.util.HSVLike; import net.kyori.adventure.util.Index; -import net.kyori.examination.ExaminableProperty; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,128 +32,109 @@ * * @since 4.0.0 */ -public final class NamedTextColor implements TextColor { - private static final int BLACK_VALUE = 0x000000; - private static final int DARK_BLUE_VALUE = 0x0000aa; - private static final int DARK_GREEN_VALUE = 0x00aa00; - private static final int DARK_AQUA_VALUE = 0x00aaaa; - private static final int DARK_RED_VALUE = 0xaa0000; - private static final int DARK_PURPLE_VALUE = 0xaa00aa; - private static final int GOLD_VALUE = 0xffaa00; - private static final int GRAY_VALUE = 0xaaaaaa; - private static final int DARK_GRAY_VALUE = 0x555555; - private static final int BLUE_VALUE = 0x5555ff; - private static final int GREEN_VALUE = 0x55ff55; - private static final int AQUA_VALUE = 0x55ffff; - private static final int RED_VALUE = 0xff5555; - private static final int LIGHT_PURPLE_VALUE = 0xff55ff; - private static final int YELLOW_VALUE = 0xffff55; - private static final int WHITE_VALUE = 0xffffff; - +public sealed interface NamedTextColor extends TextColor permits NamedTextColorImpl { /** * The standard {@code black} colour. * * @since 4.0.0 */ - public static final NamedTextColor BLACK = new NamedTextColor("black", BLACK_VALUE); + NamedTextColor BLACK = new NamedTextColorImpl("black", NamedTextColorImpl.BLACK_VALUE); /** * The standard {@code dark_blue} colour. * * @since 4.0.0 */ - public static final NamedTextColor DARK_BLUE = new NamedTextColor("dark_blue", DARK_BLUE_VALUE); + NamedTextColor DARK_BLUE = new NamedTextColorImpl("dark_blue", NamedTextColorImpl.DARK_BLUE_VALUE); /** * The standard {@code dark_green} colour. * * @since 4.0.0 */ - public static final NamedTextColor DARK_GREEN = new NamedTextColor("dark_green", DARK_GREEN_VALUE); + NamedTextColor DARK_GREEN = new NamedTextColorImpl("dark_green", NamedTextColorImpl.DARK_GREEN_VALUE); /** * The standard {@code dark_aqua} colour. * * @since 4.0.0 */ - public static final NamedTextColor DARK_AQUA = new NamedTextColor("dark_aqua", DARK_AQUA_VALUE); + NamedTextColor DARK_AQUA = new NamedTextColorImpl("dark_aqua", NamedTextColorImpl.DARK_AQUA_VALUE); /** * The standard {@code dark_red} colour. * * @since 4.0.0 */ - public static final NamedTextColor DARK_RED = new NamedTextColor("dark_red", DARK_RED_VALUE); + NamedTextColor DARK_RED = new NamedTextColorImpl("dark_red", NamedTextColorImpl.DARK_RED_VALUE); /** * The standard {@code dark_purple} colour. * * @since 4.0.0 */ - public static final NamedTextColor DARK_PURPLE = new NamedTextColor("dark_purple", DARK_PURPLE_VALUE); + NamedTextColor DARK_PURPLE = new NamedTextColorImpl("dark_purple", NamedTextColorImpl.DARK_PURPLE_VALUE); /** * The standard {@code gold} colour. * * @since 4.0.0 */ - public static final NamedTextColor GOLD = new NamedTextColor("gold", GOLD_VALUE); + NamedTextColor GOLD = new NamedTextColorImpl("gold", NamedTextColorImpl.GOLD_VALUE); /** * The standard {@code gray} colour. * * @since 4.0.0 */ - public static final NamedTextColor GRAY = new NamedTextColor("gray", GRAY_VALUE); + NamedTextColor GRAY = new NamedTextColorImpl("gray", NamedTextColorImpl.GRAY_VALUE); /** * The standard {@code dark_gray} colour. * * @since 4.0.0 */ - public static final NamedTextColor DARK_GRAY = new NamedTextColor("dark_gray", DARK_GRAY_VALUE); + NamedTextColor DARK_GRAY = new NamedTextColorImpl("dark_gray", NamedTextColorImpl.DARK_GRAY_VALUE); /** * The standard {@code blue} colour. * * @since 4.0.0 */ - public static final NamedTextColor BLUE = new NamedTextColor("blue", BLUE_VALUE); + NamedTextColor BLUE = new NamedTextColorImpl("blue", NamedTextColorImpl.BLUE_VALUE); /** * The standard {@code green} colour. * * @since 4.0.0 */ - public static final NamedTextColor GREEN = new NamedTextColor("green", GREEN_VALUE); + NamedTextColor GREEN = new NamedTextColorImpl("green", NamedTextColorImpl.GREEN_VALUE); /** * The standard {@code aqua} colour. * * @since 4.0.0 */ - public static final NamedTextColor AQUA = new NamedTextColor("aqua", AQUA_VALUE); + NamedTextColor AQUA = new NamedTextColorImpl("aqua", NamedTextColorImpl.AQUA_VALUE); /** * The standard {@code red} colour. * * @since 4.0.0 */ - public static final NamedTextColor RED = new NamedTextColor("red", RED_VALUE); + NamedTextColor RED = new NamedTextColorImpl("red", NamedTextColorImpl.RED_VALUE); /** * The standard {@code light_purple} colour. * * @since 4.0.0 */ - public static final NamedTextColor LIGHT_PURPLE = new NamedTextColor("light_purple", LIGHT_PURPLE_VALUE); + NamedTextColor LIGHT_PURPLE = new NamedTextColorImpl("light_purple", NamedTextColorImpl.LIGHT_PURPLE_VALUE); /** * The standard {@code yellow} colour. * * @since 4.0.0 */ - public static final NamedTextColor YELLOW = new NamedTextColor("yellow", YELLOW_VALUE); + NamedTextColor YELLOW = new NamedTextColorImpl("yellow", NamedTextColorImpl.YELLOW_VALUE); /** * The standard {@code white} colour. * * @since 4.0.0 */ - public static final NamedTextColor WHITE = new NamedTextColor("white", WHITE_VALUE); - - private static final List VALUES = Collections.unmodifiableList(Arrays.asList(BLACK, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED, DARK_PURPLE, GOLD, GRAY, DARK_GRAY, BLUE, GREEN, AQUA, RED, LIGHT_PURPLE, YELLOW, WHITE)); + NamedTextColor WHITE = new NamedTextColorImpl("white", NamedTextColorImpl.WHITE_VALUE); /** * An index of name to color. * * @since 4.0.0 */ - public static final Index NAMES = Index.create(constant -> constant.name, VALUES); + Index NAMES = Index.create(NamedTextColor::toString, NamedTextColorImpl.VALUES); /** * Gets the named color exactly matching the provided color. @@ -169,58 +143,26 @@ public final class NamedTextColor implements TextColor { * @return the matched color, or null * @since 4.10.0 */ - public static @Nullable NamedTextColor namedColor(final int value) { - switch (value) { - case BLACK_VALUE: return BLACK; - case DARK_BLUE_VALUE: return DARK_BLUE; - case DARK_GREEN_VALUE: return DARK_GREEN; - case DARK_AQUA_VALUE: return DARK_AQUA; - case DARK_RED_VALUE: return DARK_RED; - case DARK_PURPLE_VALUE: return DARK_PURPLE; - case GOLD_VALUE: return GOLD; - case GRAY_VALUE: return GRAY; - case DARK_GRAY_VALUE: return DARK_GRAY; - case BLUE_VALUE: return BLUE; - case GREEN_VALUE: return GREEN; - case AQUA_VALUE: return AQUA; - case RED_VALUE: return RED; - case LIGHT_PURPLE_VALUE: return LIGHT_PURPLE; - case YELLOW_VALUE: return YELLOW; - case WHITE_VALUE: return WHITE; - default: return null; - } - } - - /** - * Gets the named color exactly matching the provided color. - * - * @param value the color to match - * @return the matched color, or null - * @since 4.0.0 - * @deprecated for removal since 4.10.0, use {@link #namedColor(int)} instead - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "5.0.0") - public static @Nullable NamedTextColor ofExact(final int value) { - switch (value) { - case BLACK_VALUE: return BLACK; - case DARK_BLUE_VALUE: return DARK_BLUE; - case DARK_GREEN_VALUE: return DARK_GREEN; - case DARK_AQUA_VALUE: return DARK_AQUA; - case DARK_RED_VALUE: return DARK_RED; - case DARK_PURPLE_VALUE: return DARK_PURPLE; - case GOLD_VALUE: return GOLD; - case GRAY_VALUE: return GRAY; - case DARK_GRAY_VALUE: return DARK_GRAY; - case BLUE_VALUE: return BLUE; - case GREEN_VALUE: return GREEN; - case AQUA_VALUE: return AQUA; - case RED_VALUE: return RED; - case LIGHT_PURPLE_VALUE: return LIGHT_PURPLE; - case YELLOW_VALUE: return YELLOW; - case WHITE_VALUE: return WHITE; - default: return null; - } + static @Nullable NamedTextColor namedColor(int value) { + return switch (value) { + case NamedTextColorImpl.BLACK_VALUE -> BLACK; + case NamedTextColorImpl.DARK_BLUE_VALUE -> DARK_BLUE; + case NamedTextColorImpl.DARK_GREEN_VALUE -> DARK_GREEN; + case NamedTextColorImpl.DARK_AQUA_VALUE -> DARK_AQUA; + case NamedTextColorImpl.DARK_RED_VALUE -> DARK_RED; + case NamedTextColorImpl.DARK_PURPLE_VALUE -> DARK_PURPLE; + case NamedTextColorImpl.GOLD_VALUE -> GOLD; + case NamedTextColorImpl.GRAY_VALUE -> GRAY; + case NamedTextColorImpl.DARK_GRAY_VALUE -> DARK_GRAY; + case NamedTextColorImpl.BLUE_VALUE -> BLUE; + case NamedTextColorImpl.GREEN_VALUE -> GREEN; + case NamedTextColorImpl.AQUA_VALUE -> AQUA; + case NamedTextColorImpl.RED_VALUE -> RED; + case NamedTextColorImpl.LIGHT_PURPLE_VALUE -> LIGHT_PURPLE; + case NamedTextColorImpl.YELLOW_VALUE -> YELLOW; + case NamedTextColorImpl.WHITE_VALUE -> WHITE; + default -> null; + }; } /** @@ -230,44 +172,8 @@ public final class NamedTextColor implements TextColor { * @return nearest named colour. will always return a value * @since 4.0.0 */ - public static @NotNull NamedTextColor nearestTo(final @NotNull TextColor any) { - if (any instanceof NamedTextColor) { - return (NamedTextColor) any; - } - - return TextColor.nearestColorTo(VALUES, any); - } - - private final String name; - private final int value; - private final HSVLike hsv; - - private NamedTextColor(final String name, final int value) { - this.name = name; - this.value = value; - this.hsv = HSVLike.fromRGB(this.red(), this.green(), this.blue()); - } - - @Override - public int value() { - return this.value; - } - - @Override - public @NotNull HSVLike asHSV() { - return this.hsv; - } - - @Override - public @NotNull String toString() { - return this.name; - } - - @Override - public @NotNull Stream examinableProperties() { - return Stream.concat( - Stream.of(ExaminableProperty.of("name", this.name)), - TextColor.super.examinableProperties() - ); + static @NotNull NamedTextColor nearestTo(final @NotNull TextColor any) { + if (any instanceof final NamedTextColor namedTextColor) return namedTextColor; + return TextColor.nearestColorTo(NamedTextColorImpl.VALUES, any); } } diff --git a/api/src/main/java/net/kyori/adventure/text/format/NamedTextColorImpl.java b/api/src/main/java/net/kyori/adventure/text/format/NamedTextColorImpl.java new file mode 100644 index 000000000..05a9c65c3 --- /dev/null +++ b/api/src/main/java/net/kyori/adventure/text/format/NamedTextColorImpl.java @@ -0,0 +1,66 @@ +/* + * This file is part of adventure, licensed under the MIT License. + * + * Copyright (c) 2017-2025 KyoriPowered + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package net.kyori.adventure.text.format; + +import java.util.List; +import java.util.stream.Stream; +import net.kyori.adventure.util.HSVLike; +import net.kyori.examination.ExaminableProperty; +import org.jetbrains.annotations.NotNull; + +public record NamedTextColorImpl(String name, int value) implements NamedTextColor { + static final int BLACK_VALUE = 0x000000; + static final int DARK_BLUE_VALUE = 0x0000aa; + static final int DARK_GREEN_VALUE = 0x00aa00; + static final int DARK_AQUA_VALUE = 0x00aaaa; + static final int DARK_RED_VALUE = 0xaa0000; + static final int DARK_PURPLE_VALUE = 0xaa00aa; + static final int GOLD_VALUE = 0xffaa00; + static final int GRAY_VALUE = 0xaaaaaa; + static final int DARK_GRAY_VALUE = 0x555555; + static final int BLUE_VALUE = 0x5555ff; + static final int GREEN_VALUE = 0x55ff55; + static final int AQUA_VALUE = 0x55ffff; + static final int RED_VALUE = 0xff5555; + static final int LIGHT_PURPLE_VALUE = 0xff55ff; + static final int YELLOW_VALUE = 0xffff55; + static final int WHITE_VALUE = 0xffffff; + + static final List VALUES = List.of(BLACK, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED, DARK_PURPLE, GOLD, GRAY, DARK_GRAY, BLUE, GREEN, AQUA, RED, LIGHT_PURPLE, YELLOW, WHITE); + + @Override + public @NotNull HSVLike asHSV() { + return HSVLike.fromRGB(this.red(), this.green(), this.blue()); + } + + @Override + public @NotNull String toString() { + return this.name; + } + + @Override + public @NotNull Stream examinableProperties() { + return Stream.of(ExaminableProperty.of("name", this.name)); + } +} diff --git a/api/src/main/java/net/kyori/adventure/text/format/ShadowColor.java b/api/src/main/java/net/kyori/adventure/text/format/ShadowColor.java index e656fca9d..98e6a5298 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/ShadowColor.java +++ b/api/src/main/java/net/kyori/adventure/text/format/ShadowColor.java @@ -118,8 +118,7 @@ public interface ShadowColor extends StyleBuilderApplicable, ARGBLike { | (green & 0xff) << 8 | (blue & 0xff); - if (value == ShadowColorImpl.NONE_VALUE) return none(); - return new ShadowColorImpl(value); + return shadowColor(value); } /** diff --git a/api/src/main/java/net/kyori/adventure/text/format/ShadowColorImpl.java b/api/src/main/java/net/kyori/adventure/text/format/ShadowColorImpl.java index 0bce5b54c..375b0585f 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/ShadowColorImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/format/ShadowColorImpl.java @@ -28,37 +28,16 @@ import net.kyori.examination.Examinable; import net.kyori.examination.ExaminableProperty; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -final class ShadowColorImpl implements ShadowColor, Examinable { +/** + * @param value ARGB + */ +record ShadowColorImpl(int value) implements ShadowColor, Examinable { static final int NONE_VALUE = 0; static final ShadowColorImpl NONE = new ShadowColorImpl(NONE_VALUE); - private final int value; // ARGB - - ShadowColorImpl(final int value) { - this.value = value; - } - - @Override - public int value() { - return this.value; - } - - @Override - public boolean equals(final @Nullable Object other) { - if (!(other instanceof ShadowColorImpl)) return false; - final ShadowColorImpl that = (ShadowColorImpl) other; - return this.value == that.value; - } - - @Override - public int hashCode() { - return Integer.hashCode(this.value); - } - @Override - public String toString() { + public @NotNull String toString() { return Internals.toString(this); } diff --git a/api/src/main/java/net/kyori/adventure/text/format/Style.java b/api/src/main/java/net/kyori/adventure/text/format/Style.java index 3b22c90ae..41f728988 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/Style.java +++ b/api/src/main/java/net/kyori/adventure/text/format/Style.java @@ -36,7 +36,6 @@ import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.util.MonkeyBars; import net.kyori.examination.Examinable; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,8 +58,7 @@ * * @since 4.0.0 */ -@ApiStatus.NonExtendable -public interface Style extends Buildable, Examinable, StyleGetter, StyleSetter