diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index da77ba3b3..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,36 +0,0 @@ -stages: - - build - - publish - -variables: - GRADLE_USER_HOME: "$CI_PROJECT_DIR/.gradle" - MAVEN_USER_SETTINGS: "$CI_PROJECT_DIR/maven-settings.xml" - -cache: - paths: - - .gradle/caches - - .gradle/caches/** - -before_script: - - export GRADLE_USER_HOME=`pwd`/.gradle - - export GRADLE_OPTS="-Dorg.gradle.daemon=false -Dorg.gradle.parallel=false" - - mkdir -p ~/.m2 - - echo "$MAVEN_SETTINGS_XML" > ~/.m2/settings.xml - -build: - stage: build - image: gradle:latest - script: - - gradle clean shadowJar - - echo "Gefundene Artefakte:" - - find . -type f -path "**/build/libs/*.jar" ! -path "**/.gradle/**" -exec ls -lh {} \; - -publish: - stage: publish - image: gradle:latest - script: - - gradle publish - dependencies: - - build - rules: - - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 89bed798a..5649faae2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,17 @@ +import dev.slne.surf.api.generator.nms.NmsVersion import org.jetbrains.kotlin.gradle.dsl.KotlinJvmExtension plugins { - id("io.papermc.paperweight.userdev") version "2.0.0-beta.20" apply false + id("io.papermc.paperweight.userdev") version "2.0.0-beta.21" apply false + id("dev.slne.surf.api.generator.nms-module-generator") } +nmsGenerator { + referenceVersion = NmsVersion.V1_21_11 + targetVersion = NmsVersion.V26_1 +} + + allprojects { repositories { mavenCentral() diff --git a/gradle.properties b/gradle.properties index f30e17d9a..06832df4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,6 +7,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled javaVersion=25 mcVersion=26.1.1 group=dev.slne.surf.api -version=3.0.10 +version=3.1.0 relocationPrefix=dev.slne.surf.api.libs snapshot=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4b7594449..0cbc1223a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ packetevents-plugin = "2.11.2" commandapi = "11.2.0" # LuckPerms -luckperms = "v5.5.0-bukkit" +luckperms = "5.4" # Scoreboard Library scoreboard-library = "2.7.3" @@ -151,6 +151,7 @@ flogger-slf4j-backend = { module = "com.google.flogger:flogger-slf4j-backend", v aide-reflection = { module = "tech.hiddenproject:aide-reflection", version.ref = "aide-reflection" } glm = { module = "io.github.kotlin-graphics:glm", version.ref = "glm" } datafixerupper = { module = "com.mojang:datafixerupper", version.ref = "datafixerupper" } +luckperms = { module = "net.luckperms:api", version.ref = "luckperms" } auto-service-annotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "auto-service" } auto-service = { module = "dev.zacsweers.autoservice:auto-service-ksp", version.ref = "auto-service-ksp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 5ee117d36..cca86ba88 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,6 +3,7 @@ pluginManagement { mavenLocal() gradlePluginPortal() } + includeBuild("surf-api-generator/gradle-nms-module-generator") } plugins { @@ -17,6 +18,9 @@ include(":surf-api-core:surf-api-core") include(":surf-api-core:surf-api-core-server") include(":surf-api-paper:surf-api-paper") +include(":surf-api-paper:surf-api-paper-nms:surf-api-paper-nms-common") +include(":surf-api-paper:surf-api-paper-nms:surf-api-paper-nms-v1-21-11") +include(":surf-api-paper:surf-api-paper-nms:surf-api-paper-nms-v26-1") include(":surf-api-paper:surf-api-paper-server") include(":surf-api-velocity:surf-api-velocity") diff --git a/surf-api-core/surf-api-core/api/surf-api-core.api b/surf-api-core/surf-api-core/api/surf-api-core.api index 6cb773d78..3d97d7481 100644 --- a/surf-api-core/surf-api-core/api/surf-api-core.api +++ b/surf-api-core/surf-api-core/api/surf-api-core.api @@ -6628,6 +6628,21 @@ public final class dev/slne/surf/api/core/invoker/SuspendInvokerSupport { public static synthetic fun invokeSuspendDirect$default (Ljava/lang/invoke/MethodHandle;Ljava/lang/Object;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } +public final class dev/slne/surf/api/core/luckperms/LuckPermsAccess { + public static final field INSTANCE Ldev/slne/surf/api/core/luckperms/LuckPermsAccess; + public final fun getLuckperms ()Lnet/luckperms/api/LuckPerms; + public final fun getUser (Ljava/util/UUID;)Lnet/luckperms/api/model/user/User; + public final fun loadUser (Ljava/util/UUID;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class dev/slne/surf/api/core/luckperms/LuckPermsAccessKt { + public static final fun getLuckPermsUser (Lnet/kyori/adventure/audience/Audience;)Lnet/luckperms/api/model/user/User; + public static final fun getLuckPermsUserOrNull (Lnet/kyori/adventure/audience/Audience;)Lnet/luckperms/api/model/user/User; + public static final fun getPrefix (Lnet/luckperms/api/model/user/User;)Ljava/lang/String; + public static final fun getSuffix (Lnet/luckperms/api/model/user/User;)Ljava/lang/String; + public static final fun getWeight (Lnet/luckperms/api/model/user/User;)Ljava/lang/Object; +} + public final class dev/slne/surf/api/core/math/VoxelLineTracer { public static final field INSTANCE Ldev/slne/surf/api/core/math/VoxelLineTracer; public final fun trace (Lorg/spongepowered/math/vector/Vector3d;Lorg/spongepowered/math/vector/Vector3d;)Lkotlin/sequences/Sequence; diff --git a/surf-api-core/surf-api-core/build.gradle.kts b/surf-api-core/surf-api-core/build.gradle.kts index 41b104fb7..961052634 100644 --- a/surf-api-core/surf-api-core/build.gradle.kts +++ b/surf-api-core/surf-api-core/build.gradle.kts @@ -6,6 +6,7 @@ plugins { dependencies { api(projects.surfApiShared.surfApiSharedPublic) api(libs.adventure.nbt) + compileOnlyApi(libs.luckperms) compileOnlyApi(libs.packetevents.api) compileOnlyApi(libs.dazzleconf) compileOnlyApi(libs.spongepowered.math) diff --git a/surf-api-core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/luckperms/LuckPermsAccess.kt b/surf-api-core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/luckperms/LuckPermsAccess.kt new file mode 100644 index 000000000..260ad924e --- /dev/null +++ b/surf-api-core/surf-api-core/src/main/kotlin/dev/slne/surf/api/core/luckperms/LuckPermsAccess.kt @@ -0,0 +1,46 @@ +package dev.slne.surf.api.core.luckperms + +import dev.slne.surf.api.core.messages.adventure.uuidOrNull +import kotlinx.coroutines.future.await +import net.kyori.adventure.audience.Audience +import net.luckperms.api.LuckPermsProvider +import net.luckperms.api.model.user.User +import net.luckperms.api.node.NodeType +import java.util.* + +object LuckPermsAccess { + val luckperms get() = LuckPermsProvider.get() + + fun getUser(uuid: UUID) = luckperms.userManager.getUser(uuid) + suspend fun loadUser(uuid: UUID): User = luckperms.userManager.loadUser(uuid).await() +} + +val User.prefix: String + get() = this.cachedData.metaData.prefix ?: "" +val User.suffix: String + get() = this.cachedData.metaData.suffix ?: "" + +val User.weight + get() = LuckPermsAccess.luckperms.groupManager.getGroup(this.primaryGroup)?.weight ?: 0 + +inline fun User.getMeta(key: String): T? { + val value = this.resolveInheritedNodes(NodeType.META, this.queryOptions) + .find { it.metaKey == key } + ?.metaValue + + return value as? T +} + +inline fun User.getMeta(key: String, default: T): T { + val value = this.resolveInheritedNodes(NodeType.META, this.queryOptions) + .find { it.metaKey == key } + ?.metaValue + + return value as? T ?: default +} + + +fun Audience.getLuckPermsUser(): User = this.getLuckPermsUserOrNull() + ?: error("Audience does not have a valid UUID or LuckPerms user could not be found.") + +fun Audience.getLuckPermsUserOrNull(): User? = this.uuidOrNull()?.let { LuckPermsAccess.getUser(it) } \ No newline at end of file diff --git a/surf-api-generator/build.gradle.kts b/surf-api-generator/build.gradle.kts index 182a80282..a0e1ef887 100644 --- a/surf-api-generator/build.gradle.kts +++ b/surf-api-generator/build.gradle.kts @@ -106,6 +106,8 @@ tasks.register("generate") { } + + private fun String.downloadTo(output: Path) { uri(this).toURL().openStream() .use { Files.copy(it, output, StandardCopyOption.REPLACE_EXISTING) } diff --git a/surf-api-generator/gradle-nms-module-generator/build.gradle.kts b/surf-api-generator/gradle-nms-module-generator/build.gradle.kts new file mode 100644 index 000000000..f2655ca68 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() +} + +gradlePlugin { + plugins { + create("nms-module-generator") { + id = "dev.slne.surf.api.generator.nms-module-generator" + implementationClass = "dev.slne.surf.api.generator.nms.GenerateNmsModulePlugin" + } + } +} \ No newline at end of file diff --git a/surf-api-generator/gradle-nms-module-generator/settings.gradle.kts b/surf-api-generator/gradle-nms-module-generator/settings.gradle.kts new file mode 100644 index 000000000..bfce74418 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "gradle-nms-module-generator" + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/GenerateNmsModulePlugin.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/GenerateNmsModulePlugin.kt new file mode 100644 index 000000000..166b5c961 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/GenerateNmsModulePlugin.kt @@ -0,0 +1,44 @@ +package dev.slne.surf.api.generator.nms + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.register + +/** + * Gradle plugin that registers the `nmsGenerator` extension and the + * `generateNmsModule` task. + * + * Apply the plugin and configure it in `build.gradle.kts`: + * + * ```kotlin + * plugins { + * id("dev.slne.surf.api.generator.nms-module-generator") + * } + * + * nmsGenerator { + * referenceVersion = NmsVersion.V26_1 + * targetVersion = NmsVersion.V1_21_11 + * + * transformations { + * renameClass("net.minecraft.resources.Identifier", + * "net.minecraft.resources.ResourceLocation") + * removeImport("net.minecraft.world.item.component.TypedEntityData") + * replaceCode("TypedEntityData.decodeEntity(nbt)", "CustomData.of(nbt)") + * } + * } + * ``` + * + * Then run: + * ``` + * ./gradlew generateNmsModule # interactive — asks before overwriting + * ./gradlew generateNmsModule -PforceOverwrite # non-interactive + * ``` + */ +abstract class GenerateNmsModulePlugin : Plugin { + override fun apply(target: Project) { + target.extensions.create("nmsGenerator") + target.tasks.register("generateNmsModule") + } +} + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/GenerateNmsModuleTask.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/GenerateNmsModuleTask.kt new file mode 100644 index 000000000..962d0e6a3 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/GenerateNmsModuleTask.kt @@ -0,0 +1,87 @@ +package dev.slne.surf.api.generator.nms + +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.tasks.TaskAction +import java.nio.file.Path +import kotlin.io.path.exists + +/** + * Generates a single NMS module from the configured reference version. + * + * If the target module already contains sources the task asks for + * confirmation before overwriting. Pass `-PforceOverwrite` to skip + * the prompt (useful in scripts or CI). + */ +abstract class GenerateNmsModuleTask : DefaultTask() { + + init { + group = "generation" + description = "Generates an NMS module from the reference version sources" + } + + @TaskAction + fun generate() { + val ext = project.extensions.getByType(NmsGeneratorExtension::class.java) + + check(ext.isConfigured) { + "nmsGenerator.referenceVersion and nmsGenerator.targetVersion must be set" + } + + val reference = ext.referenceVersion + val target = ext.targetVersion + val repoRoot = project.rootProject.projectDir.toPath() + + confirmOverwriteIfNeeded(repoRoot, target) + + logger.lifecycle("Generating NMS module: {} -> {} ...", reference.name, target.name) + + val generated = NmsModuleGenerator( + reference = reference, + target = target, + transformations = ext.transformationScope.transformations, + repoRoot = repoRoot, + logger = logger, + ).generate() + + logger.lifecycle("") + logger.lifecycle("------------------------------------------") + logger.lifecycle("Generation complete - {} file(s) written.", generated) + logger.lifecycle("") + logger.lifecycle("Next steps:") + logger.lifecycle(" 1. Add include(\"{}\") to settings.gradle.kts (if not present).", target.gradlePath) + logger.lifecycle(" 2. Register {} in the runtime NmsVersion enum.", target.name) + logger.lifecycle(" 3. Review the generated sources and fix remaining compilation errors.") + logger.lifecycle("------------------------------------------") + } + + // ------------------------------------------------------------------ // + + private fun confirmOverwriteIfNeeded(repoRoot: Path, target: NmsVersion) { + val targetSources = repoRoot + .resolve(target.modulePath) + .resolve("src/main/kotlin") + + if (!targetSources.exists()) return + + // Allow skipping the prompt via project property + if (project.hasProperty("forceOverwrite")) return + + val console = System.console() ?: throw GradleException( + "Target module ${target.name} already exists. " + + "Pass -PforceOverwrite to overwrite." + ) + + console.printf( + "%nTarget module '%s' already has sources at:%n %s%n", + target.name, + targetSources.toAbsolutePath(), + ) + val answer = console.readLine("Overwrite? [y/N] ")?.trim()?.lowercase() + + if (answer != "y" && answer != "yes") { + throw GradleException("Aborted by user.") + } + } +} + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsGeneratorDsl.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsGeneratorDsl.kt new file mode 100644 index 000000000..d67f75c6e --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsGeneratorDsl.kt @@ -0,0 +1,7 @@ +package dev.slne.surf.api.generator.nms + +/** Scope marker that prevents leaking receivers across nested DSL blocks. */ +@DslMarker +@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE) +annotation class NmsGeneratorDsl + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsGeneratorExtension.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsGeneratorExtension.kt new file mode 100644 index 000000000..7fc8f3d47 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsGeneratorExtension.kt @@ -0,0 +1,40 @@ +package dev.slne.surf.api.generator.nms + +/** + * Gradle extension for the `nms-module-generator` plugin. + * + * ```kotlin + * nmsGenerator { + * referenceVersion = NmsVersion.V26_1 + * targetVersion = NmsVersion.V1_21_11 + * + * transformations { + * renameClass("net.minecraft.resources.Identifier", + * "net.minecraft.resources.ResourceLocation") + * } + * } + * ``` + * + * @see GenerateNmsModulePlugin + */ +@NmsGeneratorDsl +open class NmsGeneratorExtension { + + /** The NMS version whose sources serve as the generation template. */ + lateinit var referenceVersion: NmsVersion + + /** The NMS version to generate. */ + lateinit var targetVersion: NmsVersion + + internal var transformationScope: TransformationScope = TransformationScope() + private set + + /** `true` if both [referenceVersion] and [targetVersion] have been set. */ + internal val isConfigured: Boolean + get() = ::referenceVersion.isInitialized && ::targetVersion.isInitialized + + /** Configures the source-code transformations applied during generation. */ + fun transformations(block: TransformationScope.() -> Unit) { + transformationScope = TransformationScope().apply(block) + } +} diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsModuleGenerator.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsModuleGenerator.kt new file mode 100644 index 000000000..caf527e39 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsModuleGenerator.kt @@ -0,0 +1,234 @@ +package dev.slne.surf.api.generator.nms + +import org.gradle.api.logging.Logger +import java.nio.file.Path +import kotlin.io.path.createDirectories +import kotlin.io.path.exists +import kotlin.io.path.writeText + +/** + * Copies every `.kt` source file from a [reference] NMS module into a + * [target] module, applying version-specific transformations along the way. + * + * Processing order per file: + * 1. Replace [reference] version-id and class-prefix with [target] equivalents. + * 2. Apply each [NmsTransformation] from [transformations] in declaration order. + * + * Additionally generates: + * - `META-INF/services/dev.slne.surf.api.paper.nms.common.NmsProvider` for ServiceLoader + * - `build.gradle.kts` (only when absent) + */ +class NmsModuleGenerator( + private val reference: NmsVersion, + private val target: NmsVersion, + private val transformations: List, + private val repoRoot: Path, + private val logger: Logger, +) { + + private val referenceSourceRoot: Path = + repoRoot.resolve(reference.modulePath).resolve(KOTLIN_SOURCE_PATH) + + private val targetSourceRoot: Path = + repoRoot.resolve(target.modulePath).resolve(KOTLIN_SOURCE_PATH) + + // ------------------------------------------------------------------ // + // Public API // + // ------------------------------------------------------------------ // + + /** + * Runs the full generation pipeline and returns the number of + * generated source files. + */ + fun generate(): Int { + require(referenceSourceRoot.exists()) { + "Reference source root does not exist: $referenceSourceRoot" + } + + prepareTargetDirectory() + val generated = copyAndTransformSources() + generateServiceFile() + generateBuildFile() + + logger.lifecycle( + "Generated {} source file(s) in {}", + generated, + targetSourceRoot.toAbsolutePath(), + ) + return generated + } + + // ------------------------------------------------------------------ // + // Internal steps // + // ------------------------------------------------------------------ // + + private fun prepareTargetDirectory() { + if (targetSourceRoot.exists()) { + targetSourceRoot.toFile().deleteRecursively() + } + targetSourceRoot.createDirectories() + } + + private fun copyAndTransformSources(): Int { + val exclusions = transformations + .filterIsInstance() + .map(NmsTransformation.ExcludeFile::filePattern) + + val sourceFiles = referenceSourceRoot.toFile() + .walk() + .filter { it.isFile && it.extension == "kt" } + .toList() + + var count = 0 + for (file in sourceFiles) { + val relativeKey = referenceSourceRoot + .relativize(file.toPath()) + .toString() + .replace('\\', '/') + + if (exclusions.any { relativeKey.endsWith(it) || relativeKey == it }) { + logger.info("Excluded: {}", relativeKey) + continue + } + + val targetPath = targetSourceRoot.resolve(transformPath(relativeKey)) + targetPath.parent.createDirectories() + targetPath.writeText(transformContent(file.readText(), relativeKey)) + count++ + } + return count + } + + // ------------------------------------------------------------------ // + // Transformations // + // ------------------------------------------------------------------ // + + /** Rewrites directory segments and file names for the target version. */ + private fun transformPath(relativeKey: String): String = relativeKey + .replace(reference.versionId, target.versionId) + .replace(reference.classPrefix, target.classPrefix) + + /** Applies all transformations to a single file's content. */ + private fun transformContent(content: String, relativeKey: String): String { + // Always replace version-id and class-prefix first + var result = content + .replace(reference.versionId, target.versionId) + .replace(reference.classPrefix, target.classPrefix) + + for (t in transformations) { + result = apply(result, t, relativeKey) + } + return result + } + + private fun apply( + content: String, + transformation: NmsTransformation, + relativeKey: String, + ): String = when (transformation) { + + is NmsTransformation.RenameClass -> { + var result = content.replace( + "import ${transformation.oldFqn}", + "import ${transformation.newFqn}", + ) + if (transformation.oldSimpleName != transformation.newSimpleName) { + result = result.replace( + Regex("\\b${Regex.escape(transformation.oldSimpleName)}\\b"), + transformation.newSimpleName, + ) + } + result + } + + is NmsTransformation.RemoveImport -> + content + .replace("import ${transformation.fqn}\n", "") + .replace("import ${transformation.fqn}\r\n", "") + + is NmsTransformation.ReplaceCode -> + content.replace(transformation.old, transformation.new) + + is NmsTransformation.ReplacePattern -> + content.replace(transformation.pattern, transformation.replacement) + + is NmsTransformation.TransformFile -> + if (relativeKey.endsWith(transformation.filePattern) || relativeKey == transformation.filePattern) { + transformation.transformer(content) + } else { + content + } + + is NmsTransformation.ExcludeFile -> + content // already handled at file level + } + + // ------------------------------------------------------------------ // + // Scaffold generation // + // ------------------------------------------------------------------ // + + private fun generateServiceFile() { + val serviceDir = repoRoot + .resolve(target.modulePath) + .resolve("src/main/resources/META-INF/services") + serviceDir.createDirectories() + + val providerFqn = "$PROVIDER_PACKAGE_PREFIX${target.versionId}.${target.classPrefix}NmsProvider" + serviceDir.resolve(NMS_PROVIDER_SERVICE).writeText("$providerFqn\n") + + logger.lifecycle("Generated service file: {}", providerFqn) + } + + private fun generateBuildFile() { + val buildFile = repoRoot.resolve(target.modulePath).resolve("build.gradle.kts") + if (buildFile.exists()) { + logger.lifecycle("build.gradle.kts already exists, skipping") + return + } + + buildFile.parent.createDirectories() + buildFile.writeText(buildGradleTemplate()) + logger.lifecycle("Generated build.gradle.kts (paperDevBundle={})", target.paperDevBundle) + } + + private fun buildGradleTemplate(): String = """ + |plugins { + | `core-convention` + | id("io.papermc.paperweight.userdev") apply true + |} + | + |kotlin { + | compilerOptions { + | optIn.add("dev.slne.surf.api.paper.visualizer.visualizer.ExperimentalVisualizerApi") + | } + |} + | + |dependencies { + | api(projects.surfApiPaper.surfApiPaperNms.surfApiPaperNmsCommon) + | api(projects.surfApiCore.surfApiCoreServer) + | + | paperweight.paperDevBundle("${target.paperDevBundle}") + | + | compileOnly(libs.placeholder.api) + | compileOnly(libs.reflection.remapper) + | compileOnly(libs.mccoroutine.folia.api) + | compileOnly(libs.scoreboard.library.api) + | + | implementation(libs.bytebuddy) + |} + | + |configurations.all { + | exclude(group = "org.spigotmc", module = "spigot-api") + |} + """.trimMargin() + "\n" + + private companion object { + const val KOTLIN_SOURCE_PATH = "src/main/kotlin" + const val PROVIDER_PACKAGE_PREFIX = "dev.slne.surf.api.paper.server.nms." + const val NMS_PROVIDER_SERVICE = "dev.slne.surf.api.paper.nms.common.NmsProvider" + } +} + + + + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsTransformation.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsTransformation.kt new file mode 100644 index 000000000..a14582761 --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsTransformation.kt @@ -0,0 +1,70 @@ +package dev.slne.surf.api.generator.nms + +/** + * A single source-code transformation applied during NMS module generation. + * + * Transformations run **after** the automatic version-id and class-prefix + * replacements and are applied in declaration order. + */ +sealed class NmsTransformation { + + /** + * Renames a fully-qualified class in every generated file. + * + * Handles both `import` statements and in-code simple-name references + * (via `\b` word-boundary matching when the simple names differ). + * + * @property oldFqn Fully-qualified name of the class in the reference module. + * @property newFqn Fully-qualified name of the replacement class. + */ + data class RenameClass( + val oldFqn: String, + val newFqn: String, + ) : NmsTransformation() { + val oldSimpleName: String get() = oldFqn.substringAfterLast('.') + val newSimpleName: String get() = newFqn.substringAfterLast('.') + } + + /** + * Removes an `import` line from every generated file. + * + * @property fqn Fully-qualified name to remove (without the `import` keyword). + */ + data class RemoveImport(val fqn: String) : NmsTransformation() + + /** + * Literal string replacement applied to every generated file. + * + * @property old Text to search for. + * @property new Replacement text. + */ + data class ReplaceCode(val old: String, val new: String) : NmsTransformation() + + /** + * Regex-based replacement applied to every generated file. + * + * @property pattern Compiled regex pattern. + * @property replacement Replacement string (supports group references like `$1`). + */ + data class ReplacePattern(val pattern: Regex, val replacement: String) : NmsTransformation() + + /** + * Custom transformation function targeting files whose relative path + * matches or ends with [filePattern]. + * + * @property filePattern Relative path suffix to match (e.g. `"bridges/SomeFile.kt"`). + * @property transformer Receives the current file content and returns the transformed content. + */ + data class TransformFile( + val filePattern: String, + val transformer: (String) -> String, + ) : NmsTransformation() + + /** + * Excludes matching files from generation entirely. + * + * @property filePattern Relative path suffix to match. + */ + data class ExcludeFile(val filePattern: String) : NmsTransformation() +} + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsVersion.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsVersion.kt new file mode 100644 index 000000000..1c06f6b9a --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/NmsVersion.kt @@ -0,0 +1,42 @@ +package dev.slne.surf.api.generator.nms + +/** + * Supported NMS versions for module generation. + * + * Each entry encapsulates all version-specific metadata required by the + * generator, so consumers only need to reference an enum constant instead + * of specifying identifiers, prefixes, and bundle versions manually. + * + * @property versionId Identifier used in package names and directory paths (e.g. `"v26_1"`). + * @property classPrefix Prefix applied to generated class names (e.g. `"V26_1"`). + * @property paperDevBundle Version string passed to `paperweight.paperDevBundle(…)`. + */ +enum class NmsVersion( + val versionId: String, + val classPrefix: String, + val paperDevBundle: String, +) { + V1_21_11( + versionId = "v1_21_11", + classPrefix = "V1_21_11", + paperDevBundle = "1.21.11-R0.1-SNAPSHOT", + ), + V26_1( + versionId = "v26_1", + classPrefix = "V26_1", + paperDevBundle = "26.1+", + ); + + /** Relative path from the repository root to this version's Gradle module. */ + val modulePath: String + get() = "$MODULE_BASE_PATH${versionId.replace('_', '-')}" + + /** Gradle project path usable in `settings.gradle.kts` `include(…)` calls. */ + val gradlePath: String + get() = ":${modulePath.replace('/', ':')}" + + private companion object { + const val MODULE_BASE_PATH = "surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-" + } +} + diff --git a/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/TransformationScope.kt b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/TransformationScope.kt new file mode 100644 index 000000000..05b5e3a1c --- /dev/null +++ b/surf-api-generator/gradle-nms-module-generator/src/main/kotlin/dev/slne/surf/api/generator/nms/TransformationScope.kt @@ -0,0 +1,56 @@ +package dev.slne.surf.api.generator.nms + +/** + * DSL scope for declaring [NmsTransformation] rules. + * + * Available inside the `transformations { … }` block of the + * [NmsGeneratorExtension]. Each method adds a transformation that will + * be applied in declaration order during generation. + */ +@NmsGeneratorDsl +class TransformationScope internal constructor() { + + private val _transformations = mutableListOf() + + /** Snapshot of all registered transformations. */ + internal val transformations: List get() = _transformations.toList() + + /** + * Renames a fully-qualified class in all generated files. + * + * Automatically rewrites the `import` line **and** every in-code + * reference (via word-boundary matching when the simple names differ). + */ + fun renameClass(oldFqn: String, newFqn: String) { + _transformations += NmsTransformation.RenameClass(oldFqn, newFqn) + } + + /** Removes the `import` line for [fqn] from all generated files. */ + fun removeImport(fqn: String) { + _transformations += NmsTransformation.RemoveImport(fqn) + } + + /** Replaces every occurrence of [old] with [new] in all generated files. */ + fun replaceCode(old: String, new: String) { + _transformations += NmsTransformation.ReplaceCode(old, new) + } + + /** Replaces matches of the given regex [pattern] with [replacement]. */ + fun replacePattern(pattern: String, replacement: String) { + _transformations += NmsTransformation.ReplacePattern(Regex(pattern), replacement) + } + + /** + * Applies [transformer] to every file whose relative path ends with + * [filePattern] (uses `/` as separator). + */ + fun transformFile(filePattern: String, transformer: (String) -> String) { + _transformations += NmsTransformation.TransformFile(filePattern, transformer) + } + + /** Excludes files whose relative path ends with [filePattern] from generation. */ + fun excludeFile(filePattern: String) { + _transformations += NmsTransformation.ExcludeFile(filePattern) + } +} + diff --git a/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/ClassNames.kt b/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/ClassNames.kt index cff057e4d..a4c39eebf 100644 --- a/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/ClassNames.kt +++ b/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/ClassNames.kt @@ -5,6 +5,7 @@ import dev.slne.surf.api.shared.api.component.Priority import dev.slne.surf.api.shared.api.component.SurfComponentMeta import dev.slne.surf.api.shared.api.component.processor.ComponentPostProcessor import dev.slne.surf.api.shared.api.component.requirement.* +import dev.slne.surf.api.shared.internal.nms.NmsProviderMarker object ClassNames { val COMPONENT_META = nameOf() @@ -19,4 +20,5 @@ object ClassNames { val CONDITIONAL_ON_MISSING_COMPONENT = nameOf() val CONDITIONAL_ON_PROPERTY = nameOf() val COMPONENT_POST_PROCESSOR = nameOf() + val NMS_PROVIDER = nameOf() } \ No newline at end of file diff --git a/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/nms/NmsProvidersCollector.kt b/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/nms/NmsProvidersCollector.kt new file mode 100644 index 000000000..540d33661 --- /dev/null +++ b/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/nms/NmsProvidersCollector.kt @@ -0,0 +1,79 @@ +package dev.slne.surf.api.processor.nms + +import com.google.devtools.ksp.KspExperimental +import com.google.devtools.ksp.processing.Dependencies +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.symbol.ClassKind +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import dev.slne.surf.api.processor.ClassNames +import dev.slne.surf.api.processor.util.AnnotationUtils +import dev.slne.surf.api.processor.util.getArgumentValueAs +import dev.slne.surf.api.processor.util.toBinaryName +import dev.slne.surf.api.shared.internal.nms.NmsProviderConfig +import dev.slne.surf.api.shared.internal.nms.NmsProviderMeta +import dev.slne.surf.api.shared.internal.nms.NmsVersion + +class NmsProvidersCollector(environment: SymbolProcessorEnvironment) : SymbolProcessor { + + private val logger = environment.logger + private val codeGenerator = environment.codeGenerator + private val nmsProviders = mutableMapOf>() + + @OptIn(KspExperimental::class) + override fun process(resolver: Resolver): List { + val metas = AnnotationUtils.findAnnotatedClasses( + resolver = resolver, + annotationFqName = ClassNames.NMS_PROVIDER, + includeMetaAnnotations = false, + excludeAnnotationClasses = false, + logger = logger + ).mapNotNull(fun(nmsProviderClass): NmsProviderMeta? { + val annotation = nmsProviderClass.findNmsProviderAnnotation() ?: return null + val rawVersion = annotation.getArgumentValueAs("version") ?: return null + if (rawVersion.classKind != ClassKind.ENUM_ENTRY) return null + + val version = try { + NmsVersion.valueOf(rawVersion.simpleName.asString()) + } catch (_: Throwable) { + logger.error("Unknown NmsVersion: ${rawVersion.simpleName.asString()}") + return null + } + + return NmsProviderMeta(version, nmsProviderClass.toBinaryName()) + }).toList() + + val module = resolver.getModuleName().asString() + nmsProviders.computeIfAbsent(module) { mutableListOf() }.addAll(metas) + + return emptyList() + } + + private fun KSAnnotated.findNmsProviderAnnotation() = annotations.find { + it.annotationType.resolve().declaration.qualifiedName?.asString() == ClassNames.NMS_PROVIDER + } + + override fun finish() { + for ((module, providers) in nmsProviders) { + if (providers.isEmpty()) continue + + val filePath = "${NmsProviderConfig.NMS_PROVIDERS_DIRECTORY}/$module.json" + try { + codeGenerator.createNewFileByPath(Dependencies.ALL_FILES, filePath, "") + .bufferedWriter() + .use { writer -> + val jsonString = NmsProviderConfig.json.encodeToString(providers) + writer.write(jsonString) + } + + logger.info("Wrote NMS providers to: $filePath") + } catch (e: Exception) { + logger.error("Unable to create $filePath, $e") + } + } + + nmsProviders.clear() + } +} \ No newline at end of file diff --git a/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/nms/NmsProvidersCollectorProvider.kt b/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/nms/NmsProvidersCollectorProvider.kt new file mode 100644 index 000000000..d4b0895ad --- /dev/null +++ b/surf-api-gradle-plugin/surf-api-processor/src/main/kotlin/dev/slne/surf/api/processor/nms/NmsProvidersCollectorProvider.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.api.processor.nms + +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.processing.SymbolProcessorProvider + +class NmsProvidersCollectorProvider : SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { + return NmsProvidersCollector(environment) + } +} \ No newline at end of file diff --git a/surf-api-gradle-plugin/surf-api-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/surf-api-gradle-plugin/surf-api-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider index 213861160..8bbb4d91d 100644 --- a/surf-api-gradle-plugin/surf-api-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider +++ b/surf-api-gradle-plugin/surf-api-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -1,2 +1,3 @@ dev.slne.surf.api.processor.autoservice.AutoServiceSymbolProcessorProvider -dev.slne.surf.api.processor.component.ComponentSymbolProcessorProvider \ No newline at end of file +dev.slne.surf.api.processor.nms.NmsProvidersCollectorProvider +dev.slne.surf.api.processor.component.ComponentSymbolProcessorProvider diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/build.gradle.kts b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/build.gradle.kts new file mode 100644 index 000000000..583bc237c --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + `core-convention` +} + +dependencies { + compileOnlyApi(projects.surfApiPaper.surfApiPaper) + compileOnlyApi(projects.surfApiShared.surfApiSharedInternal) + compileOnly(libs.paper.api) +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/AbstractChannelInjector.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/AbstractChannelInjector.kt new file mode 100644 index 000000000..5fd307cdb --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/AbstractChannelInjector.kt @@ -0,0 +1,204 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.core.messages.Colors +import dev.slne.surf.api.core.messages.CommonComponents +import dev.slne.surf.api.core.messages.adventure.text +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import io.netty.channel.Channel +import io.netty.channel.ChannelDuplexHandler +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.ChannelPromise +import io.netty.util.AttributeKey +import net.kyori.adventure.key.Key +import org.bukkit.entity.Player +import org.bukkit.event.Listener +import dev.slne.surf.api.paper.event.register as registerListener +import dev.slne.surf.api.paper.event.unregister as unregisterListener + +@OptIn(NmsUseWithCaution::class) +abstract class AbstractChannelInjector : Listener { + companion object { + private val log = logger() + + private val CHANNEL_KEY = Key.key("surf-api", "packet-listener") + private const val CHANNEL_NAME = "surf_api_packet_listener" + + val instance by lazy { NmsProvider.current.createChannelInjector() } + } + + private val packetHandlerKey = AttributeKey.newInstance("surf_api_packet_handler") + + fun register() { + registerChannelInitializeListener(CHANNEL_KEY) { this.getOrInjectPacketHandler(it) } + registerListener(NmsProvider.current.plugin) + } + + fun unregister() { + unregisterListener() + unregisterChannelInitializeListener(CHANNEL_KEY) + } + + @Suppress("SameParameterValue") + protected abstract fun registerChannelInitializeListener(key: Key, listener: (Channel) -> Unit) + + @Suppress("SameParameterValue") + protected abstract fun unregisterChannelInitializeListener(key: Key) + + protected abstract fun createPacketHandler(): H + protected abstract fun getNmsChannelHandlerName(): String + + protected fun getOrInjectPacketHandler(channel: Channel): H { + val handler = createPacketHandler() + val attr = channel.attr(packetHandlerKey) + + if (!attr.compareAndSet(null, handler)) { + return attr.get() + } + + val command = Runnable { + with(channel.pipeline()) { + if (get(CHANNEL_NAME) == null) { + addBefore(getNmsChannelHandlerName(), CHANNEL_NAME, handler) + } + } + } + + with(channel.eventLoop()) { + if (inEventLoop()) { + command.run() + } else { + execute(command) + } + } + + return handler + } + + protected fun createFailedToInjectPacketListenerDisconnectReason() = CommonComponents.renderDisconnectMessage( + "FAILED TO INJECT PACKET LISTENER", + { + text( + "Dein Profil ist nicht authentifiziert, daher können wir den Paket-Listener nicht einbinden. Dies ist wahrscheinlich ein Problem mit deiner Verbindung zu den Authentifizierungsservern von Mojang.", + Colors.ERROR + ) + }, + issue = true + ) + + @OptIn(NmsUseWithCaution::class) + abstract class AbstractPacketHandler : ChannelDuplexHandler() { + companion object { + val NO_CONNECTION_SENTINEL = Any() + } + + private val bridge = InternalNmsBridge.get() + private val packetListenerApi = InternalPacketListenerApiBridge.get() + private val packetBridgeHandler = NmsProvider.current.getPacketBridgeHandler() + + @OptIn(NmsUseWithCaution::class) + override fun write( + ctx: ChannelHandlerContext, + msg: Any, + promise: ChannelPromise, + ) { // server -> client + handlePacket( + originalMsg = msg, + passthrough = { super.write(ctx, it, promise) }, + nmsHandler = packetListenerApi::handleClientboundPacket, + bridgeHandler = ::handleClientboundPacketFromBridge + ) + } + + @OptIn(NmsUseWithCaution::class) + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { // client -> server + handlePacket( + originalMsg = msg, + passthrough = { super.channelRead(ctx, it) }, + nmsHandler = packetListenerApi::handleServerboundPacket, + bridgeHandler = ::handleServerboundPacketFromBridge + ) + } + + protected abstract fun isPacket(msg: Any): Boolean + protected abstract fun getPlayerFromConnection(): Any? + protected abstract fun getBukkitPlayer(player: Any?): Player? + + private inline fun handlePacket( + originalMsg: Any, + passthrough: (Any) -> Unit, + nmsHandler: (packet: Any, serverPlayer: Any?) -> Any?, + bridgeHandler: (player: Player?, packet: Any) -> Any? + ) { + var msg = originalMsg + if (!isPacket(msg)) { + passthrough(msg) + return + } + + val player = getPlayerFromConnection() + if (player === NO_CONNECTION_SENTINEL) { + passthrough(msg) + return + } + + try { + msg = nmsHandler(msg, player) ?: return + msg = bridgeHandler(getBukkitPlayer(player), msg) ?: return + passthrough(msg) + } catch (outOfMemoryError: OutOfMemoryError) { + throw outOfMemoryError + } catch (t: Throwable) { + log.atSevere() + .withCause(t).log("Failed to handle packet") + passthrough(msg) + } + } + + @OptIn(NmsUseWithCaution::class) + fun handleServerboundPacketFromBridge( + player: Player?, + packet: Any, + ): Any? { + val apiPacket = packetBridgeHandler.wrapServerboundPacket(packet) + + if (apiPacket != null) { // we have an api packet wrapper for this packet + val resultApi = this.bridge.handleServerboundPacket( + apiPacket, + player + ) + + if (resultApi != null) { // we may have a modified packet + return packetBridgeHandler.unwrapPacket(resultApi) + } + } else { + return packet // no api packet wrapper, so we just return the original packet + } + + return null // the packet was canceled + } + + fun handleClientboundPacketFromBridge( + player: Player?, + packet: Any, + ): Any? { + val apiPacket = packetBridgeHandler.wrapClientboundPacket(packet) + + if (apiPacket != null) { + val resultApi = this.bridge.handleClientboundPacket( + apiPacket, + player + ) + + if (resultApi != null) { + return packetBridgeHandler.unwrapPacket(resultApi) + } + } else { + return packet + } + + return null + } + } +} + diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/GlowingLifecycleHandler.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/GlowingLifecycleHandler.kt new file mode 100644 index 000000000..ac9cd476a --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/GlowingLifecycleHandler.kt @@ -0,0 +1,33 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import org.bukkit.entity.Player + +/** + * Version-agnostic interface for glowing API lifecycle operations. + * + * Provides the operations needed by the GlowingListener event handler + * without depending on version-specific implementations. + */ +interface GlowingLifecycleHandler { + /** + * Removes all glowing effects for a player (called on quit). + */ + fun removeAllGlowingOnQuit(player: Player) + + /** + * Gets block glow spawn operations for a chunk load event. + * + * @param player the player who loaded the chunk + * @param chunkX the chunk X coordinate + * @param chunkZ the chunk Z coordinate + * @param world the world of the chunk + * @return a [PacketOperation] to spawn the glowing blocks, or null if none + */ + fun getBlockGlowSpawnOperationForChunk( + player: Player, + chunkX: Int, + chunkZ: Int, + world: org.bukkit.World + ): PacketOperation? +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/InternalNmsBridge.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/InternalNmsBridge.kt new file mode 100644 index 000000000..41932e053 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/InternalNmsBridge.kt @@ -0,0 +1,25 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.SurfPaperNmsBridge +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket +import org.bukkit.entity.Player + +@NmsUseWithCaution +interface InternalNmsBridge : SurfPaperNmsBridge { + fun handleServerboundPacket( + packet: Packet, + player: Player?, + ): Packet? + + fun handleClientboundPacket( + packet: Packet, + player: Player?, + ): Packet? + + companion object { + fun get() = SurfPaperNmsBridge.INSTANCE as InternalNmsBridge + } +} + diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/InternalPacketListenerApiBridge.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/InternalPacketListenerApiBridge.kt new file mode 100644 index 000000000..6896f3590 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/InternalPacketListenerApiBridge.kt @@ -0,0 +1,22 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.packet.listener.SurfPaperPacketListenerApi + +@NmsUseWithCaution +interface InternalPacketListenerApiBridge : SurfPaperPacketListenerApi { + fun handleClientboundPacket( + packet: Any, + serverPlayer: Any? + ): Any? + + fun handleServerboundPacket( + packet: Any, + serverPlayer: Any? + ): Any? + + companion object { + fun get() = SurfPaperPacketListenerApi.INSTANCE as InternalPacketListenerApiBridge + } +} + diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/LibLoaderBridge.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/LibLoaderBridge.kt new file mode 100644 index 000000000..0d407a1ad --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/LibLoaderBridge.kt @@ -0,0 +1,18 @@ +package dev.slne.surf.api.paper.nms.common + +import java.net.URLClassLoader + +interface LibLoaderBridge { + fun getActiveCompatibilities(): MutableSet + + fun convertWithCommodore( + b: ByteArray, + pluginName: String, + pluginVersion: String, + activeCompatibilities: MutableSet + ): ByteArray + + fun overwriteLibraryLoader(pluginClassLoader: URLClassLoader, newLoader: URLClassLoader) + + fun getLibraryLoader(pluginClassLoader: URLClassLoader): URLClassLoader +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsPacketBridgeHandler.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsPacketBridgeHandler.kt new file mode 100644 index 000000000..033cc367f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsPacketBridgeHandler.kt @@ -0,0 +1,40 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.NmsPacket +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket + +/** + * Handles wrapping/unwrapping of NMS packets for the channel injector. + * + * This interface bridges the gap between raw NMS packet objects (passed as [Any]) + * and the API-level [NmsPacket] wrappers, allowing version-specific packet + * handling without the channel injector needing to know about specific NMS types. + */ +@NmsUseWithCaution +interface NmsPacketBridgeHandler { + /** + * Wraps a raw NMS serverbound packet into an API [NmsServerboundPacket]. + * + * @param nmsPacket the raw NMS packet object + * @return the API wrapper, or `null` if no wrapper is available for this packet type + */ + fun wrapServerboundPacket(nmsPacket: Any): NmsServerboundPacket? + + /** + * Wraps a raw NMS clientbound packet into an API [NmsClientboundPacket]. + * + * @param nmsPacket the raw NMS packet object + * @return the API wrapper, or `null` if no wrapper is available for this packet type + */ + fun wrapClientboundPacket(nmsPacket: Any): NmsClientboundPacket? + + /** + * Extracts the underlying NMS packet from an API [NmsPacket] wrapper. + * + * @param apiPacket the API packet wrapper + * @return the raw NMS packet object + */ + fun unwrapPacket(apiPacket: NmsPacket): Any +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsProvider.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsProvider.kt new file mode 100644 index 000000000..34f339a92 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsProvider.kt @@ -0,0 +1,196 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.glow.SurfGlowingApi +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.* +import dev.slne.surf.api.paper.nms.bridges.packets.SurfPaperNmsPacketBridges +import dev.slne.surf.api.paper.nms.bridges.packets.block.SurfPaperNmsBlockPackets +import dev.slne.surf.api.paper.nms.bridges.packets.entity.SurfPaperNmsSpawnPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerChatPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerToastPackets +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener +import dev.slne.surf.api.paper.region.TickThreadGuard +import dev.slne.surf.api.shared.internal.nms.NmsProviderConfig +import dev.slne.surf.api.shared.internal.nms.NmsProviderMeta +import dev.slne.surf.api.shared.internal.nms.NmsVersion +import org.bukkit.plugin.java.JavaPlugin +import java.io.File +import java.net.URI +import java.util.jar.JarFile + +/** + * Main interface for version-specific NMS operations. + * + * Each supported Minecraft version provides an implementation of this interface + * that creates the appropriate NMS bridge implementations and packet listeners. + */ +@NmsUseWithCaution +interface NmsProvider { + /** + * The NMS version this provider supports. + */ + val version: NmsVersion + val plugin: JavaPlugin + + // ==================== Bridge Factories ==================== // + + fun createNmsBridge(): InternalNmsBridge + fun createCommonBridge(): SurfPaperNmsCommonBridge + fun createEntityBridge(): SurfPaperNmsEntityBridge + fun createItemBridge(): SurfPaperNmsItemBridge + fun createNbtBridge(): SurfPaperNmsNbtBridge + fun createGlowingBridge(): SurfPaperNmsGlowingBridge + fun createStatsBridge(): SurfPaperNmsStatsBridge + fun createLootTableBridge(): SurfPaperNmsLootTableBridge + fun createCommandArgumentTypesBridge(): SurfPaperNmsCommandArgumentTypesBridge + fun createPacketBridges(): SurfPaperNmsPacketBridges + fun createBlockPackets(): SurfPaperNmsBlockPackets + fun createSpawnPackets(): SurfPaperNmsSpawnPackets + fun createPlayerPackets(): SurfPaperNmsPlayerPackets + fun createPlayerChatPackets(): SurfPaperNmsPlayerChatPackets + fun createPlayerToastPackets(): SurfPaperNmsPlayerToastPackets + fun createTickThreadGuard(): TickThreadGuard + fun getLibLoaderBridge(): LibLoaderBridge + + // ==================== Packet Bridge Handler ==================== // + + /** + * Creates the packet bridge handler for wrapping/unwrapping NMS packets. + */ + fun getPacketBridgeHandler(): NmsPacketBridgeHandler + + /** + * Creates the packet lore registry for managing version-specific lore handlers. + */ + fun createPacketLoreRegistry(): PacketLoreRegistry + + /** + * Creates the glowing lifecycle handler for event-driven glowing management. + */ + fun createGlowingLifecycleHandler(): GlowingLifecycleHandler + + // ==================== Glowing API ==================== // + + /** + * Creates the version-specific glowing API implementation. + */ + fun createGlowingApi(): SurfGlowingApi + + // ==================== Packet Listeners ==================== // + + fun createChannelInjector(): AbstractChannelInjector<*> + fun createPacketListenerApi(): InternalPacketListenerApiBridge + + /** + * Creates version-specific packet listeners (e.g. lore handler, glowing handler). + * + * @return list of packet listeners to be registered with the packet listener API + */ + fun createPacketListeners(): List + + /** + * Initializes version-specific resources. Called during plugin enable. + */ + fun initialize() + + /** + * Cleans up version-specific resources. Called during plugin disable. + */ + fun shutdown() + + companion object { + private val log = logger() + + /** + * Loads the [NmsProvider] for the currently running Minecraft version. + * + * @throws IllegalStateException if no provider is found for the current version + */ + val current: NmsProvider by lazy { + val version = NmsVersionResolver.current + + try { + val metas = mutableListOf() + + val resources = javaClass.classLoader.getResources(NmsProviderConfig.NMS_PROVIDERS_DIRECTORY) + while (resources.hasMoreElements()) { + val url = resources.nextElement() + + if (url.protocol == "jar") { + val jarPath = url.path.substringBefore("!") + JarFile(File(URI(jarPath))).use { jarFile -> + jarFile.entries().asSequence() + .filter { + it.name.startsWith(NmsProviderConfig.NMS_PROVIDERS_DIRECTORY) && it.name.endsWith( + ".json" + ) + } + .forEach { entry -> + try { + val raw = jarFile.getInputStream(entry).bufferedReader() + .use { it.readText() } + val decoded = + NmsProviderConfig.json.decodeFromString>(raw) + metas += decoded + } catch (e: Exception) { + log.atSevere() + .withCause(e) + .log("Failed to parse ${entry.name}") + } + } + } + } else { + val dir = File(url.toURI()) + dir.listFiles { file -> file.extension == "json" }?.forEach { file -> + try { + val raw = file.readText() + val decoded = + NmsProviderConfig.json.decodeFromString>(raw) + metas += decoded + } catch (e: Exception) { + log.atSevere() + .withCause(e) + .log("Failed to parse ${file.name}") + } + } + } + } + + log.atInfo().log("Discovered %s NmsProviders: %s", metas.size, metas.joinToString(", ")) + + val selectedMeta = metas.find { it.version == version }?.also { meta -> + log.atInfo().log("Found matching NmsProvider: %s", meta.version.versionPrefix) + } ?: run { + log.atWarning() + .log("No exact match for NmsProvider version %s, using fallback", version.versionPrefix) + val fallback = metas.maxByOrNull { it.version.versionPrefix } + ?: error("No NmsProvider implementations found") + log.atWarning().log("Selected fallback NmsProvider: %s", fallback.version.versionPrefix) + fallback + } + + val clazz = try { + Class.forName(selectedMeta.implementation) + } catch (e: Throwable) { + throw IllegalStateException("Failed to load NmsProvider implementation", e) + } + + val constructor = try { + clazz.getConstructor(JavaPlugin::class.java) + } catch (e: Throwable) { + throw IllegalStateException( + "Failed to load NmsProvider implementation. Implementation must have a constructor with a single argument of type JavaPlugin", + e + ) + } + + constructor.newInstance(JavaPlugin.getProvidingPlugin(NmsProvider::class.java)) as NmsProvider + } catch (e: Exception) { + log.atSevere().withCause(e).log("Failed to load NmsProvider") + throw IllegalStateException("Failed to load NmsProvider", e) + } + } + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsVersionResolver.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsVersionResolver.kt new file mode 100644 index 000000000..a4584e080 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/NmsVersionResolver.kt @@ -0,0 +1,30 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.shared.internal.nms.NmsVersion +import org.bukkit.Bukkit + +object NmsVersionResolver { + private val log = logger() + + /** + * The NMS version of the currently running Minecraft server. + * + * Detected at runtime from `Bukkit.getMinecraftVersion()`. + * Uses latest provided NMS version if no exact match is found. + */ + val current: NmsVersion by lazy { + val mcVersion = Bukkit.getMinecraftVersion() + val matched = NmsVersion.entries.firstOrNull { mcVersion.startsWith(it.versionPrefix) } + if (matched != null) { + matched + } else { + val fallback = NmsVersion.entries.maxByOrNull { it.versionPrefix } ?: error("No NMS versions defined!") + log.atWarning().log( + "There is no matching nms version, using fallback NMS version: %s", + fallback.name + ) + fallback + } + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/PacketLoreRegistry.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/PacketLoreRegistry.kt new file mode 100644 index 000000000..691f1b7cb --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-common/src/main/kotlin/dev/slne/surf/api/paper/nms/common/PacketLoreRegistry.kt @@ -0,0 +1,18 @@ +package dev.slne.surf.api.paper.nms.common + +import dev.slne.surf.api.paper.packet.lore.SurfPaperPacketLoreHandler +import org.bukkit.NamespacedKey +import org.bukkit.plugin.Plugin + +/** + * Version-agnostic interface for managing packet lore handlers. + * + * Each version module provides an implementation that delegates to + * its version-specific packet lore listener. + */ +interface PacketLoreRegistry { + fun register(plugin: Plugin, identifier: NamespacedKey, listener: SurfPaperPacketLoreHandler) + fun register(plugin: Plugin, listener: SurfPaperPacketLoreHandler) + fun unregister(identifier: NamespacedKey) + fun unregister(plugin: Plugin) +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/build.gradle.kts b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/build.gradle.kts new file mode 100644 index 000000000..c39dd476b --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + `core-convention` + id("io.papermc.paperweight.userdev") apply true +} + +kotlin { + compilerOptions { + optIn.add("dev.slne.surf.api.paper.visualizer.visualizer.ExperimentalVisualizerApi") + } +} + +dependencies { + api(projects.surfApiPaper.surfApiPaperNms.surfApiPaperNmsCommon) + api(projects.surfApiCore.surfApiCoreServer) + + paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") + + compileOnly(libs.placeholder.api) + compileOnly(libs.reflection.remapper) + compileOnly(libs.mccoroutine.folia.api) + compileOnly(libs.scoreboard.library.api) + + implementation(libs.bytebuddy) +} + +configurations.all { + exclude(group = "org.spigotmc", module = "spigot-api") +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/V1_21_11NmsPacketBridgeHandler.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/V1_21_11NmsPacketBridgeHandler.kt new file mode 100644 index 000000000..7bb6f7497 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/V1_21_11NmsPacketBridgeHandler.kt @@ -0,0 +1,28 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11 + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsPacketBridgeHandler +import dev.slne.surf.api.paper.nms.listener.packets.NmsPacket +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.V1_21_11NmsPacketImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.V1_21_11PacketRegistry +import net.minecraft.network.protocol.Packet + +@NmsUseWithCaution +object V1_21_11NmsPacketBridgeHandler : NmsPacketBridgeHandler { + + @Suppress("UNCHECKED_CAST") + override fun wrapServerboundPacket(nmsPacket: Any): NmsServerboundPacket? { + return V1_21_11PacketRegistry.createServerboundPacketOrNull(nmsPacket as Packet<*>) + } + + @Suppress("UNCHECKED_CAST") + override fun wrapClientboundPacket(nmsPacket: Any): NmsClientboundPacket? { + return V1_21_11PacketRegistry.createClientboundPacketOrNull(nmsPacket as Packet<*>) + } + + override fun unwrapPacket(apiPacket: NmsPacket): Any { + return V1_21_11NmsPacketImpl.getFromApi(apiPacket).nmsPacket + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/V1_21_11NmsProvider.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/V1_21_11NmsProvider.kt new file mode 100644 index 000000000..8f1f27b06 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/V1_21_11NmsProvider.kt @@ -0,0 +1,103 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11 + +import dev.slne.surf.api.paper.glow.SurfGlowingApi +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.* +import dev.slne.surf.api.paper.nms.bridges.packets.SurfPaperNmsPacketBridges +import dev.slne.surf.api.paper.nms.bridges.packets.block.SurfPaperNmsBlockPackets +import dev.slne.surf.api.paper.nms.bridges.packets.entity.SurfPaperNmsSpawnPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerChatPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerToastPackets +import dev.slne.surf.api.paper.nms.common.* +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener +import dev.slne.surf.api.paper.region.TickThreadGuard +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.* +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11SurfPaperNmsPacketBridgesImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.block.V1_21_11SurfPaperNmsBlockPacketsImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.entity.V1_21_11SurfPaperNmsSpawnPacketsImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.player.V1_21_11SurfPaperNmsPlayerChatPacketsImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.player.V1_21_11SurfPaperNmsPlayerPacketsImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.player.V1_21_11SurfPaperNmsPlayerToastPacketsImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11GlowingLifecycleHandler +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.packet.listener.V1_21_11ChannelInjector +import dev.slne.surf.api.paper.server.nms.v1_21_11.packet.listener.V1_21_11GlowingPacketListener +import dev.slne.surf.api.paper.server.nms.v1_21_11.packet.lore.V1_21_11PacketLoreListener +import dev.slne.surf.api.paper.server.nms.v1_21_11.packet.lore.V1_21_11PacketLoreRegistry +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection +import dev.slne.surf.api.paper.server.nms.v1_21_11.region.V1_21_11TickThreadGuard +import dev.slne.surf.api.shared.internal.nms.NmsProviderMarker +import dev.slne.surf.api.shared.internal.nms.NmsVersion +import org.bukkit.plugin.java.JavaPlugin + +@Suppress("ClassName") +@OptIn(NmsUseWithCaution::class) +@NmsProviderMarker(NmsVersion.V1_21_11) +class V1_21_11NmsProvider(override val plugin: JavaPlugin) : NmsProvider { + override val version: NmsVersion = NmsVersion.V1_21_11 + + override fun createNmsBridge() = V1_21_11SurfPaperNmsBridgeImpl() + override fun createCommonBridge(): SurfPaperNmsCommonBridge = + V1_21_11SurfPaperNmsCommonBridgeImpl() + + override fun createEntityBridge(): SurfPaperNmsEntityBridge = + V1_21_11SurfPaperNmsEntityBridgeImpl() + + override fun createItemBridge(): SurfPaperNmsItemBridge = V1_21_11SurfPaperNmsItemBridgeImpl() + override fun createNbtBridge(): SurfPaperNmsNbtBridge = V1_21_11SurfPaperNmsNbtBridgeImpl() + override fun createGlowingBridge(): SurfPaperNmsGlowingBridge = V1_21_11SurfPaperNmsGlowingBridgeImpl + + override fun createStatsBridge(): SurfPaperNmsStatsBridge = + V1_21_11SurfPaperNmsStatsBridgeImpl() + + override fun createLootTableBridge(): SurfPaperNmsLootTableBridge = + V1_21_11SurfPaperNmsLootTableBridgeImpl() + + override fun createCommandArgumentTypesBridge(): SurfPaperNmsCommandArgumentTypesBridge = + V1_21_11SurfPaperNmsCommandArgumentTypesBridgeImpl() + + override fun createPacketBridges(): SurfPaperNmsPacketBridges = + V1_21_11SurfPaperNmsPacketBridgesImpl() + + override fun createBlockPackets(): SurfPaperNmsBlockPackets = + V1_21_11SurfPaperNmsBlockPacketsImpl() + + override fun createSpawnPackets(): SurfPaperNmsSpawnPackets = + V1_21_11SurfPaperNmsSpawnPacketsImpl() + + override fun createPlayerPackets(): SurfPaperNmsPlayerPackets = + V1_21_11SurfPaperNmsPlayerPacketsImpl() + + override fun createPlayerChatPackets(): SurfPaperNmsPlayerChatPackets = + V1_21_11SurfPaperNmsPlayerChatPacketsImpl() + + override fun createPlayerToastPackets(): SurfPaperNmsPlayerToastPackets = + V1_21_11SurfPaperNmsPlayerToastPacketsImpl() + + override fun createTickThreadGuard(): TickThreadGuard = V1_21_11TickThreadGuard() + override fun getLibLoaderBridge(): LibLoaderBridge = V1_21_11LibLoaderBridgeImpl + + override fun getPacketBridgeHandler(): NmsPacketBridgeHandler = V1_21_11NmsPacketBridgeHandler + + override fun createPacketLoreRegistry(): PacketLoreRegistry = V1_21_11PacketLoreRegistry() + override fun createGlowingLifecycleHandler(): GlowingLifecycleHandler = + V1_21_11GlowingLifecycleHandler() + + override fun createGlowingApi(): SurfGlowingApi = V1_21_11SurfGlowingApiImpl + override fun createChannelInjector(): AbstractChannelInjector<*> = V1_21_11ChannelInjector + override fun createPacketListenerApi(): InternalPacketListenerApiBridge = V1_21_11PacketListenerApiImpl() + + override fun createPacketListeners(): List = listOf( + V1_21_11PacketLoreListener, + V1_21_11GlowingPacketListener, + ) + + override fun initialize() { + V1_21_11Reflection.initialize() + } + + override fun shutdown() { + // No cleanup needed + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11LibLoaderBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11LibLoaderBridgeImpl.kt new file mode 100644 index 000000000..376d3d9ae --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11LibLoaderBridgeImpl.kt @@ -0,0 +1,58 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges + +import dev.slne.surf.api.core.reflection.Field +import dev.slne.surf.api.core.reflection.Field.Type +import dev.slne.surf.api.core.reflection.SurfProxy +import dev.slne.surf.api.core.reflection.SurfReflection +import dev.slne.surf.api.core.reflection.createProxy +import dev.slne.surf.api.core.util.setFinalField +import dev.slne.surf.api.paper.nms.common.LibLoaderBridge +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.commodore +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.craftServer +import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader +import org.bukkit.craftbukkit.util.ApiVersion +import java.net.URLClassLoader + +@Suppress("ClassName") +object V1_21_11LibLoaderBridgeImpl : LibLoaderBridge { + + override fun getActiveCompatibilities(): MutableSet { + return craftServer.activeCompatibilities + } + + override fun convertWithCommodore( + b: ByteArray, + pluginName: String, + pluginVersion: String, + activeCompatibilities: MutableSet + ): ByteArray { + return commodore.convert( + b, + pluginName, + ApiVersion.getOrCreateVersion(pluginVersion), + activeCompatibilities + ) + } + + @Suppress("DEPRECATION") + override fun overwriteLibraryLoader(pluginClassLoader: URLClassLoader, newLoader: URLClassLoader) { + PaperPluginClassLoader::class.java.getDeclaredField("libraryLoader").apply { + setAccessible(true) + setFinalField(this, pluginClassLoader, newLoader) + } + } + + override fun getLibraryLoader(pluginClassLoader: URLClassLoader): URLClassLoader { + return PaperPluginClassLoaderProxy.instance.getLibraryLoader(pluginClassLoader as PaperPluginClassLoader) + } + + @SurfProxy(PaperPluginClassLoader::class) + interface PaperPluginClassLoaderProxy { + @Field("libraryLoader", Type.GETTER) + fun getLibraryLoader(instance: PaperPluginClassLoader): URLClassLoader + + companion object { + val instance = SurfReflection.createProxy() + } + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/listener/SurfPaperPacketListenerApiImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11PacketListenerApiImpl.kt similarity index 89% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/listener/SurfPaperPacketListenerApiImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11PacketListenerApiImpl.kt index cf095abcd..8ff01d075 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/listener/SurfPaperPacketListenerApiImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11PacketListenerApiImpl.kt @@ -1,10 +1,8 @@ -package dev.slne.surf.api.paper.server.impl.packet.listener +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.core.util.logger import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.packet.listener.SurfPaperPacketListenerApi +import dev.slne.surf.api.paper.nms.common.InternalPacketListenerApiBridge import dev.slne.surf.api.paper.packet.listener.listener.PacketListener import dev.slne.surf.api.paper.packet.listener.listener.PacketListenerResult import dev.slne.surf.api.paper.packet.listener.listener.annotation.ClientboundListener @@ -22,14 +20,13 @@ import java.util.concurrent.ConcurrentMap import java.util.concurrent.CopyOnWriteArraySet @NmsUseWithCaution -@AutoService(SurfPaperPacketListenerApi::class) -class SurfPaperPacketListenerApiImpl : SurfPaperPacketListenerApi { +class V1_21_11PacketListenerApiImpl : InternalPacketListenerApiBridge { + private typealias ListenerMethodsMap = ConcurrentHashMap, CopyOnWriteArraySet> + private val log = logger() - private val clientboundListenerMethods = - ConcurrentHashMap, CopyOnWriteArraySet>() - private val serverboundListenerMethods = - ConcurrentHashMap, CopyOnWriteArraySet>() + private val clientboundListenerMethods = ListenerMethodsMap() + private val serverboundListenerMethods = ListenerMethodsMap() private val lookup = MethodHandles.lookup() private val normalizedListenerType = MethodType.methodType( @@ -39,7 +36,7 @@ class SurfPaperPacketListenerApiImpl : SurfPaperPacketListenerApi { ) private val toBukkitPlayerHandle: MethodHandle = lookup.findStatic( - SurfPaperPacketListenerApiImpl::class.java, + V1_21_11PacketListenerApiImpl::class.java, "toBukkitPlayer", MethodType.methodType(Player::class.java, ServerPlayer::class.java) ) @@ -50,10 +47,6 @@ class SurfPaperPacketListenerApiImpl : SurfPaperPacketListenerApi { fun toBukkitPlayer(serverPlayer: ServerPlayer?): Player? = serverPlayer?.bukkitEntity } - init { - checkInstantiationByServiceLoader() - } - override fun registerListeners(listener: PacketListener) { for (method in listener.javaClass.declaredMethods) { try { @@ -174,10 +167,10 @@ class SurfPaperPacketListenerApiImpl : SurfPaperPacketListenerApi { } } - fun handleClientboundPacket( - packet: Packet<*>, - serverPlayer: ServerPlayer? - ): Packet<*>? { + override fun handleClientboundPacket(packet: Any, serverPlayer: Any?): Any? { + packet as Packet<*> + serverPlayer as ServerPlayer? + val methods = clientboundListenerMethods[packet.javaClass] ?: return packet var result: Packet<*>? = packet @@ -195,10 +188,10 @@ class SurfPaperPacketListenerApiImpl : SurfPaperPacketListenerApi { return result } - fun handleServerboundPacket( - packet: Packet<*>, - serverPlayer: ServerPlayer? - ): Packet<*>? { + override fun handleServerboundPacket(packet: Any, serverPlayer: Any?): Any? { + packet as Packet<*> + serverPlayer as ServerPlayer? + val methods = serverboundListenerMethods[packet.javaClass] ?: return packet var result: Packet<*>? = packet @@ -228,4 +221,4 @@ class SurfPaperPacketListenerApiImpl : SurfPaperPacketListenerApi { val listener: PacketListener, val invoker: ListenerInvoker, ) -} +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/SurfPaperNmsBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsBridgeImpl.kt similarity index 84% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/SurfPaperNmsBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsBridgeImpl.kt index 12ae2c753..2f94281a0 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/SurfPaperNmsBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsBridgeImpl.kt @@ -1,13 +1,11 @@ -package dev.slne.surf.api.paper.server.impl.nms +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges -import com.google.auto.service.AutoService import com.google.common.flogger.StackSize -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.core.util.logger import dev.slne.surf.api.paper.api.nms.listener.NmsClientboundPacketListener import dev.slne.surf.api.paper.api.nms.listener.NmsServerboundPacketListener import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.nms.SurfPaperNmsBridge +import dev.slne.surf.api.paper.nms.common.InternalNmsBridge import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket import dev.slne.surf.api.paper.packet.listener.listener.PacketListenerResult @@ -15,19 +13,14 @@ import org.bukkit.entity.Player import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArraySet -@AutoService(SurfPaperNmsBridge::class) @NmsUseWithCaution -class SurfPaperNmsBridgeImpl : SurfPaperNmsBridge { - private val log = logger() +class V1_21_11SurfPaperNmsBridgeImpl : InternalNmsBridge { + private typealias PacketListenerMap = ConcurrentHashMap, CopyOnWriteArraySet> - private val serverboundPacketListeners = - ConcurrentHashMap, CopyOnWriteArraySet>>() - private val clientboundPacketListeners = - ConcurrentHashMap, CopyOnWriteArraySet>>() + private val log = logger() - init { - checkInstantiationByServiceLoader() - } + private val serverboundPacketListeners = PacketListenerMap>() + private val clientboundPacketListeners = PacketListenerMap>() override fun registerServerboundPacketListener(listener: NmsServerboundPacketListener<*>) { val packetClass = listener.packetClass @@ -76,7 +69,7 @@ class SurfPaperNmsBridgeImpl : SurfPaperNmsBridge { } @Suppress("UNCHECKED_CAST") - fun handleServerboundPacket( + override fun handleServerboundPacket( packet: Packet, player: Player?, ): Packet? { @@ -104,7 +97,7 @@ class SurfPaperNmsBridgeImpl : SurfPaperNmsBridge { } @Suppress("UNCHECKED_CAST") - fun handleClientboundPacket( + override fun handleClientboundPacket( packet: Packet, player: Player?, ): Packet? { diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsCommandArgumentTypesBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsCommandArgumentTypesBridgeImpl.kt similarity index 85% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsCommandArgumentTypesBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsCommandArgumentTypesBridgeImpl.kt index 6040a8c92..86d6964de 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsCommandArgumentTypesBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsCommandArgumentTypesBridgeImpl.kt @@ -1,14 +1,12 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges -import com.google.auto.service.AutoService import com.mojang.brigadier.arguments.ArgumentType import com.mojang.brigadier.context.CommandContext import com.mojang.brigadier.exceptions.CommandSyntaxException -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommandArgumentTypesBridge -import dev.slne.surf.api.paper.server.nms.AdventureNBT -import dev.slne.surf.api.paper.server.reflection.Reflection +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.AdventureNBT +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection import net.bytebuddy.ByteBuddy import net.bytebuddy.dynamic.loading.ClassLoadingStrategy import net.bytebuddy.dynamic.scaffold.TypeValidation @@ -21,11 +19,7 @@ import java.lang.reflect.InvocationHandler import java.util.concurrent.ConcurrentHashMap @NmsUseWithCaution -@AutoService(SurfPaperNmsCommandArgumentTypesBridge::class) -class SurfPaperNmsCommandArgumentTypesBridgeImpl : SurfPaperNmsCommandArgumentTypesBridge { - init { - checkInstantiationByServiceLoader() - } +class V1_21_11SurfPaperNmsCommandArgumentTypesBridgeImpl : SurfPaperNmsCommandArgumentTypesBridge { override fun compoundTag(): ArgumentType<*> { return CompoundTagArgument.compoundTag() @@ -42,8 +36,8 @@ class SurfPaperNmsCommandArgumentTypesBridgeImpl : SurfPaperNmsCommandArgumentTy converter: OpenedResultConverter ): ArgumentType { val wrappedConverter = OpenedResultConverterImpl.of(converter) - val wrapped = Reflection.VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY.wrap( - Reflection.VANILLA_ARGUMENT_PROVIDER_PROXY.provider(), + val wrapped = V1_21_11Reflection.VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY.wrap( + V1_21_11Reflection.VANILLA_ARGUMENT_PROVIDER_PROXY.provider(), base, wrappedConverter ) as ArgumentType @@ -110,4 +104,4 @@ class SurfPaperNmsCommandArgumentTypesBridgeImpl : SurfPaperNmsCommandArgumentTy } } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsCommonBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsCommonBridgeImpl.kt similarity index 81% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsCommonBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsCommonBridgeImpl.kt index ae0d152e8..4bf87f50f 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsCommonBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsCommonBridgeImpl.kt @@ -1,14 +1,12 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.dialog.noticeDialogWithBuilder import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommonBridge -import dev.slne.surf.api.paper.server.nms.toNms -import dev.slne.surf.api.paper.server.nms.toNmsBlock -import dev.slne.surf.api.paper.server.nms.toNmsItem -import dev.slne.surf.api.paper.server.reflection.Reflection +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNmsBlock +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNmsItem +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection import io.papermc.paper.configuration.GlobalConfiguration import net.kyori.adventure.text.Component import net.minecraft.network.protocol.common.ClientboundClearDialogPacket @@ -21,12 +19,8 @@ import org.bukkit.block.data.BlockData import org.bukkit.entity.Player import java.net.InetSocketAddress -@AutoService(SurfPaperNmsCommonBridge::class) @NmsUseWithCaution -class SurfPaperNmsCommonBridgeImpl : SurfPaperNmsCommonBridge { - init { - checkInstantiationByServiceLoader() - } +class V1_21_11SurfPaperNmsCommonBridgeImpl : SurfPaperNmsCommonBridge { @Suppress("DEPRECATION") override fun nextEntityId(): Int { @@ -86,7 +80,7 @@ class SurfPaperNmsCommonBridgeImpl : SurfPaperNmsCommonBridge { override fun getServerIp(): InetSocketAddress { val channels = - Reflection.SERVER_CONNECTION_LISTENER_PROXY.getChannels(MinecraftServer.getServer().connection) + V1_21_11Reflection.SERVER_CONNECTION_LISTENER_PROXY.getChannels(MinecraftServer.getServer().connection) val channel = channels.firstOrNull() ?: error("No channels found in server connection listener proxy") diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsEntityBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsEntityBridgeImpl.kt similarity index 75% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsEntityBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsEntityBridgeImpl.kt index 88268e8c2..aafcd14a0 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsEntityBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsEntityBridgeImpl.kt @@ -1,15 +1,13 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges import ca.spottedleaf.moonrise.common.util.TickThread -import com.google.auto.service.AutoService import com.mojang.brigadier.exceptions.CommandSyntaxException import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsEntityBridge -import dev.slne.surf.api.paper.server.nms.AdventureNBT -import dev.slne.surf.api.paper.server.nms.toNms -import dev.slne.surf.api.paper.server.nms.toNmsHolder +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.AdventureNBT +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNmsHolder import dev.slne.surf.api.paper.util.chunkX import dev.slne.surf.api.paper.util.chunkZ import io.papermc.paper.math.FinePosition @@ -20,11 +18,7 @@ import org.bukkit.World import org.bukkit.entity.EntityType @NmsUseWithCaution -@AutoService(SurfPaperNmsEntityBridge::class) -class SurfPaperNmsEntityBridgeImpl : SurfPaperNmsEntityBridge { - init { - checkInstantiationByServiceLoader() - } +class V1_21_11SurfPaperNmsEntityBridgeImpl : SurfPaperNmsEntityBridge { @Suppress("UnstableApiUsage") override fun createEntityByNbt( @@ -56,4 +50,4 @@ class SurfPaperNmsEntityBridgeImpl : SurfPaperNmsEntityBridge { throw WrapperCommandSyntaxException(e) } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsGlowingBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsGlowingBridgeImpl.kt new file mode 100644 index 000000000..b8af4a206 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsGlowingBridgeImpl.kt @@ -0,0 +1,56 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsGlowingBridge +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11TeamData +import dev.slne.surf.api.paper.server.nms.v1_21_11.packet.listener.V1_21_11GlowingPacketListener +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket +import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket +import net.minecraft.network.syncher.SynchedEntityData.DataValue +import org.bukkit.entity.Entity + +@NmsUseWithCaution +object V1_21_11SurfPaperNmsGlowingBridgeImpl : SurfPaperNmsGlowingBridge { + fun createTeam(data: V1_21_11TeamData): PacketOperation = + V1_21_11PacketOperationImpl.simple { + ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(data.team, true) + } + + fun addEntityToTeam(data: V1_21_11TeamData, entry: String): PacketOperation = + V1_21_11PacketOperationImpl.simple { + ClientboundSetPlayerTeamPacket.createPlayerPacket( + data.team, + entry, + ClientboundSetPlayerTeamPacket.Action.ADD + ) + } + + fun removeEntityFromTeam(data: V1_21_11TeamData, entry: String): PacketOperation = + V1_21_11PacketOperationImpl.simple { + ClientboundSetPlayerTeamPacket.createPlayerPacket( + data.team, + entry, + ClientboundSetPlayerTeamPacket.Action.REMOVE + ) + } + + fun setEntityFlags(entityId: Int, flags: Byte, ignorePacket: Boolean = false): PacketOperation = + V1_21_11PacketOperationImpl.simple { + val dataAccessor = V1_21_11Reflection.ENTITY_PROXY.getDataFlagsSharedId() + val data = DataValue(dataAccessor.id(), dataAccessor.serializer, flags) + ClientboundSetEntityDataPacket(entityId, listOf(data)).also { + if (ignorePacket) { + V1_21_11GlowingPacketListener.ignorePacket(it) + } + } + } + + override fun getCurrentFlags(entity: Entity): Byte { + val dataAccessor = V1_21_11Reflection.ENTITY_PROXY.getDataFlagsSharedId() + return entity.toNms().entityData.get(dataAccessor) + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsItemBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsItemBridgeImpl.kt similarity index 59% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsItemBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsItemBridgeImpl.kt index 22cbfa5ff..2050fecc2 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsItemBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsItemBridgeImpl.kt @@ -1,21 +1,15 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsItemBridge -import dev.slne.surf.api.paper.server.nms.nms +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.nms +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection import net.minecraft.core.component.DataComponentMap import net.minecraft.core.component.DataComponents import org.bukkit.inventory.ItemType -@AutoService(SurfPaperNmsItemBridge::class) @NmsUseWithCaution -class SurfPaperNmsItemBridgeImpl : SurfPaperNmsItemBridge { - init { - checkInstantiationByServiceLoader() - } - +class V1_21_11SurfPaperNmsItemBridgeImpl : SurfPaperNmsItemBridge { override fun setDefaultMaxStackSize(item: ItemType, maxStackSize: Int) { require(maxStackSize in 1..100) { "Max stack size must be between 1 and 100" } @@ -25,6 +19,7 @@ class SurfPaperNmsItemBridgeImpl : SurfPaperNmsItemBridge { .set(DataComponents.MAX_STACK_SIZE, maxStackSize) .build() - nmsItem.builtInRegistryHolder().bindComponents(updatedComponents) + + V1_21_11Reflection.ITEM_PROXY.setComponents(nmsItem, updatedComponents) } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsLootTableBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsLootTableBridgeImpl.kt similarity index 87% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsLootTableBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsLootTableBridgeImpl.kt index 66c622970..df9a5041a 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsLootTableBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsLootTableBridgeImpl.kt @@ -1,12 +1,11 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges -import com.google.auto.service.AutoService import dev.slne.surf.api.core.util.emptyObjectList import dev.slne.surf.api.core.util.mutableObjectListOf import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsLootTableBridge -import dev.slne.surf.api.paper.server.nms.toBukkit -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toBukkit +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms import net.minecraft.server.MinecraftServer import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.storage.loot.LootParams @@ -18,9 +17,8 @@ import org.bukkit.entity.LivingEntity import org.bukkit.inventory.ItemStack import kotlin.jvm.optionals.getOrNull -@AutoService(SurfPaperNmsLootTableBridge::class) @NmsUseWithCaution -class SurfPaperNmsLootTableBridgeImpl : SurfPaperNmsLootTableBridge { +class V1_21_11SurfPaperNmsLootTableBridgeImpl : SurfPaperNmsLootTableBridge { override fun getDifferentLootTable( entity: LivingEntity, damageSource: DamageSource, @@ -54,4 +52,4 @@ class SurfPaperNmsLootTableBridgeImpl : SurfPaperNmsLootTableBridge { return lootTable.getRandomItems(lootParams, nmsEntity.lootTableSeed) .mapTo(mutableObjectListOf()) { it.toBukkit() } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsNbtBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsNbtBridgeImpl.kt new file mode 100644 index 000000000..6e81bf5ae --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsNbtBridgeImpl.kt @@ -0,0 +1,62 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges + +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsNbtBridge +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toBukkit +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import net.minecraft.core.component.DataComponentPatch +import net.minecraft.core.component.DataComponents +import net.minecraft.nbt.CompoundTag +import net.minecraft.world.item.component.CustomData +import net.minecraft.world.item.component.TypedEntityData +import org.bukkit.entity.EntityType +import org.bukkit.inventory.ItemStack +import kotlin.jvm.optionals.getOrNull + +@NmsUseWithCaution +class V1_21_11SurfPaperNmsNbtBridgeImpl : SurfPaperNmsNbtBridge { + private val log = logger() + + override fun makeItemStackEntityInvisible( + itemStack: ItemStack, + invisibleEntityType: EntityType, + ): ItemStack { + val nmsStack = itemStack.toNms() + + val nbt = CompoundTag() + nbt.putBoolean("Invisible", true) + nbt.putString("id", invisibleEntityType.key.asString()) + + val entityData = TypedEntityData.decodeEntity(nbt) + + val patch = DataComponentPatch.builder() + .set(DataComponents.ENTITY_DATA, entityData) + .build() + + nmsStack.applyComponents(patch) + + return nmsStack.toBukkit() + } + + @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") + override fun getNbtString( + itemStack: ItemStack, + key: String, + ): String { + log.atWarning() + .atMostEvery(30, java.util.concurrent.TimeUnit.SECONDS) + .log( + ("Using deprecated method getNbtString(ItemStack, String) in SurfBukkitNmsNbtBridgeImpl." + + " ItemStacks now use DataComponents and nbt keys are not used. Please update your" + + " code to use DataComponents instead.") + ) + + return itemStack.toNms().components + .getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY) + .unsafe + .getString(key) + .getOrNull() + ?: "{}" + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsStatsBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsStatsBridgeImpl.kt new file mode 100644 index 000000000..a18b4536e --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/V1_21_11SurfPaperNmsStatsBridgeImpl.kt @@ -0,0 +1,21 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsStatsBridge +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection +import org.bukkit.entity.Player + +@NmsUseWithCaution +class V1_21_11SurfPaperNmsStatsBridgeImpl : SurfPaperNmsStatsBridge { + + override fun getPlayerStatsAsJson(player: Player): String { + val gson = V1_21_11Reflection.SERVER_STATS_COUNTER_PROXY.getGson() + val jsonElement = V1_21_11Reflection.SERVER_STATS_COUNTER_PROXY.toJson(player.toNms().stats) + return gson.toJson(jsonElement) + } + + override fun savePlayerStatsToFile(player: Player) { + player.toNms().stats.save() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/V1_21_11PacketOperationImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/V1_21_11PacketOperationImpl.kt new file mode 100644 index 000000000..9e00e2afd --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/V1_21_11PacketOperationImpl.kt @@ -0,0 +1,115 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets + +import com.google.common.flogger.FluentLogger +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientGamePacketListener +import net.minecraft.network.protocol.game.ClientboundBundlePacket +import org.bukkit.entity.Player +import java.util.* + +class V1_21_11PacketOperationImpl : PacketOperation { + private var operation: Operation + + private constructor(operation: Operation) { + this.operation = operation + } + + private constructor() { + this.operation = Operation.empty() + } + + override fun execute(player: Player) { + val connection = player.toNms().connection + val packets = operation.apply( + player, + LinkedList>() + ) + + if (packets.isEmpty()) { + return + } + + if (packets.size == 1) { + connection.send(packets.first()) + return + } + + connection.send(ClientboundBundlePacket(packets)) + } + + override fun add(operation: PacketOperation): V1_21_11PacketOperationImpl { + require(operation is V1_21_11PacketOperationImpl) { "operation must be an instance of V1_21_11PacketOperationImpl" } + + this.operation = this.operation.andThen(operation.operation) + return this + } + + override fun isEmpty(): Boolean { + val operation = operation + return operation is EmptyOperation && operation.empty + } + + fun interface Operation { + fun apply( + player: Player, + packets: LinkedList>, + ): LinkedList> + + fun andThen(after: Operation): Operation { + return Operation { player, packets -> + after.apply(player, apply(player, packets)) + } + } + + companion object { + fun empty() = EmptyOperation() + } + } + + class EmptyOperation : Operation { + var empty: Boolean = true + private set + + override fun apply( + player: Player, + packets: LinkedList>, + ): LinkedList> { + return packets + } + + override fun andThen(after: Operation): Operation { + empty = false + return super.andThen(after) + } + } + + companion object { + private val logger: FluentLogger = FluentLogger.forEnclosingClass() + + @JvmStatic + fun empty(): V1_21_11PacketOperationImpl { + return V1_21_11PacketOperationImpl() + } + + @JvmStatic + fun complex(operation: Operation): V1_21_11PacketOperationImpl { + return V1_21_11PacketOperationImpl(operation) + } + + fun simple(packetSupplier: (Player) -> Packet): V1_21_11PacketOperationImpl { + return V1_21_11PacketOperationImpl { player, packets -> + packets.add(packetSupplier(player)) + packets + } + } + + fun task(task: (Player) -> Unit): V1_21_11PacketOperationImpl { + return V1_21_11PacketOperationImpl { player, packets -> + task(player) + packets + } + } + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/V1_21_11SurfPaperNmsPacketBridgesImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/V1_21_11SurfPaperNmsPacketBridgesImpl.kt new file mode 100644 index 000000000..2f248d5aa --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/V1_21_11SurfPaperNmsPacketBridgesImpl.kt @@ -0,0 +1,12 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.SurfPaperNmsPacketBridges + +@NmsUseWithCaution +class V1_21_11SurfPaperNmsPacketBridgesImpl : SurfPaperNmsPacketBridges { + + override fun createEmptyPacketOperation(): V1_21_11PacketOperationImpl { + return V1_21_11PacketOperationImpl.empty() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/block/V1_21_11SurfPaperNmsBlockPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/block/V1_21_11SurfPaperNmsBlockPacketsImpl.kt new file mode 100644 index 000000000..d57ab8cbc --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/block/V1_21_11SurfPaperNmsBlockPacketsImpl.kt @@ -0,0 +1,31 @@ +@file:Suppress("UnstableApiUsage") + +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.block + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.block.SurfPaperNmsBlockPackets +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import io.papermc.paper.math.BlockPosition +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket +import org.bukkit.block.data.BlockData + +@NmsUseWithCaution +class V1_21_11SurfPaperNmsBlockPacketsImpl : SurfPaperNmsBlockPackets { + + override fun updateBlockData(position: BlockPosition, blockData: BlockData) = + V1_21_11PacketOperationImpl.simple { + ClientboundBlockUpdatePacket( + position.toNms(), + blockData.toNms() + ) + } + + + override fun resetBlock(position: BlockPosition) = V1_21_11PacketOperationImpl.simple { + ClientboundBlockUpdatePacket( + it.toNms().level(), + position.toNms() + ) + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/entity/SurfPaperNmsSpawnPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/entity/V1_21_11SurfPaperNmsSpawnPacketsImpl.kt similarity index 89% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/entity/SurfPaperNmsSpawnPacketsImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/entity/V1_21_11SurfPaperNmsSpawnPacketsImpl.kt index b72a70286..6a905e719 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/entity/SurfPaperNmsSpawnPacketsImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/entity/V1_21_11SurfPaperNmsSpawnPacketsImpl.kt @@ -1,13 +1,12 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets.entity +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.entity -import com.google.auto.service.AutoService import com.google.common.flogger.StackSize import com.mojang.math.Transformation import dev.slne.surf.api.core.util.logger import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.packets.entity.* -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms import io.papermc.paper.math.BlockPosition import io.papermc.paper.math.FinePosition import it.unimi.dsi.fastutil.ints.IntList @@ -29,23 +28,22 @@ import kotlin.experimental.inv import kotlin.experimental.or @Suppress("UnstableApiUsage") -@AutoService(SurfPaperNmsSpawnPackets::class) @NmsUseWithCaution -class SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { +class V1_21_11SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { private val log = logger() override fun despawn(entityIds: IntList) = - PacketOperationImpl.simple { ClientboundRemoveEntitiesPacket(entityIds) } + V1_21_11PacketOperationImpl.simple { ClientboundRemoveEntitiesPacket(entityIds) } override fun despawn(vararg entityId: Int) = - PacketOperationImpl.simple { ClientboundRemoveEntitiesPacket(*entityId) } + V1_21_11PacketOperationImpl.simple { ClientboundRemoveEntitiesPacket(*entityId) } override fun spawnItemDisplay( entityId: Int, position: FinePosition, settings: ItemDisplaySettings, - ) = PacketOperationImpl.complex { player, packets -> + ) = V1_21_11PacketOperationImpl.complex { player, packets -> val serverPlayer = player.toNms() val display = Display.ItemDisplay(EntityType.ITEM_DISPLAY, serverPlayer.level()).apply { id = entityId @@ -66,7 +64,7 @@ class SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { entityId: Int, position: FinePosition, settings: TextDisplaySettings, - ) = PacketOperationImpl.complex { player, packets -> + ) = V1_21_11PacketOperationImpl.complex { player, packets -> val serverPlayer = player.toNms() val display = Display.TextDisplay(EntityType.TEXT_DISPLAY, serverPlayer.level()).apply { id = entityId @@ -108,7 +106,7 @@ class SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { entityId: Int, position: BlockPosition, settings: SignBlockUpdateSettings, - ) = PacketOperationImpl.complex { player, packets -> + ) = V1_21_11PacketOperationImpl.complex { player, packets -> val nbt = CompoundTag() val registryLookup = MinecraftServer.getServer().registryAccess() writeUpdateSignToTag(nbt, registryLookup, settings.frontText, settings.backText) @@ -121,7 +119,7 @@ class SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { entityId: Int, position: FinePosition, settings: BlockDisplaySettings, - ) = PacketOperationImpl.complex { player, packets -> + ) = V1_21_11PacketOperationImpl.complex { player, packets -> val serverPlayer = player.toNms() val display = Display.BlockDisplay(EntityType.BLOCK_DISPLAY, serverPlayer.level()).apply { id = entityId @@ -143,7 +141,7 @@ class SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { pitch: Float, deltaMovement: FinePosition?, onGround: Boolean, - ) = PacketOperationImpl.simple { + ) = V1_21_11PacketOperationImpl.simple { ClientboundTeleportEntityPacket.teleport( entityId, PositionMoveRotation(position.toNms(), deltaMovement?.toNms() ?: Vec3.ZERO, yaw, pitch), diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerChatPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerChatPacketsImpl.kt similarity index 83% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerChatPacketsImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerChatPacketsImpl.kt index 1a89fa287..5be4f1ebc 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerChatPacketsImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerChatPacketsImpl.kt @@ -1,12 +1,11 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets.player +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.player -import com.google.auto.service.AutoService import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation import dev.slne.surf.api.paper.nms.bridges.packets.player.LastSeenMessagesPacked import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerChatPackets -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms import net.kyori.adventure.chat.SignedMessage import net.kyori.adventure.text.Component import net.minecraft.network.chat.ChatType @@ -20,8 +19,7 @@ import java.util.* import net.minecraft.network.chat.MessageSignature as NmsMessageSignature @NmsUseWithCaution -@AutoService(SurfPaperNmsPlayerChatPackets::class) -class SurfPaperNmsPlayerChatPacketsImpl : SurfPaperNmsPlayerChatPackets { +class V1_21_11SurfPaperNmsPlayerChatPacketsImpl : SurfPaperNmsPlayerChatPackets { override fun sendPlayerChatMessagePacket( senderUuid: UUID, senderDisplayName: Component, @@ -33,7 +31,7 @@ class SurfPaperNmsPlayerChatPacketsImpl : SurfPaperNmsPlayerChatPackets { content: String, unsignedContent: Component?, lastSeen: LastSeenMessagesPacked, - ): PacketOperation = PacketOperationImpl.simple { player -> + ): PacketOperation = V1_21_11PacketOperationImpl.simple { player -> val messageSignature = signature?.let { NmsMessageSignature(it.bytes()) } val signedBody = SignedMessageBody.Packed(content, timestamp, salt, lastSeen.toNms()) @@ -63,4 +61,4 @@ class SurfPaperNmsPlayerChatPacketsImpl : SurfPaperNmsPlayerChatPackets { return LastSeenMessages.Packed(list) } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerPacketsImpl.kt similarity index 63% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerPacketsImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerPacketsImpl.kt index 1e9f7e7fc..4314e873a 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerPacketsImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerPacketsImpl.kt @@ -1,13 +1,11 @@ @file:Suppress("UnstableApiUsage") -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets.player +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.player -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerPackets -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms import io.papermc.paper.math.BlockPosition import net.kyori.adventure.text.Component import net.minecraft.network.protocol.game.ClientboundContainerClosePacket @@ -17,23 +15,19 @@ import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket import org.bukkit.event.inventory.InventoryType import org.bukkit.inventory.ItemStack -@AutoService(SurfPaperNmsPlayerPackets::class) @NmsUseWithCaution -class SurfPaperNmsPlayerPacketsImpl : SurfPaperNmsPlayerPackets { - init { - checkInstantiationByServiceLoader() - } +class V1_21_11SurfPaperNmsPlayerPacketsImpl : SurfPaperNmsPlayerPackets { override fun openSignEditor( position: BlockPosition, frontSide: Boolean, - ) = PacketOperationImpl.simple { ClientboundOpenSignEditorPacket(position.toNms(), frontSide) } + ) = V1_21_11PacketOperationImpl.simple { ClientboundOpenSignEditorPacket(position.toNms(), frontSide) } override fun openInventory( syncId: Int, type: InventoryType, title: Component, - ) = PacketOperationImpl.simple { + ) = V1_21_11PacketOperationImpl.simple { ClientboundOpenScreenPacket( syncId, type.toNms(), @@ -46,7 +40,7 @@ class SurfPaperNmsPlayerPacketsImpl : SurfPaperNmsPlayerPackets { revision: Int, slot: Int, item: ItemStack, - ) = PacketOperationImpl.simple { + ) = V1_21_11PacketOperationImpl.simple { ClientboundContainerSetSlotPacket( syncId, revision, @@ -56,5 +50,5 @@ class SurfPaperNmsPlayerPacketsImpl : SurfPaperNmsPlayerPackets { } override fun closeInventory(syncId: Int) = - PacketOperationImpl.simple { ClientboundContainerClosePacket(syncId) } + V1_21_11PacketOperationImpl.simple { ClientboundContainerClosePacket(syncId) } } diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerToastPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerToastPacketsImpl.kt similarity index 80% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerToastPacketsImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerToastPacketsImpl.kt index 38016ef31..c222bf7e4 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/player/SurfPaperNmsPlayerToastPacketsImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/bridges/packets/player/V1_21_11SurfPaperNmsPlayerToastPacketsImpl.kt @@ -1,11 +1,10 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets.player +package dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.player -import com.google.auto.service.AutoService import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerToastPackets import dev.slne.surf.api.paper.nms.bridges.packets.player.toast.Toast -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms import net.minecraft.advancements.Advancement import net.minecraft.advancements.AdvancementProgress import net.minecraft.advancements.AdvancementRequirements @@ -16,9 +15,8 @@ import java.util.* @NmsUseWithCaution -@AutoService(SurfPaperNmsPlayerToastPackets::class) -class SurfPaperNmsPlayerToastPacketsImpl : SurfPaperNmsPlayerToastPackets { - override fun showToast(toast: Toast) = PacketOperationImpl.complex { _, packets -> +class V1_21_11SurfPaperNmsPlayerToastPacketsImpl : SurfPaperNmsPlayerToastPackets { + override fun showToast(toast: Toast) = V1_21_11PacketOperationImpl.complex { _, packets -> val id = Identifier.fromNamespaceAndPath("surfapi", "toast_${UUID.randomUUID()}") packets.add(showPacket(id, toast)) @@ -59,4 +57,4 @@ class SurfPaperNmsPlayerToastPacketsImpl : SurfPaperNmsPlayerToastPackets { private const val CRITERION_ID = "surfapi_toast" private val requirements by lazy { AdvancementRequirements.allOf(listOf(CRITERION_ID)) } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/extensions/AdventureNBT.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/extensions/AdventureNBT.kt new file mode 100644 index 000000000..9e1c5a98f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/extensions/AdventureNBT.kt @@ -0,0 +1,96 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.extensions + +import net.kyori.adventure.nbt.* +import net.minecraft.nbt.* + +object AdventureNBT { + fun toNms( + adventure: CompoundBinaryTag, + accounter: NbtAccounter = NbtAccounter.unlimitedHeap() + ): CompoundTag { + return CompoundTag().also { tag -> + for ((key, value) in adventure) { + tag.put(key, toNms(value, accounter)) + } + } + } + + fun toNms( + adventure: BinaryTag, + accounter: NbtAccounter = NbtAccounter.unlimitedHeap() + ): Tag { + accounter.pushDepth() + + val nmsTag = when (adventure) { + is IntBinaryTag -> IntTag.valueOf(adventure.value()) + is ByteBinaryTag -> ByteTag.valueOf(adventure.value()) + is FloatBinaryTag -> FloatTag.valueOf(adventure.value()) + is LongBinaryTag -> LongTag.valueOf(adventure.value()) + is DoubleBinaryTag -> DoubleTag.valueOf(adventure.value()) + is ShortBinaryTag -> ShortTag.valueOf(adventure.value()) + is StringBinaryTag -> StringTag.valueOf(adventure.value()) + is ByteArrayBinaryTag -> ByteArrayTag(adventure.value()) + is IntArrayBinaryTag -> IntArrayTag(adventure.value()) + is LongArrayBinaryTag -> LongArrayTag(adventure.value()) + is EndBinaryTag -> EndTag.INSTANCE + is ListBinaryTag -> if (adventure.isEmpty) { + ListTag() + } else { + val list = ListTag() + for (entry in adventure) { + val nms = toNms(entry) + list.add(nms) + } + list + } + + is CompoundBinaryTag -> { + val tag = CompoundTag() + for ((key, entry) in adventure) { + val nms = toNms(entry) + tag.put(key, nms) + } + tag + } + + else -> throw IllegalArgumentException("Unsupported tag type: ${adventure::class}") + } + + accounter.popDepth() + + return nmsTag + } + + fun fromNms(nms: CompoundTag): CompoundBinaryTag = CompoundBinaryTag.builder().also { builder -> + nms.forEach { key, tag -> builder.put(key, fromNms(tag)) } + }.build() + + fun fromNms(nms: Tag): BinaryTag = when (nms) { + is IntTag -> IntBinaryTag.intBinaryTag(nms.intValue()) + is ByteTag -> ByteBinaryTag.byteBinaryTag(nms.byteValue()) + is FloatTag -> FloatBinaryTag.floatBinaryTag(nms.floatValue()) + is LongTag -> LongBinaryTag.longBinaryTag(nms.longValue()) + is DoubleTag -> DoubleBinaryTag.doubleBinaryTag(nms.doubleValue()) + is ShortTag -> ShortBinaryTag.shortBinaryTag(nms.shortValue()) + is StringTag -> StringBinaryTag.stringBinaryTag(nms.value()) + is ByteArrayTag -> ByteArrayBinaryTag.byteArrayBinaryTag(*nms.asByteArray) + is IntArrayTag -> IntArrayBinaryTag.intArrayBinaryTag(*nms.asIntArray) + is LongArrayTag -> LongArrayBinaryTag.longArrayBinaryTag(*nms.asLongArray) + is EndTag -> EndBinaryTag.endBinaryTag() + is ListTag -> { + val tag = ListBinaryTag.heterogeneousListBinaryTag() + for (t in nms) { + tag.add(fromNms(t)) + } + tag.build() + } + + is CompoundTag -> { + val adventure = CompoundBinaryTag.builder() + nms.forEach { key, tag -> + adventure.put(key, fromNms(tag)) + } + adventure.build() + } + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/extensions/nms-extensions.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/extensions/nms-extensions.kt new file mode 100644 index 000000000..a99af87ee --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/extensions/nms-extensions.kt @@ -0,0 +1,150 @@ +@file:Suppress("UnstableApiUsage") + +package dev.slne.surf.api.paper.server.nms.v1_21_11.extensions + +import dev.slne.surf.api.paper.extensions.server +import dev.slne.surf.api.paper.nms.bridges.packets.entity.SignBlockUpdateSettings +import io.papermc.paper.advancement.AdvancementDisplay +import io.papermc.paper.advancement.AdvancementDisplay.Frame.* +import io.papermc.paper.adventure.PaperAdventure +import io.papermc.paper.math.BlockPosition +import io.papermc.paper.math.FinePosition +import io.papermc.paper.math.Position +import net.minecraft.advancements.AdvancementType +import net.minecraft.core.BlockPos +import net.minecraft.core.Holder +import net.minecraft.network.chat.Component +import net.minecraft.server.level.ServerLevel +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.Display +import net.minecraft.world.inventory.MenuType +import net.minecraft.world.item.DyeColor +import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemDisplayContext +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.entity.SignText +import net.minecraft.world.phys.Vec3 +import org.bukkit.Material +import org.bukkit.Server +import org.bukkit.World +import org.bukkit.block.BlockState +import org.bukkit.block.data.BlockData +import org.bukkit.craftbukkit.CraftServer +import org.bukkit.craftbukkit.CraftWorld +import org.bukkit.craftbukkit.block.CraftBlockState +import org.bukkit.craftbukkit.block.data.CraftBlockData +import org.bukkit.craftbukkit.damage.CraftDamageSource +import org.bukkit.craftbukkit.entity.CraftEntity +import org.bukkit.craftbukkit.entity.CraftEntityType +import org.bukkit.craftbukkit.entity.CraftLivingEntity +import org.bukkit.craftbukkit.entity.CraftPlayer +import org.bukkit.craftbukkit.inventory.CraftItemStack +import org.bukkit.craftbukkit.inventory.CraftItemType +import org.bukkit.craftbukkit.util.Commodore +import org.bukkit.craftbukkit.util.CraftMagicNumbers +import org.bukkit.damage.DamageSource +import org.bukkit.entity.Display.Billboard +import org.bukkit.entity.Entity +import org.bukkit.entity.EntityType +import org.bukkit.entity.ItemDisplay.ItemDisplayTransform +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryType +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.ItemType +import org.spongepowered.math.imaginary.Quaternionf +import org.spongepowered.math.vector.Vector3f +import net.kyori.adventure.text.Component as AdventureComponent +import net.minecraft.world.item.ItemStack as NmsItemStack +import net.minecraft.world.level.block.state.BlockState as NmsBlockState +import org.joml.Quaternionf as NmsQuaternionf +import org.joml.Vector3f as NmsVector3f + +fun Player.toNms(): ServerPlayer = (this as CraftPlayer).handle +fun Material.toNmsBlock(): Block = CraftMagicNumbers.getBlock(this) +fun Material.toNmsItem(): Item = CraftMagicNumbers.getItem(this) +fun BlockData.toNms(): NmsBlockState = (this as CraftBlockData).state +fun Vector3f?.toNms(): NmsVector3f? = + if (this == null) null else NmsVector3f(this.x(), this.y(), this.z()) + +fun FinePosition.toNms() = Vec3(x(), y(), z()) +fun BlockState.toNms(): NmsBlockState = (this as CraftBlockState).handle +fun Quaternionf?.toNms(): NmsQuaternionf? = + if (this == null) null else NmsQuaternionf(x(), y(), z(), w()) + +fun Billboard.toNms(): Display.BillboardConstraints = + Display.BillboardConstraints.valueOf(this.name) + +fun ItemStack.toNms(): NmsItemStack = CraftItemStack.asNMSCopy(this) +fun ItemDisplayTransform.toNms(): ItemDisplayContext = ItemDisplayContext.BY_ID.apply(this.ordinal) +fun NmsItemStack.toBukkit(): ItemStack = CraftItemStack.asBukkitCopy(this) +val ItemType.nms: Item get() = CraftItemType.bukkitToMinecraftNew(this) +fun BlockPosition.toNms(): BlockPos = BlockPos(blockX(), blockY(), blockZ()) +fun SignBlockUpdateSettings.SignText.toNms(): SignText { + val lines = arrayOf( + line1.toNms(), + line2.toNms(), + line3.toNms(), + line4.toNms() + ) + + return SignText(lines, lines, DyeColor.BLACK, false) +} + +fun InventoryType.toNms(): MenuType<*> = when (this) { + InventoryType.ANVIL -> MenuType.ANVIL + InventoryType.BEACON -> MenuType.BEACON + InventoryType.BLAST_FURNACE -> MenuType.BLAST_FURNACE + InventoryType.BREWING -> MenuType.BREWING_STAND + InventoryType.CARTOGRAPHY -> MenuType.CARTOGRAPHY_TABLE + InventoryType.CHEST -> MenuType.GENERIC_9x6 + InventoryType.DISPENSER, InventoryType.DROPPER -> MenuType.GENERIC_3x3 + InventoryType.ENCHANTING -> MenuType.ENCHANTMENT + InventoryType.FURNACE -> MenuType.FURNACE + InventoryType.GRINDSTONE -> MenuType.GRINDSTONE + InventoryType.HOPPER -> MenuType.HOPPER + InventoryType.LECTERN -> MenuType.LECTERN + InventoryType.LOOM -> MenuType.LOOM + InventoryType.MERCHANT -> MenuType.MERCHANT + InventoryType.SHULKER_BOX -> MenuType.SHULKER_BOX + InventoryType.SMOKER -> MenuType.SMOKER + InventoryType.SMITHING -> MenuType.SMITHING + InventoryType.STONECUTTER -> MenuType.STONECUTTER + InventoryType.PLAYER -> MenuType.GENERIC_9x4 + InventoryType.CRAFTER -> MenuType.CRAFTER_3x3 + InventoryType.WORKBENCH -> MenuType.CRAFTING + InventoryType.BARREL, InventoryType.CHISELED_BOOKSHELF, InventoryType.DECORATED_POT, InventoryType.JUKEBOX, InventoryType.COMPOSTER, InventoryType.ENDER_CHEST -> MenuType.GENERIC_9x3 + InventoryType.CREATIVE, InventoryType.CRAFTING -> throw UnsupportedOperationException("Can't open a $this inventory!") + else -> throw UnsupportedOperationException("Unknown inventory type: $this") +} + +fun BlockPos.toBukkit(): BlockPosition = Position.block(x, y, z) + +fun Array.toBukkit() = this.map { it.toBukkit() } +fun AdventureComponent.toNms(): Component = PaperAdventure.asVanilla(this) +fun Component.toBukkit(): AdventureComponent = PaperAdventure.asAdventure(this) + +fun Server.toCraft() = this as CraftServer +val craftServer: CraftServer get() = server.toCraft() +val commodore: Commodore get() = CraftMagicNumbers.INSTANCE.commodore + +fun EntityType.toNms(): net.minecraft.world.entity.EntityType<*> = + CraftEntityType.bukkitToMinecraft(this) + +@Suppress("DEPRECATION") +fun EntityType.toNmsHolder() = + CraftEntityType.bukkitToMinecraftHolder(this) as Holder.Reference> + +fun World.toNms(): ServerLevel = (this as CraftWorld).handle +fun Entity.toNms(): net.minecraft.world.entity.Entity = (this as CraftEntity).handleRaw +fun LivingEntity.toNms(): net.minecraft.world.entity.LivingEntity = + (this as CraftLivingEntity).handle + +fun DamageSource.toNms(): net.minecraft.world.damagesource.DamageSource = + (this as CraftDamageSource).handle + +fun AdvancementDisplay.Frame.toNms() = when (this) { + CHALLENGE -> AdvancementType.CHALLENGE + GOAL -> AdvancementType.GOAL + TASK -> AdvancementType.TASK +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11GlowingLifecycleHandler.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11GlowingLifecycleHandler.kt new file mode 100644 index 000000000..a6d96d25b --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11GlowingLifecycleHandler.kt @@ -0,0 +1,35 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.nms.common.GlowingLifecycleHandler +import dev.slne.surf.api.paper.util.chunkX +import dev.slne.surf.api.paper.util.chunkZ +import org.bukkit.World +import org.bukkit.entity.Player + +@NmsUseWithCaution +class V1_21_11GlowingLifecycleHandler : GlowingLifecycleHandler { + override fun removeAllGlowingOnQuit(player: Player) { + V1_21_11SurfGlowingApiImpl.removeAllGlowingOnQuit(player) + } + + override fun getBlockGlowSpawnOperationForChunk( + player: Player, + chunkX: Int, + chunkZ: Int, + world: World + ): PacketOperation? { + val playerData = V1_21_11SurfGlowingApiImpl.getBlockPlayerData(player) ?: return null + val blockDataList = playerData.blocks + if (blockDataList.isEmpty()) return null + + val spawnOperation = PacketOperation.start() + for ((loc, block) in blockDataList) { + if (loc.chunkX != chunkX || loc.chunkZ != chunkZ || loc.world != world) continue + spawnOperation.add(block.spawn()) + } + + return spawnOperation + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/SurfGlowingApiImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11SurfGlowingApiImpl.kt similarity index 62% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/SurfGlowingApiImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11SurfGlowingApiImpl.kt index 67ad7d01a..344f82e33 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/SurfGlowingApiImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11SurfGlowingApiImpl.kt @@ -1,19 +1,18 @@ -package dev.slne.surf.api.paper.server.impl.glow +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow import com.github.shynixn.mccoroutine.folia.entityDispatcher import com.github.shynixn.mccoroutine.folia.launch -import com.google.auto.service.AutoService import dev.slne.surf.api.paper.extensions.server import dev.slne.surf.api.paper.glow.SurfGlowingApi import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsGlowingBridge import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation -import dev.slne.surf.api.paper.server.impl.glow.block.BlockGlowingData -import dev.slne.surf.api.paper.server.impl.glow.block.BlockPlayerData -import dev.slne.surf.api.paper.server.impl.glow.entity.EntityGlowingData -import dev.slne.surf.api.paper.server.impl.glow.entity.EntityPlayerData -import dev.slne.surf.api.paper.server.plugin -import dev.slne.surf.api.paper.server.reflection.Reflection +import dev.slne.surf.api.paper.nms.common.NmsProvider +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.V1_21_11SurfPaperNmsGlowingBridgeImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.block.BlockGlowingData +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.block.BlockPlayerData +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.entity.EntityGlowingData +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.entity.EntityPlayerData +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection import dev.slne.surf.api.paper.util.isChunkVisible import io.papermc.paper.adventure.PaperAdventure import net.kyori.adventure.text.format.NamedTextColor @@ -24,10 +23,13 @@ import org.bukkit.entity.Player import java.util.* import java.util.concurrent.ConcurrentHashMap -@AutoService(SurfGlowingApi::class) -class SurfGlowingApiImpl : SurfGlowingApi { +@NmsUseWithCaution +object V1_21_11SurfGlowingApiImpl : SurfGlowingApi { + private val entityPlayerData = ConcurrentHashMap() + private val blockPlayerData = ConcurrentHashMap() + + val glowingFlag = 1 shl V1_21_11Reflection.ENTITY_PROXY.getFlagGlowing() - @OptIn(NmsUseWithCaution::class) override fun makeGlowing( target: Entity, viewer: Player, @@ -38,7 +40,7 @@ class SurfGlowingApiImpl : SurfGlowingApi { teamIdFor(target), viewer, color, - SurfPaperNmsGlowingBridge.getCurrentFlags(target) + V1_21_11SurfPaperNmsGlowingBridgeImpl.getCurrentFlags(target) ) } @@ -49,10 +51,10 @@ class SurfGlowingApiImpl : SurfGlowingApi { color: NamedTextColor?, otherFlags: Byte, ) { - val color = color?.let { PaperAdventure.asVanilla(it) } + val nmsColor = color?.let { PaperAdventure.asVanilla(it) } val uuid = viewer.uniqueId val playerData = entityPlayerData.computeIfAbsent(uuid) { EntityPlayerData(uuid) } - val glowingData = playerData.entities.get(targetId) + val glowingData = playerData.entities[targetId] val operation = PacketOperation.start() if (glowingData == null) { @@ -60,26 +62,25 @@ class SurfGlowingApiImpl : SurfGlowingApi { playerData, targetId, teamId, - color, + nmsColor, otherFlags ) - playerData.entities.put(targetId, newData) + playerData.entities[targetId] = newData operation.add(newData.sendGlowingFlag(enabled = true, ignorePacket = true)) - if (color != null) { + if (nmsColor != null) { operation.add(newData.sendTeamColor()) } operation.execute(viewer) - return } - if (color == glowingData.color) return - if (color == null) { + if (nmsColor == glowingData.color) return + if (nmsColor == null) { operation.add(glowingData.removeFromTeam()) glowingData.color = null } else { - glowingData.color = color + glowingData.color = nmsColor operation.add(glowingData.sendTeamColor()) } @@ -92,17 +93,18 @@ class SurfGlowingApiImpl : SurfGlowingApi { override fun makeGlowing(location: Location, viewer: Player, color: NamedTextColor) { location.checkFinite() - val location = location.toBlockLocation() + val blockLocation = location.toBlockLocation() val uuid = viewer.uniqueId val playerData = blockPlayerData.getOrPut(uuid) { BlockPlayerData(uuid) } - val blockData = playerData.blocks[location] + val blockData = playerData.blocks[blockLocation] if (blockData == null) { - val newData = BlockGlowingData(playerData, location, color) - playerData.blocks[location] = newData + val newData = BlockGlowingData(playerData, blockLocation, color) + playerData.blocks[blockLocation] = newData + val plugin = NmsProvider.current.plugin plugin.launch(plugin.entityDispatcher(viewer)) { - if (viewer.isChunkVisible(location)) { + if (viewer.isChunkVisible(blockLocation)) { newData.spawn().execute(viewer) } } @@ -139,9 +141,9 @@ class SurfGlowingApiImpl : SurfGlowingApi { override fun removeGlowing(location: Location, viewer: Player) { location.checkFinite() - val location = location.toBlockLocation() + val blockLocation = location.toBlockLocation() val playerData = blockPlayerData[viewer.uniqueId] ?: return - val blockData = playerData.blocks.remove(location) ?: return + val blockData = playerData.blocks.remove(blockLocation) ?: return blockData.remove() if (playerData.blocks.isEmpty()) { @@ -151,25 +153,17 @@ class SurfGlowingApiImpl : SurfGlowingApi { private fun teamIdFor(entity: Entity) = (entity as? Player)?.name ?: entity.uniqueId.toString() - companion object { - val INSTANCE get() = SurfGlowingApi.INSTANCE as SurfGlowingApiImpl - - private val entityPlayerData = ConcurrentHashMap() - private val blockPlayerData = ConcurrentHashMap() - val glowingFlag = 1 shl Reflection.ENTITY_PROXY.getFlagGlowing() + fun getEntityPlayerData(player: Player): EntityPlayerData? = + entityPlayerData[player.uniqueId] - fun getEntityPlayerData(player: Player): EntityPlayerData? = - entityPlayerData[player.uniqueId] + fun getBlockPlayerData(player: Player): BlockPlayerData? = + blockPlayerData[player.uniqueId] - fun getBlockPlayerData(player: Player): BlockPlayerData? = - blockPlayerData[player.uniqueId] - - fun removeAllGlowingOnQuit(player: Player) { - val uuid = player.uniqueId - TeamData.removeFromAll(uuid) - entityPlayerData.remove(uuid)?.entities?.clear() - blockPlayerData.remove(uuid)?.blocks?.clear() - } + fun removeAllGlowingOnQuit(player: Player) { + val uuid = player.uniqueId + V1_21_11TeamData.removeFromAll(uuid) + entityPlayerData.remove(uuid)?.entities?.clear() + blockPlayerData.remove(uuid)?.blocks?.clear() } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/TeamData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11TeamData.kt similarity index 69% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/TeamData.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11TeamData.kt index b37b29d55..264a9ab71 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/TeamData.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/V1_21_11TeamData.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.impl.glow +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow import net.minecraft.ChatFormatting import net.minecraft.world.scores.PlayerTeam @@ -8,7 +8,7 @@ import java.util.* import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicInteger -class TeamData(color: ChatFormatting) { +class V1_21_11TeamData(color: ChatFormatting) { private val scoreboard = Scoreboard() val teamId = "glow-${uid()}${color.char}" val team = PlayerTeam(scoreboard, teamId).apply { @@ -26,15 +26,15 @@ class TeamData(color: ChatFormatting) { private val lastUid = AtomicInteger() fun uid(): Int = lastUid.getAndIncrement() - private val teams = EnumMap(ChatFormatting::class.java) + private val teams = EnumMap(ChatFormatting::class.java) - fun getByColor(color: ChatFormatting): TeamData = - teams.computeIfAbsent(color) { TeamData(color) } + fun getByColor(color: ChatFormatting): V1_21_11TeamData = + teams.computeIfAbsent(color) { V1_21_11TeamData(color) } - fun getByColorOrNull(color: ChatFormatting): TeamData? = teams[color] + fun getByColorOrNull(color: ChatFormatting): V1_21_11TeamData? = teams[color] fun removeFromAll(uuid: UUID) { teams.values.forEach { it.removeSeen(uuid) } } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/block/BlockGlowingData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/block/BlockGlowingData.kt new file mode 100644 index 000000000..04fa1ec90 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/block/BlockGlowingData.kt @@ -0,0 +1,79 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow.block + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommonBridge +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.nms.bridges.packets.entity.SurfPaperNmsSpawnPackets +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.V1_21_11SurfPaperNmsGlowingBridgeImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection +import glm_.shl +import net.kyori.adventure.text.format.NamedTextColor +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket +import net.minecraft.world.entity.EntityType +import net.minecraft.world.phys.Vec3 +import org.bukkit.Location +import java.util.* + +@OptIn(NmsUseWithCaution::class) +class BlockGlowingData( + val playerData: BlockPlayerData, + val location: Location, + var color: NamedTextColor, +) { + + private val entityId: Int by lazy { SurfPaperNmsCommonBridge.nextEntityId() } + private val uuid: UUID by lazy { UUID.randomUUID() } + private var initialized = false + + fun spawn(): PacketOperation { + initialize() + + val spawnOperation = V1_21_11PacketOperationImpl.simple { + ClientboundAddEntityPacket( + entityId, + uuid, + location.x, + location.y, + location.z, + location.pitch, + location.yaw, + EntityType.SHULKER, + 0, + Vec3.ZERO, + 0.0 + ) + } + val invisibleOperation = V1_21_11SurfPaperNmsGlowingBridgeImpl.setEntityFlags(entityId, invisibleFlag) + + return spawnOperation + invisibleOperation + } + + + fun updateColor() { + val player = playerData.player ?: return + V1_21_11SurfGlowingApiImpl.makeGlowing( + entityId, + uuid.toString(), + player, + color, + invisibleFlag + ) + } + + fun remove() { + playerData.player?.let { SurfPaperNmsSpawnPackets.despawn(entityId).execute(it) } + V1_21_11SurfGlowingApiImpl.removeGlowing(entityId, playerData.uuid) + } + + private fun initialize() { + if (initialized) return + initialized = true + updateColor() + } + + companion object { + val invisibleFlag = 1.toByte() shl V1_21_11Reflection.ENTITY_PROXY.getFlagInvisible() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/block/BlockPlayerData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/block/BlockPlayerData.kt new file mode 100644 index 000000000..c8f7d9e8a --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/block/BlockPlayerData.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow.block + +import dev.slne.surf.api.paper.extensions.server +import org.bukkit.Location +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +class BlockPlayerData(val uuid: UUID) { + val blocks = ConcurrentHashMap() + val player get() = server.getPlayer(uuid) +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/entity/EntityGlowingData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/entity/EntityGlowingData.kt new file mode 100644 index 000000000..2b42fa0f5 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/entity/EntityGlowingData.kt @@ -0,0 +1,74 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow.entity + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.V1_21_11SurfPaperNmsGlowingBridgeImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.bridges.packets.V1_21_11PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11TeamData +import glm_.and +import glm_.or +import net.minecraft.ChatFormatting + +@NmsUseWithCaution +data class EntityGlowingData( + val playerData: EntityPlayerData, + val entityId: Int, + val teamId: String, + var color: ChatFormatting?, + var otherFlags: Byte, +) { + + @OptIn(NmsUseWithCaution::class) + fun sendTeamColor(): PacketOperation { + val color = color ?: return V1_21_11PacketOperationImpl.empty() + val teamData = V1_21_11TeamData.getByColor(color) + + val operation = PacketOperation.start() + if (teamData.markSeen(playerData.uuid)) { + operation.add(V1_21_11SurfPaperNmsGlowingBridgeImpl.createTeam(teamData)) + } + operation.add(V1_21_11SurfPaperNmsGlowingBridgeImpl.addEntityToTeam(teamData, teamId)) + + return operation + } + + @OptIn(NmsUseWithCaution::class) + fun removeFromTeam(): PacketOperation { + val color = color ?: return V1_21_11PacketOperationImpl.empty() + val teamData = V1_21_11TeamData.getByColorOrNull(color) ?: return V1_21_11PacketOperationImpl.empty() + + val operation = PacketOperation.start() + if (teamData.removeSeen(playerData.uuid)) { + operation.add( + V1_21_11SurfPaperNmsGlowingBridgeImpl.removeEntityFromTeam( + teamData, + teamId + ) + ) + } + + return operation + } + + @OptIn(NmsUseWithCaution::class) + fun sendGlowingFlag(enabled: Boolean, ignorePacket: Boolean = false): PacketOperation { + val newFlags = if (enabled) { + otherFlags or V1_21_11SurfGlowingApiImpl.glowingFlag + } else { + otherFlags and V1_21_11SurfGlowingApiImpl.glowingFlag.inv() + } + + return V1_21_11SurfPaperNmsGlowingBridgeImpl.setEntityFlags( + entityId, + newFlags, + ignorePacket + ) + } + + fun computeFlags(): Byte { + return (otherFlags and V1_21_11SurfGlowingApiImpl.glowingFlag.inv()).or( + if (color != null) V1_21_11SurfGlowingApiImpl.glowingFlag else 0 + ) + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/entity/EntityPlayerData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/entity/EntityPlayerData.kt similarity index 56% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/entity/EntityPlayerData.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/entity/EntityPlayerData.kt index 63c1433bb..58b132da9 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/entity/EntityPlayerData.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/glow/entity/EntityPlayerData.kt @@ -1,8 +1,10 @@ -package dev.slne.surf.api.paper.server.impl.glow.entity +package dev.slne.surf.api.paper.server.nms.v1_21_11.glow.entity +import dev.slne.surf.api.paper.nms.NmsUseWithCaution import java.util.* import java.util.concurrent.ConcurrentHashMap +@NmsUseWithCaution data class EntityPlayerData(val uuid: UUID) { val entities = ConcurrentHashMap() -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/NmsPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/V1_21_11NmsPacketImpl.kt similarity index 58% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/NmsPacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/V1_21_11NmsPacketImpl.kt index 94efd1670..9f7c1a80a 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/NmsPacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/V1_21_11NmsPacketImpl.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.NmsPacket @@ -6,7 +6,7 @@ import net.minecraft.network.PacketListener import net.minecraft.network.protocol.Packet @NmsUseWithCaution -abstract class NmsPacketImpl, Listener : PacketListener>(var nmsPacket: Nms) : +abstract class V1_21_11NmsPacketImpl, Listener : PacketListener>(var nmsPacket: Nms) : NmsPacket { val nmsClass = nmsPacket.javaClass @@ -16,8 +16,8 @@ abstract class NmsPacketImpl, Listener : PacketListen companion object { @JvmStatic - fun getFromApi(nmsPacket: NmsPacket): NmsPacketImpl<*, *> { - require(nmsPacket is NmsPacketImpl<*, *>) { "Invalid NmsPacket implementation: " + nmsPacket.javaClass.getName() } + fun getFromApi(nmsPacket: NmsPacket): V1_21_11NmsPacketImpl<*, *> { + require(nmsPacket is V1_21_11NmsPacketImpl<*, *>) { "Invalid NmsPacket implementation: " + nmsPacket.javaClass.getName() } return nmsPacket } } diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/V1_21_11PacketRegistry.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/V1_21_11PacketRegistry.kt new file mode 100644 index 000000000..e11d7a13f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/V1_21_11PacketRegistry.kt @@ -0,0 +1,78 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.clientbound.V1_21_11ClientboundDisconnectPacketImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.clientbound.V1_21_11ClientboundSystemChatPacketImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound.V1_21_11CommandSuggestionPacketImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound.V1_21_11RenameItemPacketImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound.V1_21_11ServerboundCustomPayloadPacketImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound.V1_21_11SignUpdatePacketImpl +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.common.ClientCommonPacketListener +import net.minecraft.network.protocol.common.ClientboundDisconnectPacket +import net.minecraft.network.protocol.common.ServerCommonPacketListener +import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket +import net.minecraft.network.protocol.game.ClientboundSystemChatPacket +import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket +import net.minecraft.network.protocol.game.ServerboundRenameItemPacket +import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket +import kotlin.reflect.KClass + +@OptIn(NmsUseWithCaution::class) +object V1_21_11PacketRegistry { + private typealias PacketMap = Object2ObjectOpenHashMap>, F> + + private val SERVERBOUND_PACKETS = PacketMap>() + private val CLIENTBOUND_PACKETS = PacketMap>() + + init { + // @formatter:off + // Serverbound packets + registerServerboundPacket(ServerboundSignUpdatePacket::class) { V1_21_11SignUpdatePacketImpl(it) } + registerServerboundPacket(ServerboundRenameItemPacket::class) { V1_21_11RenameItemPacketImpl(it) } + registerServerboundPacket(ServerboundCommandSuggestionPacket::class) { V1_21_11CommandSuggestionPacketImpl(it) } + registerServerboundPacket(ServerboundCustomPayloadPacket::class) { V1_21_11ServerboundCustomPayloadPacketImpl(it) } + + // Clientbound packets + registerClientboundPacket(ClientboundDisconnectPacket::class) { V1_21_11ClientboundDisconnectPacketImpl(it) } + registerClientboundPacket(ClientboundSystemChatPacket::class) { V1_21_11ClientboundSystemChatPacketImpl(it) } + // @formatter:on + } + + private fun , Api : NmsServerboundPacket> registerServerboundPacket( + nms: KClass, + factory: ServerboundPacketFactory, + ) { + SERVERBOUND_PACKETS[nms.java] = factory + } + + @Suppress("UNCHECKED_CAST") + fun > createServerboundPacketOrNull(packet: Nms): NmsServerboundPacket? { + val factory = SERVERBOUND_PACKETS[packet.javaClass] as? ServerboundPacketFactory + return factory?.create(packet) + } + + private fun , Api : NmsClientboundPacket, Listener : ClientCommonPacketListener> registerClientboundPacket( + nms: KClass, + factory: ClientboundPacketFactory, + ) { + CLIENTBOUND_PACKETS[nms.java] = factory + } + + @Suppress("UNCHECKED_CAST") + fun > createClientboundPacketOrNull(packet: Nms): NmsClientboundPacket? { + val factory = CLIENTBOUND_PACKETS[packet.javaClass] as? ClientboundPacketFactory + return factory?.create(packet) + } + + private fun interface ServerboundPacketFactory, Api : NmsServerboundPacket> { + fun create(packet: Nms): Api + } + + private fun interface ClientboundPacketFactory, Api : NmsClientboundPacket> { + fun create(packet: Nms): Api + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/ClientboundDisconnectPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11ClientboundDisconnectPacketImpl.kt similarity index 52% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/ClientboundDisconnectPacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11ClientboundDisconnectPacketImpl.kt index 8cec3344f..afbd59908 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/ClientboundDisconnectPacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11ClientboundDisconnectPacketImpl.kt @@ -1,14 +1,14 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.clientbound +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.clientbound import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.clientbound.DisconnectPacket -import dev.slne.surf.api.paper.server.nms.toBukkit +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toBukkit import net.minecraft.network.protocol.common.ClientCommonPacketListener import net.minecraft.network.protocol.common.ClientboundDisconnectPacket @NmsUseWithCaution -class ClientboundDisconnectPacketImpl(nmsPacket: ClientboundDisconnectPacket) : - NmsClientboundPacketImpl(nmsPacket), +class V1_21_11ClientboundDisconnectPacketImpl(nmsPacket: ClientboundDisconnectPacket) : + V1_21_11NmsClientboundPacketImpl(nmsPacket), DisconnectPacket { override val reason get() = nmsPacket.reason.toBukkit() -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/ClientboundSystemChatPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11ClientboundSystemChatPacketImpl.kt similarity index 67% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/ClientboundSystemChatPacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11ClientboundSystemChatPacketImpl.kt index 5480b2dca..991bd4cc8 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/ClientboundSystemChatPacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11ClientboundSystemChatPacketImpl.kt @@ -1,15 +1,15 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.clientbound +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.clientbound import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.clientbound.SystemChatPacket -import dev.slne.surf.api.paper.server.nms.toBukkit +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toBukkit import net.kyori.adventure.text.Component import net.minecraft.network.protocol.game.ClientGamePacketListener import net.minecraft.network.protocol.game.ClientboundSystemChatPacket @NmsUseWithCaution -class ClientboundSystemChatPacketImpl(nmsPacket: ClientboundSystemChatPacket) : - NmsClientboundPacketImpl(nmsPacket), +class V1_21_11ClientboundSystemChatPacketImpl(nmsPacket: ClientboundSystemChatPacket) : + V1_21_11NmsClientboundPacketImpl(nmsPacket), SystemChatPacket { override var content: Component get() = nmsPacket.content().toBukkit() @@ -22,4 +22,4 @@ class ClientboundSystemChatPacketImpl(nmsPacket: ClientboundSystemChatPacket) : set(value) { nmsPacket = ClientboundSystemChatPacket(nmsPacket.content(), value) } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11NmsClientboundPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11NmsClientboundPacketImpl.kt new file mode 100644 index 000000000..19e50bbed --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/clientbound/V1_21_11NmsClientboundPacketImpl.kt @@ -0,0 +1,12 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.clientbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.V1_21_11NmsPacketImpl +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.common.ClientCommonPacketListener + +@NmsUseWithCaution +abstract class V1_21_11NmsClientboundPacketImpl, Listener : ClientCommonPacketListener>( + nmsPacket: Nms, +) : NmsClientboundPacket, V1_21_11NmsPacketImpl(nmsPacket) diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/CommandSuggestionPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11CommandSuggestionPacketImpl.kt similarity index 59% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/CommandSuggestionPacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11CommandSuggestionPacketImpl.kt index f168dc5f9..8112169d8 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/CommandSuggestionPacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11CommandSuggestionPacketImpl.kt @@ -1,12 +1,12 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.serverbound.CommandSuggestionPacket import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket @NmsUseWithCaution -class CommandSuggestionPacketImpl(nmsPacket: ServerboundCommandSuggestionPacket) : - NmsServerboundPacketImpl(nmsPacket), +class V1_21_11CommandSuggestionPacketImpl(nmsPacket: ServerboundCommandSuggestionPacket) : + V1_21_11NmsServerboundPacketImpl(nmsPacket), CommandSuggestionPacket { override val completionId get() = nmsPacket.id override val command get() = nmsPacket.command diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11NmsServerboundPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11NmsServerboundPacketImpl.kt new file mode 100644 index 000000000..814e98b5c --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11NmsServerboundPacketImpl.kt @@ -0,0 +1,10 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.V1_21_11NmsPacketImpl +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.common.ServerCommonPacketListener + +@NmsUseWithCaution +abstract class V1_21_11NmsServerboundPacketImpl>(nmsPacket: Nms) : + V1_21_11NmsPacketImpl(nmsPacket) diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/RenameItemPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11RenameItemPacketImpl.kt similarity index 52% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/RenameItemPacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11RenameItemPacketImpl.kt index 1ea116406..c7b34968d 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/RenameItemPacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11RenameItemPacketImpl.kt @@ -1,11 +1,11 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.serverbound.RenameItemPacket import net.minecraft.network.protocol.game.ServerboundRenameItemPacket @NmsUseWithCaution -class RenameItemPacketImpl(nmsPacket: ServerboundRenameItemPacket) : - NmsServerboundPacketImpl(nmsPacket), RenameItemPacket { +class V1_21_11RenameItemPacketImpl(nmsPacket: ServerboundRenameItemPacket) : + V1_21_11NmsServerboundPacketImpl(nmsPacket), RenameItemPacket { override val newName: String get() = nmsPacket.name } diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/ServerboundCustomPayloadPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11ServerboundCustomPayloadPacketImpl.kt similarity index 88% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/ServerboundCustomPayloadPacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11ServerboundCustomPayloadPacketImpl.kt index e1bb7e851..75924cad6 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/ServerboundCustomPayloadPacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11ServerboundCustomPayloadPacketImpl.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound import dev.slne.surf.api.paper.nms.NmsUseWithCaution import io.papermc.paper.adventure.PaperAdventure @@ -9,9 +9,9 @@ import net.minecraft.network.protocol.common.custom.DiscardedPayload import dev.slne.surf.api.paper.nms.listener.packets.serverbound.ServerboundCustomPayloadPacket.Payload as ApiPayload @NmsUseWithCaution -class ServerboundCustomPayloadPacketImpl( +class V1_21_11ServerboundCustomPayloadPacketImpl( nmsPacket: ServerboundCustomPayloadPacket -) : NmsServerboundPacketImpl(nmsPacket), +) : V1_21_11NmsServerboundPacketImpl(nmsPacket), dev.slne.surf.api.paper.nms.listener.packets.serverbound.ServerboundCustomPayloadPacket { override var payload: ApiPayload @@ -39,4 +39,4 @@ class ServerboundCustomPayloadPacketImpl( ) } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/SignUpdatePacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11SignUpdatePacketImpl.kt similarity index 63% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/SignUpdatePacketImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11SignUpdatePacketImpl.kt index 93abf0a2e..83540ba5b 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/SignUpdatePacketImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/listener/packets/serverbound/V1_21_11SignUpdatePacketImpl.kt @@ -1,13 +1,13 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound +package dev.slne.surf.api.paper.server.nms.v1_21_11.listener.packets.serverbound import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.serverbound.SignUpdatePacket -import dev.slne.surf.api.paper.server.nms.toBukkit +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toBukkit import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket @NmsUseWithCaution -class SignUpdatePacketImpl(nmsPacket: ServerboundSignUpdatePacket) : - NmsServerboundPacketImpl(nmsPacket), SignUpdatePacket { +class V1_21_11SignUpdatePacketImpl(nmsPacket: ServerboundSignUpdatePacket) : + V1_21_11NmsServerboundPacketImpl(nmsPacket), SignUpdatePacket { override val position get() = nmsPacket.pos.toBukkit() override val lines: Array get() = nmsPacket.lines override val isFrontText get() = nmsPacket.isFrontText diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/listener/V1_21_11ChannelInjector.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/listener/V1_21_11ChannelInjector.kt new file mode 100644 index 000000000..86cfd5fa9 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/listener/V1_21_11ChannelInjector.kt @@ -0,0 +1,98 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.packet.listener + +import dev.slne.surf.api.core.reflection.Field +import dev.slne.surf.api.core.reflection.SurfProxy +import dev.slne.surf.api.core.reflection.SurfReflection +import dev.slne.surf.api.core.reflection.createProxy +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.nms.common.AbstractChannelInjector +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import io.netty.channel.Channel +import io.papermc.paper.connection.PaperPlayerLoginConnection +import io.papermc.paper.connection.ReadablePlayerCookieConnectionImpl +import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent +import io.papermc.paper.network.ChannelInitializeListenerHolder +import net.kyori.adventure.key.Key +import net.minecraft.network.Connection +import net.minecraft.network.HandlerNames +import net.minecraft.network.protocol.Packet +import net.minecraft.server.level.ServerPlayer +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.player.PlayerJoinEvent + +@Suppress("ClassName", "UnstableApiUsage") +object V1_21_11ChannelInjector : AbstractChannelInjector() { + private val log = logger() + + override fun registerChannelInitializeListener( + key: Key, + listener: (Channel) -> Unit + ) { + ChannelInitializeListenerHolder.addListener(key, listener) + } + + override fun unregisterChannelInitializeListener(key: Key) { + ChannelInitializeListenerHolder.removeListener(key) + } + + override fun createPacketHandler() = PacketHandler() + override fun getNmsChannelHandlerName(): String = HandlerNames.PACKET_HANDLER + + @EventHandler + fun onPlayerLogin(event: PlayerConnectionValidateLoginEvent) { + val paperConnection = event.connection + if (paperConnection is PaperPlayerLoginConnection) { + val profile = paperConnection.authenticatedProfile + + if (profile == null) { + event.kickMessage(createFailedToInjectPacketListenerDisconnectReason()) + + log.atWarning() + .log("Failed to inject packet listener for player (${paperConnection.unsafeProfile}) with unauthenticated profile: ${paperConnection.address} - ${paperConnection.clientAddress}") + return + } + + val connection = + ReadablePlayerCookieConnectionImplProxy.instance.getConnection(paperConnection) + val channel = connection.channel + getOrInjectPacketHandler(channel).connection = connection + } + } + + @EventHandler(priority = EventPriority.LOWEST) + fun onPlayerJoin(event: PlayerJoinEvent) { + val player = event.player.toNms() + val connection = player.connection.connection + val channel = connection.channel + + getOrInjectPacketHandler(channel).connection = connection + } + + class PacketHandler : AbstractPacketHandler() { + @Volatile + var connection: Connection? = null + + override fun isPacket(msg: Any): Boolean = msg is Packet<*> + override fun getPlayerFromConnection(): Any? { + val connection = this.connection ?: return NO_CONNECTION_SENTINEL + return connection.player as ServerPlayer? + } + + override fun getBukkitPlayer(player: Any?): Player? { + return (player as? ServerPlayer)?.bukkitEntity + } + } + + @SurfProxy(ReadablePlayerCookieConnectionImpl::class) + interface ReadablePlayerCookieConnectionImplProxy { + + @Field("connection", Field.Type.GETTER) + fun getConnection(instance: ReadablePlayerCookieConnectionImpl): Connection + + companion object { + val instance = SurfReflection.createProxy() + } + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/listener/V1_21_11GlowingPacketListener.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/listener/V1_21_11GlowingPacketListener.kt new file mode 100644 index 000000000..28d1dc2b6 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/listener/V1_21_11GlowingPacketListener.kt @@ -0,0 +1,100 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.packet.listener + +import com.github.benmanes.caffeine.cache.Caffeine +import com.sksamuel.aedile.core.expireAfterWrite +import dev.slne.surf.api.core.util.mutableObjectListOf +import dev.slne.surf.api.core.util.toMutableObjectList +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener +import dev.slne.surf.api.paper.packet.listener.listener.annotation.ClientboundListener +import dev.slne.surf.api.paper.server.nms.v1_21_11.glow.V1_21_11SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v1_21_11.reflection.V1_21_11Reflection +import glm_.or +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientboundBundlePacket +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket +import net.minecraft.network.syncher.SynchedEntityData.DataValue +import org.bukkit.entity.Player +import kotlin.time.Duration.Companion.seconds + +@OptIn(NmsUseWithCaution::class) +object V1_21_11GlowingPacketListener : PacketListener { + + val ignoreCache = Caffeine.newBuilder() + .weakKeys() + .expireAfterWrite(5.seconds) + .build, Unit>() + + fun ignorePacket(packet: Packet<*>) { + ignoreCache.put(packet, Unit) + } + + @ClientboundListener + fun onBundlePacket(packet: ClientboundBundlePacket, player: Player): ClientboundBundlePacket { + val bundles = packet.subPackets().toMutableObjectList() + bundles.replaceAll { subPacket -> + if (subPacket is ClientboundSetEntityDataPacket) { + updatePacketIfNeeded(subPacket, player) + } else { + subPacket + } + } + + return ClientboundBundlePacket(bundles) + } + + @ClientboundListener + fun onSetEntityDataPacket( + packet: ClientboundSetEntityDataPacket, + player: Player, + ): ClientboundSetEntityDataPacket { + return updatePacketIfNeeded(packet, player) + } + + private fun updatePacketIfNeeded( + packet: ClientboundSetEntityDataPacket, + player: Player + ): ClientboundSetEntityDataPacket { + // Ignore packets that we don't care about + if (ignoreCache.asMap().remove(packet) != null) { + return packet + } + + val playerData = V1_21_11SurfGlowingApiImpl.getEntityPlayerData(player) ?: return packet + val glowingData = playerData.entities[packet.id] ?: return packet + val incoming = packet.packedItems + var flagsFound = false + var edited = false + val newItems = mutableObjectListOf>(incoming.size + 1) + val dataFlagsShared = V1_21_11Reflection.ENTITY_PROXY.getDataFlagsSharedId() + val dataFlagsSharedId = dataFlagsShared.id + + for (dataValue in incoming) { + if (dataValue.id == dataFlagsSharedId) { + flagsFound = true + val current = dataValue.value as Byte + glowingData.otherFlags = current + val withGlow: Byte = current or V1_21_11SurfGlowingApiImpl.glowingFlag + + if (withGlow != current) { + edited = true + newItems.add(DataValue(dataFlagsSharedId, dataFlagsShared.serializer, withGlow)) + } else { + newItems.add(dataValue) + } + } else { + newItems.add(dataValue) + } + } + + if (!edited && !flagsFound) { + val withGlow = glowingData.otherFlags or V1_21_11SurfGlowingApiImpl.glowingFlag + if (withGlow != 0.toByte()) { + edited = true + newItems.add(DataValue(dataFlagsSharedId, dataFlagsShared.serializer, withGlow)) + } + } + + return if (edited) ClientboundSetEntityDataPacket(packet.id, newItems) else packet + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/lore/V1_21_11PacketLoreListener.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/lore/V1_21_11PacketLoreListener.kt new file mode 100644 index 000000000..b5eed7de1 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/lore/V1_21_11PacketLoreListener.kt @@ -0,0 +1,388 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.packet.lore + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener +import dev.slne.surf.api.paper.packet.listener.listener.annotation.ClientboundListener +import dev.slne.surf.api.paper.packet.listener.listener.annotation.ServerboundListener +import dev.slne.surf.api.paper.packet.lore.SurfPaperPacketLoreHandler +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toBukkit +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms +import dev.slne.surf.api.paper.util.namespacedKey +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectArrayList +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectLists +import net.kyori.adventure.text.format.TextDecoration +import net.minecraft.core.component.DataComponents +import net.minecraft.network.protocol.game.* +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.component.CustomData +import net.minecraft.world.item.component.ItemLore +import org.bukkit.NamespacedKey +import org.bukkit.plugin.Plugin +import net.minecraft.network.chat.Component as MinecraftComponent + +/** + * PacketLoreListener is a class that implements PacketListenerAbstract and is responsible for + * handling the modification of lore on item stacks in packet events. + */ +@OptIn(NmsUseWithCaution::class) +object V1_21_11PacketLoreListener : PacketListener { + private val globalHandlersByPlugin = + Object2ObjectLinkedOpenHashMap>() + + private val keyedHandlersByPlugin = + Object2ObjectLinkedOpenHashMap>() + + @Volatile + private var keyedHandlersSnapshot: Map = emptyMap() + + @Volatile + private var globalHandlersSnapshot: Array = emptyArray() + + private val ORIGINAL_LORE_KEY = namespacedKey("original_lore") + private val ORIGINAL_LORE_KEY_STRING = ORIGINAL_LORE_KEY.asString() + + private fun hasAnyHandlers(): Boolean = + keyedHandlersSnapshot.isNotEmpty() || globalHandlersSnapshot.isNotEmpty() + + @ServerboundListener + fun onPacketReceive(event: ServerboundSetCreativeModeSlotPacket) { + makeCleanItemStack(event.itemStack()) + } + + @ClientboundListener + fun onWindowItem(event: ClientboundContainerSetContentPacket): ClientboundContainerSetContentPacket { + if (!hasAnyHandlers()) return event + + val sourceItems = event.items + val updatedItems = ObjectArrayList(sourceItems.size) + + var changed = false + + for (i in sourceItems.indices) { + val original = sourceItems[i] + val updated = makeUpdatedItemStack(original) + + if (updated !== original) { + changed = true + } + + updatedItems.add(updated) + } + + val originalCarried = event.carriedItem() + val updatedCarried = makeUpdatedItemStack(originalCarried) + + if (updatedCarried !== originalCarried) { + changed = true + } + + if (!changed) { + return event + } + + return ClientboundContainerSetContentPacket( + event.containerId(), + event.stateId(), + updatedItems, + updatedCarried + ) + } + + @ClientboundListener + fun onSetSlotPacket(event: ClientboundContainerSetSlotPacket): ClientboundContainerSetSlotPacket { + val original = event.item + val updated = makeUpdatedItemStack(original) + + if (updated === original) { + return event + } + + return ClientboundContainerSetSlotPacket( + event.containerId, + event.stateId, + event.slot, + updated + ) + } + + @ClientboundListener + fun onSetPlayerInventoryPacket(event: ClientboundSetPlayerInventoryPacket): ClientboundSetPlayerInventoryPacket { + val original = event.contents + val updated = makeUpdatedItemStack(original) + + if (updated === original) { + return event + } + + return ClientboundSetPlayerInventoryPacket( + event.slot(), + updated + ) + } + + @ServerboundListener + fun onContainerClickPacket( + event: ServerboundContainerClickPacket, + player: ServerPlayer + ): ServerboundContainerClickPacket { + if (!hasAnyHandlers()) return event + + val container = player.containerMenu + val currentStateId = container.stateId + + val brokenStateId = if (event.stateId() == currentStateId) { + currentStateId - 1 + } else { + event.stateId() + } + + if (brokenStateId == event.stateId()) return event + + return ServerboundContainerClickPacket( + event.containerId(), + brokenStateId, + event.slotNum(), + event.buttonNum(), + event.clickType(), + event.changedSlots(), + event.carriedItem() + ) + } + + @ClientboundListener + fun onSetCursorItemPacket(event: ClientboundSetCursorItemPacket): ClientboundSetCursorItemPacket { + val original = event.contents + val updated = makeUpdatedItemStack(original) + + if (updated === original) { + return event + } + + return ClientboundSetCursorItemPacket(updated) + } + + /** + * Returns the original item if: + * - item is empty + * - no handlers exist + * - no keyed handler matches and no global handler exists + * - handlers run but lore result is identical + * + * Only copies the stack if at least one handler will actually run. + */ + private fun makeUpdatedItemStack( + original: ItemStack, + ): ItemStack { + if (original.isEmpty) return original + + // One volatile read + val keyedSnapshot = keyedHandlersSnapshot + val globalSnapshot = globalHandlersSnapshot + + if (keyedSnapshot.isEmpty() && globalSnapshot.isEmpty()) { + return original + } + + /* + * We need Bukkit PDC for the current handler API, but only when there + * are keyed handlers to consider. The original mirror is used to cheaply + * determine whether any keyed handlers actually match. + */ + val matchingKeyedHandlers = if (keyedSnapshot.isNotEmpty()) { + val originalBukkitStack = original.asBukkitMirror() + val originalPdc = originalBukkitStack.persistentDataContainer + resolveMatchingKeyedHandlers( + originalPdc.keys, + keyedSnapshot + ) + } else { + ObjectLists.emptyList() + } + + if (matchingKeyedHandlers.isEmpty() && globalSnapshot.isEmpty()) { + return original + } + + /* + * From here on, we know that at least one handler will run. + * Only now create a copy. + */ + val item = original.copy() + val bukkitStack = item.asBukkitMirror() + val pdc = bukkitStack.persistentDataContainer + + val originalLore = item.getOrDefault(DataComponents.LORE, ItemLore.EMPTY) + val originalLines = originalLore.lines + + val mutableLore = originalLines.mapTo( + ObjectArrayList(originalLines.size) + ) { it.toBukkit() } + + for (i in matchingKeyedHandlers.indices) { + matchingKeyedHandlers[i].handleLore(mutableLore, pdc, bukkitStack) + } + + for (i in globalSnapshot.indices) { + globalSnapshot[i].handleLore(mutableLore, pdc, bukkitStack) + } + + val updatedLines = ObjectArrayList(mutableLore.size) + for (i in mutableLore.indices) { + val line = + mutableLore[i].decorationIfAbsent(TextDecoration.ITALIC, TextDecoration.State.FALSE) + updatedLines.add(line.toNms()) + } + + val updatedLore = ItemLore(updatedLines) + + if (updatedLore == originalLore) { + return original + } + + item.set(DataComponents.LORE, updatedLore) + CustomData.update(DataComponents.CUSTOM_DATA, item) { tag -> + if (!tag.contains(ORIGINAL_LORE_KEY_STRING)) { + tag.store(ORIGINAL_LORE_KEY_STRING, ItemLore.CODEC, originalLore) + } + } + + return item + } + + private fun makeCleanItemStack( + stack: ItemStack, + ): ItemStack { + if (stack.isEmpty) { + return stack + } + + val customData = stack.get(DataComponents.CUSTOM_DATA) ?: return stack + if (!customData.contains(ORIGINAL_LORE_KEY_STRING)) { + return stack + } + + CustomData.update(DataComponents.CUSTOM_DATA, stack) { tag -> + val originalLore = tag.read(ORIGINAL_LORE_KEY_STRING, ItemLore.CODEC) + originalLore.ifPresent { lore -> + stack.set(DataComponents.LORE, lore) + tag.remove(ORIGINAL_LORE_KEY_STRING) + } + } + + return stack + } + + private fun resolveMatchingKeyedHandlers( + itemKeys: Set, + keyedSnapshot: Map, + ): List { + if (itemKeys.isEmpty() || keyedSnapshot.isEmpty()) { + return emptyList() + } + + var result: ObjectArrayList? = null + for (key in itemKeys) { + val handler = keyedSnapshot[key] ?: continue + + if (result == null) { + result = ObjectArrayList(2) + } + + result.add(handler) + } + + return result ?: emptyList() + } + + fun register(plugin: Plugin, identifier: NamespacedKey, listener: SurfPaperPacketLoreHandler) { + synchronized(this) { + check(!keyedHandlersSnapshot.containsKey(identifier)) { + "A PacketLore handler for $identifier is already registered!" + } + + val handlers = + keyedHandlersByPlugin.computeIfAbsent(plugin) { Object2ObjectLinkedOpenHashMap() } + + val previous = handlers.putIfAbsent(identifier, listener) + check(previous == null) { + "A PacketLore handler for $identifier is already registered for plugin ${plugin.name}!" + } + + val newSnapshot = Object2ObjectLinkedOpenHashMap(keyedHandlersSnapshot) + newSnapshot[identifier] = listener + keyedHandlersSnapshot = newSnapshot + } + } + + fun register(plugin: Plugin, listener: SurfPaperPacketLoreHandler) { + synchronized(this) { + val handlers = + globalHandlersByPlugin.computeIfAbsent(plugin) { ObjectLinkedOpenHashSet() } + if (handlers.add(listener)) { + rebuildGlobalHandlersSnapshot() + } else { + error("A PacketLore handler identical to the provided one (${listener.javaClass.name}) is already registered for plugin ${plugin.name}!") + } + } + } + + fun unregister(identifier: NamespacedKey) { + synchronized(this) { + if (!keyedHandlersSnapshot.containsKey(identifier)) { + return + } + + var emptyPlugin: Plugin? = null + + for ((plugin, handlers) in keyedHandlersByPlugin) { + if (handlers.remove(identifier) != null) { + if (handlers.isEmpty()) { + emptyPlugin = plugin + } + break + } + } + + if (emptyPlugin != null) { + keyedHandlersByPlugin.remove(emptyPlugin) + } + + val newSnapshot = Object2ObjectLinkedOpenHashMap(keyedHandlersSnapshot) + newSnapshot.remove(identifier) + keyedHandlersSnapshot = newSnapshot + } + } + + fun unregister(plugin: Plugin) { + synchronized(this) { + val removedGlobal = globalHandlersByPlugin.remove(plugin) != null + if (removedGlobal) { + rebuildGlobalHandlersSnapshot() + } + + val removedKeyed = keyedHandlersByPlugin.remove(plugin) + if (removedKeyed != null) { + val newSnapshot = Object2ObjectLinkedOpenHashMap(keyedHandlersSnapshot) + for (identifier in removedKeyed.keys) { + newSnapshot.remove(identifier) + } + keyedHandlersSnapshot = newSnapshot + } + } + } + + private fun rebuildGlobalHandlersSnapshot() { + val snapshot = ObjectArrayList() + + globalHandlersByPlugin.object2ObjectEntrySet().fastForEach { (plugin, handlers) -> + if (plugin.isEnabled) { + snapshot.addAll(handlers) + } + } + + globalHandlersSnapshot = snapshot.toTypedArray() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/lore/V1_21_11PacketLoreRegistry.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/lore/V1_21_11PacketLoreRegistry.kt new file mode 100644 index 000000000..bbe912d8f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/packet/lore/V1_21_11PacketLoreRegistry.kt @@ -0,0 +1,24 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.packet.lore + +import dev.slne.surf.api.paper.nms.common.PacketLoreRegistry +import dev.slne.surf.api.paper.packet.lore.SurfPaperPacketLoreHandler +import org.bukkit.NamespacedKey +import org.bukkit.plugin.Plugin + +class V1_21_11PacketLoreRegistry : PacketLoreRegistry { + override fun register(plugin: Plugin, identifier: NamespacedKey, listener: SurfPaperPacketLoreHandler) { + V1_21_11PacketLoreListener.register(plugin, identifier, listener) + } + + override fun register(plugin: Plugin, listener: SurfPaperPacketLoreHandler) { + V1_21_11PacketLoreListener.register(plugin, listener) + } + + override fun unregister(identifier: NamespacedKey) { + V1_21_11PacketLoreListener.unregister(identifier) + } + + override fun unregister(plugin: Plugin) { + V1_21_11PacketLoreListener.unregister(plugin) + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/EntityProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11EntityProxy.kt similarity index 85% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/EntityProxy.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11EntityProxy.kt index f9a4a85c9..79e25a57d 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/EntityProxy.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11EntityProxy.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.reflection +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection import net.minecraft.network.syncher.EntityDataAccessor import net.minecraft.world.entity.Entity @@ -7,7 +7,7 @@ import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies import xyz.jpenilla.reflectionremapper.proxy.annotation.Static @Proxies(Entity::class) -interface EntityProxy { +interface V1_21_11EntityProxy { @FieldGetter("FLAG_GLOWING") @Static @@ -20,4 +20,4 @@ interface EntityProxy { @FieldGetter("DATA_SHARED_FLAGS_ID") @Static fun getDataFlagsSharedId(): EntityDataAccessor -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ItemProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ItemProxy.kt new file mode 100644 index 000000000..28a91789e --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ItemProxy.kt @@ -0,0 +1,12 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection + +import net.minecraft.core.component.DataComponentMap +import net.minecraft.world.item.Item +import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter +import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies + +@Proxies(Item::class) +interface V1_21_11ItemProxy { + @FieldSetter("components") + fun setComponents(item: Item, components: DataComponentMap) +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11Reflection.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11Reflection.kt new file mode 100644 index 000000000..4c46e55c8 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11Reflection.kt @@ -0,0 +1,41 @@ +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection + +import dev.slne.surf.api.core.reflection.SurfReflection +import dev.slne.surf.api.core.reflection.createProxy +import dev.slne.surf.api.paper.util.reflectionProxy +import xyz.jpenilla.reflectionremapper.ReflectionRemapper +import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory + +object V1_21_11Reflection { + lateinit var SERVER_STATS_COUNTER_PROXY: V1_21_11ServerStatsCounterProxy + private set + lateinit var ENTITY_PROXY: V1_21_11EntityProxy + private set + lateinit var ITEM_PROXY: V1_21_11ItemProxy + private set + lateinit var SERVER_CONNECTION_LISTENER_PROXY: V1_21_11ServerConnectionListenerProxy + private set + lateinit var VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY: V1_21_11VanillaArgumentProviderImplProxy + private set + lateinit var VANILLA_ARGUMENT_PROVIDER_PROXY: V1_21_11VanillaArgumentProviderProxy + private set + + fun initialize() { + val remapper = ReflectionRemapper.forReobfMappingsInPaperJar() + val proxyFactory = + ReflectionProxyFactory.create(remapper, V1_21_11Reflection::class.java.classLoader) + + SERVER_STATS_COUNTER_PROXY = proxyFactory.reflectionProxy() + ENTITY_PROXY = proxyFactory.reflectionProxy() + ITEM_PROXY = proxyFactory.reflectionProxy() + SERVER_CONNECTION_LISTENER_PROXY = + proxyFactory.reflectionProxy() + VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY = + SurfReflection.createProxy() + VANILLA_ARGUMENT_PROVIDER_PROXY = + SurfReflection.createProxy() + + // gc the remapper + System.gc() + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/ServerConnectionListenerProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ServerConnectionListenerProxy.kt similarity index 76% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/ServerConnectionListenerProxy.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ServerConnectionListenerProxy.kt index 9197b5b24..a8e0a39c9 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/ServerConnectionListenerProxy.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ServerConnectionListenerProxy.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.reflection +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection import io.netty.channel.ChannelFuture import net.minecraft.server.network.ServerConnectionListener @@ -6,7 +6,7 @@ import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies @Proxies(ServerConnectionListener::class) -interface ServerConnectionListenerProxy { +interface V1_21_11ServerConnectionListenerProxy { @FieldGetter("channels") fun getChannels(instance: ServerConnectionListener): List -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/ServerStatsCounterProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ServerStatsCounterProxy.kt similarity index 84% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/ServerStatsCounterProxy.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ServerStatsCounterProxy.kt index 818eaccee..a6c9dfc54 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/ServerStatsCounterProxy.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11ServerStatsCounterProxy.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.reflection +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection import com.google.gson.Gson import com.google.gson.JsonElement @@ -9,7 +9,7 @@ import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies import xyz.jpenilla.reflectionremapper.proxy.annotation.Static @Proxies(ServerStatsCounter::class) -interface ServerStatsCounterProxy { +interface V1_21_11ServerStatsCounterProxy { @MethodName("toJson") fun toJson(statsCounter: ServerStatsCounter): JsonElement diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/VanillaArgumentProviderImplProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11VanillaArgumentProviderImplProxy.kt similarity index 80% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/VanillaArgumentProviderImplProxy.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11VanillaArgumentProviderImplProxy.kt index ee729ce8f..5e9fb9d2d 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/VanillaArgumentProviderImplProxy.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11VanillaArgumentProviderImplProxy.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.reflection +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection import com.mojang.brigadier.arguments.ArgumentType import com.mojang.brigadier.exceptions.CommandSyntaxException @@ -7,9 +7,9 @@ import dev.slne.surf.api.core.reflection.SurfProxy import io.papermc.paper.command.brigadier.argument.VanillaArgumentProviderImpl @SurfProxy(VanillaArgumentProviderImpl::class) -interface VanillaArgumentProviderImplProxy { +interface V1_21_11VanillaArgumentProviderImplProxy { @Name("wrap") @Throws(CommandSyntaxException::class) fun wrap(instance: Any, base: Any, converter: Any): ArgumentType<*> -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/VanillaArgumentProviderProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11VanillaArgumentProviderProxy.kt similarity index 72% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/VanillaArgumentProviderProxy.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11VanillaArgumentProviderProxy.kt index 0a9c9edda..67082b302 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/VanillaArgumentProviderProxy.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/reflection/V1_21_11VanillaArgumentProviderProxy.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.reflection +package dev.slne.surf.api.paper.server.nms.v1_21_11.reflection import dev.slne.surf.api.core.reflection.Name import dev.slne.surf.api.core.reflection.Static @@ -6,9 +6,9 @@ import dev.slne.surf.api.core.reflection.SurfProxy @SurfProxy(qualifiedName = "io.papermc.paper.command.brigadier.argument.VanillaArgumentProvider") -interface VanillaArgumentProviderProxy { +interface V1_21_11VanillaArgumentProviderProxy { @Static @Name("provider") fun provider(): Any -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/region/TickThreadGuardImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/region/V1_21_11TickThreadGuard.kt similarity index 83% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/region/TickThreadGuardImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/region/V1_21_11TickThreadGuard.kt index 3ee138d93..588c2b71f 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/region/TickThreadGuardImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v1-21-11/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v1_21_11/region/V1_21_11TickThreadGuard.kt @@ -1,10 +1,8 @@ -package dev.slne.surf.api.paper.server.impl.region +package dev.slne.surf.api.paper.server.nms.v1_21_11.region import ca.spottedleaf.moonrise.common.util.TickThread -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.region.TickThreadGuard -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v1_21_11.extensions.toNms import dev.slne.surf.api.paper.util.chunkX import dev.slne.surf.api.paper.util.chunkZ import io.papermc.paper.math.Position @@ -15,11 +13,7 @@ import org.bukkit.entity.Entity import org.bukkit.util.BoundingBox @Suppress("UnstableApiUsage") -@AutoService(TickThreadGuard::class) -class TickThreadGuardImpl : TickThreadGuard { - init { - checkInstantiationByServiceLoader() - } +class V1_21_11TickThreadGuard : TickThreadGuard { override fun ensureTickThread(world: World, pos: Position, reason: String) { TickThread.ensureTickThread(world.toNms(), pos.chunkX, pos.chunkZ, reason) @@ -68,4 +62,4 @@ class TickThreadGuardImpl : TickThreadGuard { ) { TickThread.ensureTickThread(world.toNms(), blockX, blockZ, reason) } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/build.gradle.kts b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/build.gradle.kts new file mode 100644 index 000000000..97fa8fa77 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + `core-convention` + id("io.papermc.paperweight.userdev") apply true +} + +kotlin { + compilerOptions { + optIn.add("dev.slne.surf.api.paper.visualizer.visualizer.ExperimentalVisualizerApi") + } +} + +dependencies { + api(projects.surfApiPaper.surfApiPaperNms.surfApiPaperNmsCommon) + api(projects.surfApiCore.surfApiCoreServer) + + paperweight.paperDevBundle("26.1+") + + compileOnly(libs.placeholder.api) + compileOnly(libs.reflection.remapper) + compileOnly(libs.mccoroutine.folia.api) + compileOnly(libs.scoreboard.library.api) + + implementation(libs.bytebuddy) +} + +configurations.all { + exclude(group = "org.spigotmc", module = "spigot-api") +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/V26_1NmsPacketBridgeHandler.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/V26_1NmsPacketBridgeHandler.kt new file mode 100644 index 000000000..d714b86a4 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/V26_1NmsPacketBridgeHandler.kt @@ -0,0 +1,29 @@ +package dev.slne.surf.api.paper.server.nms.v26_1 + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsPacketBridgeHandler +import dev.slne.surf.api.paper.nms.listener.packets.NmsPacket +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.V26_1NmsPacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.V26_1PacketRegistry +import net.minecraft.network.protocol.Packet + +@NmsUseWithCaution +@Suppress("ClassName") +object V26_1NmsPacketBridgeHandler : NmsPacketBridgeHandler { + + @Suppress("UNCHECKED_CAST") + override fun wrapServerboundPacket(nmsPacket: Any): NmsServerboundPacket? { + return V26_1PacketRegistry.createServerboundPacketOrNull(nmsPacket as Packet<*>) + } + + @Suppress("UNCHECKED_CAST") + override fun wrapClientboundPacket(nmsPacket: Any): NmsClientboundPacket? { + return V26_1PacketRegistry.createClientboundPacketOrNull(nmsPacket as Packet<*>) + } + + override fun unwrapPacket(apiPacket: NmsPacket): Any { + return V26_1NmsPacketImpl.getFromApi(apiPacket).nmsPacket + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/V26_1NmsProvider.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/V26_1NmsProvider.kt new file mode 100644 index 000000000..9d228478f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/V26_1NmsProvider.kt @@ -0,0 +1,103 @@ +package dev.slne.surf.api.paper.server.nms.v26_1 + +import dev.slne.surf.api.paper.glow.SurfGlowingApi +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.* +import dev.slne.surf.api.paper.nms.bridges.packets.SurfPaperNmsPacketBridges +import dev.slne.surf.api.paper.nms.bridges.packets.block.SurfPaperNmsBlockPackets +import dev.slne.surf.api.paper.nms.bridges.packets.entity.SurfPaperNmsSpawnPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerChatPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerToastPackets +import dev.slne.surf.api.paper.nms.common.* +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener +import dev.slne.surf.api.paper.region.TickThreadGuard +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.* +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1SurfPaperNmsPacketBridgesImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.block.V26_1SurfPaperNmsBlockPacketsImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.entity.V26_1SurfPaperNmsSpawnPacketsImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.player.V26_1SurfPaperNmsPlayerChatPacketsImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.player.V26_1SurfPaperNmsPlayerPacketsImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.player.V26_1SurfPaperNmsPlayerToastPacketsImpl +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1GlowingLifecycleHandler +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v26_1.packet.listener.V26_1ChannelInjector +import dev.slne.surf.api.paper.server.nms.v26_1.packet.listener.V26_1GlowingPacketListener +import dev.slne.surf.api.paper.server.nms.v26_1.packet.lore.V26_1PacketLoreListener +import dev.slne.surf.api.paper.server.nms.v26_1.packet.lore.V26_1PacketLoreRegistry +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection +import dev.slne.surf.api.paper.server.nms.v26_1.region.V26_1TickThreadGuard +import dev.slne.surf.api.shared.internal.nms.NmsProviderMarker +import dev.slne.surf.api.shared.internal.nms.NmsVersion +import org.bukkit.plugin.java.JavaPlugin + +@Suppress("ClassName") +@OptIn(NmsUseWithCaution::class) +@NmsProviderMarker(NmsVersion.V26_1) +class V26_1NmsProvider(override val plugin: JavaPlugin) : NmsProvider { + override val version: NmsVersion = NmsVersion.V26_1 + + override fun createNmsBridge() = V26_1SurfPaperNmsBridgeImpl() + override fun createCommonBridge(): SurfPaperNmsCommonBridge = + V26_1SurfPaperNmsCommonBridgeImpl() + + override fun createEntityBridge(): SurfPaperNmsEntityBridge = + V26_1SurfPaperNmsEntityBridgeImpl() + + override fun createItemBridge(): SurfPaperNmsItemBridge = V26_1SurfPaperNmsItemBridgeImpl() + override fun createNbtBridge(): SurfPaperNmsNbtBridge = V26_1SurfPaperNmsNbtBridgeImpl() + override fun createGlowingBridge(): SurfPaperNmsGlowingBridge = V26_1SurfPaperNmsGlowingBridgeImpl + + override fun createStatsBridge(): SurfPaperNmsStatsBridge = + V26_1SurfPaperNmsStatsBridgeImpl() + + override fun createLootTableBridge(): SurfPaperNmsLootTableBridge = + V26_1SurfPaperNmsLootTableBridgeImpl() + + override fun createCommandArgumentTypesBridge(): SurfPaperNmsCommandArgumentTypesBridge = + V26_1SurfPaperNmsCommandArgumentTypesBridgeImpl() + + override fun createPacketBridges(): SurfPaperNmsPacketBridges = + V26_1SurfPaperNmsPacketBridgesImpl() + + override fun createBlockPackets(): SurfPaperNmsBlockPackets = + V26_1SurfPaperNmsBlockPacketsImpl() + + override fun createSpawnPackets(): SurfPaperNmsSpawnPackets = + V26_1SurfPaperNmsSpawnPacketsImpl() + + override fun createPlayerPackets(): SurfPaperNmsPlayerPackets = + V26_1SurfPaperNmsPlayerPacketsImpl() + + override fun createPlayerChatPackets(): SurfPaperNmsPlayerChatPackets = + V26_1SurfPaperNmsPlayerChatPacketsImpl() + + override fun createPlayerToastPackets(): SurfPaperNmsPlayerToastPackets = + V26_1SurfPaperNmsPlayerToastPacketsImpl() + + override fun createTickThreadGuard(): TickThreadGuard = V26_1TickThreadGuard() + override fun getLibLoaderBridge(): LibLoaderBridge = V26_1LibLoaderBridgeImpl + + override fun getPacketBridgeHandler(): NmsPacketBridgeHandler = V26_1NmsPacketBridgeHandler + + override fun createPacketLoreRegistry(): PacketLoreRegistry = V26_1PacketLoreRegistry() + override fun createGlowingLifecycleHandler(): GlowingLifecycleHandler = + V26_1GlowingLifecycleHandler() + + override fun createGlowingApi(): SurfGlowingApi = V26_1SurfGlowingApiImpl + override fun createChannelInjector(): AbstractChannelInjector<*> = V26_1ChannelInjector + override fun createPacketListenerApi(): InternalPacketListenerApiBridge = V26_1PacketListenerApiImpl() + + override fun createPacketListeners(): List = listOf( + V26_1PacketLoreListener, + V26_1GlowingPacketListener, + ) + + override fun initialize() { + V26_1Reflection.initialize() + } + + override fun shutdown() { + // No cleanup needed + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1LibLoaderBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1LibLoaderBridgeImpl.kt new file mode 100644 index 000000000..3a99bd10d --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1LibLoaderBridgeImpl.kt @@ -0,0 +1,58 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import dev.slne.surf.api.core.reflection.Field +import dev.slne.surf.api.core.reflection.Field.Type +import dev.slne.surf.api.core.reflection.SurfProxy +import dev.slne.surf.api.core.reflection.SurfReflection +import dev.slne.surf.api.core.reflection.createProxy +import dev.slne.surf.api.core.util.setFinalField +import dev.slne.surf.api.paper.nms.common.LibLoaderBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.commodore +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.craftServer +import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader +import org.bukkit.craftbukkit.util.ApiVersion +import java.net.URLClassLoader + +@Suppress("ClassName") +object V26_1LibLoaderBridgeImpl : LibLoaderBridge { + + override fun getActiveCompatibilities(): MutableSet { + return craftServer.activeCompatibilities + } + + override fun convertWithCommodore( + b: ByteArray, + pluginName: String, + pluginVersion: String, + activeCompatibilities: MutableSet + ): ByteArray { + return commodore.convert( + b, + pluginName, + ApiVersion.getOrCreateVersion(pluginVersion), + activeCompatibilities + ) + } + + @Suppress("DEPRECATION") + override fun overwriteLibraryLoader(pluginClassLoader: URLClassLoader, newLoader: URLClassLoader) { + PaperPluginClassLoader::class.java.getDeclaredField("libraryLoader").apply { + setAccessible(true) + setFinalField(this, pluginClassLoader, newLoader) + } + } + + override fun getLibraryLoader(pluginClassLoader: URLClassLoader): URLClassLoader { + return PaperPluginClassLoaderProxy.instance.getLibraryLoader(pluginClassLoader as PaperPluginClassLoader) + } + + @SurfProxy(PaperPluginClassLoader::class) + interface PaperPluginClassLoaderProxy { + @Field("libraryLoader", Type.GETTER) + fun getLibraryLoader(instance: PaperPluginClassLoader): URLClassLoader + + companion object { + val instance = SurfReflection.createProxy() + } + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1PacketListenerApiImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1PacketListenerApiImpl.kt new file mode 100644 index 000000000..88794c40f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1PacketListenerApiImpl.kt @@ -0,0 +1,224 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.InternalPacketListenerApiBridge +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener +import dev.slne.surf.api.paper.packet.listener.listener.PacketListenerResult +import dev.slne.surf.api.paper.packet.listener.listener.annotation.ClientboundListener +import dev.slne.surf.api.paper.packet.listener.listener.annotation.ServerboundListener +import net.minecraft.network.protocol.Packet +import net.minecraft.server.level.ServerPlayer +import org.bukkit.entity.Player +import java.lang.invoke.MethodHandle +import java.lang.invoke.MethodHandles +import java.lang.invoke.MethodType +import java.lang.reflect.Method +import java.lang.reflect.Modifier +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap +import java.util.concurrent.CopyOnWriteArraySet + +@NmsUseWithCaution +class V26_1PacketListenerApiImpl : InternalPacketListenerApiBridge { + private typealias ListenerMethodsMap = ConcurrentHashMap, CopyOnWriteArraySet> + + private val log = logger() + + private val clientboundListenerMethods = ListenerMethodsMap() + private val serverboundListenerMethods = ListenerMethodsMap() + private val lookup = MethodHandles.lookup() + + private val normalizedListenerType = MethodType.methodType( + Any::class.java, + Packet::class.java, + ServerPlayer::class.java + ) + + private val toBukkitPlayerHandle: MethodHandle = lookup.findStatic( + V26_1PacketListenerApiImpl::class.java, + "toBukkitPlayer", + MethodType.methodType(Player::class.java, ServerPlayer::class.java) + ) + + companion object { + @Suppress("unused") + @JvmStatic + fun toBukkitPlayer(serverPlayer: ServerPlayer?): Player? = serverPlayer?.bukkitEntity + } + + override fun registerListeners(listener: PacketListener) { + for (method in listener.javaClass.declaredMethods) { + try { + if (method.isAnnotationPresent(ClientboundListener::class.java)) { + registerListenerMethod(listener, method, clientboundListenerMethods) + } else if (method.isAnnotationPresent(ServerboundListener::class.java)) { + registerListenerMethod(listener, method, serverboundListenerMethods) + } + } catch (e: IllegalAccessException) { + log.atSevere() + .withCause(e) + .log("Failed to register listener method '${method.declaringClass.name}#${method.name}' due to illegal access") + } + } + } + + private fun registerListenerMethod( + listener: PacketListener, + method: Method, + listenerMethods: ConcurrentMap, CopyOnWriteArraySet> + ) { + require(!Modifier.isStatic(method.modifiers)) { "Listener method must not be static: ${method.declaringClass.name}#${method.name}" } + require(method.parameterCount in 1..2) { "Listener method must have 1 or 2 parameters (Packet and optional ServerPlayer/Player): ${method.declaringClass.name}#${method.name}" } + + val packetParameterType = method.parameterTypes[0] + require(Packet::class.java.isAssignableFrom(packetParameterType)) { "Packet parameter must be a subclass of Packet: ${method.declaringClass.name}#${method.name}" } + + val playerParameterType = method.parameterTypes.getOrNull(1) + val hasServerPlayerParameter = + playerParameterType != null && ServerPlayer::class.java.isAssignableFrom( + playerParameterType + ) + + if (playerParameterType != null) { + val isBukkitPlayer = Player::class.java.isAssignableFrom(playerParameterType) + require(isBukkitPlayer || hasServerPlayerParameter) { "Second parameter must be either ServerPlayer or a Bukkit Player: ${method.declaringClass.name}#${method.name}" } + } + + val privateLookupIn = try { + MethodHandles.privateLookupIn(method.declaringClass, lookup) + } catch (_: IllegalAccessException) { + method.trySetAccessible() + lookup + } + + val methodHandle = createNormalizedInvokerHandle(listener, method, privateLookupIn) + val listeners = + listenerMethods.computeIfAbsent(packetParameterType) { CopyOnWriteArraySet() } + val invoker = createInvoker(methodHandle, method.returnType) + + listeners.add(ListenerMethod(listener, invoker)) + } + + private fun createNormalizedInvokerHandle( + listener: PacketListener, + method: Method, + lookup: MethodHandles.Lookup + ): MethodHandle { + val bound = lookup.unreflect(method).bindTo(listener) + val parameterTypes = method.parameterTypes + + val adapted = when (parameterTypes.size) { + 1 -> { + MethodHandles.dropArguments(bound, 1, ServerPlayer::class.java) + } + + 2 -> { + val second = parameterTypes[1] + + when { + ServerPlayer::class.java.isAssignableFrom(second) -> bound + Player::class.java.isAssignableFrom(second) -> + MethodHandles.filterArguments(bound, 1, toBukkitPlayerHandle) + + else -> error("Unsupported second parameter: $second") + } + } + + else -> error("Unsupported parameter count: ${parameterTypes.size}") + } + + return adapted.asType(normalizedListenerType) + } + + @Suppress("UNCHECKED_CAST") + private fun createInvoker( + mh: MethodHandle, + returnType: Class<*> + ): ListenerInvoker { + val resultConverter = createResultConverter(returnType) as ListenerResultConverter + return { packet, player -> + @Suppress("USELESS_CAST") + val result: Any? = mh.invokeExact(packet as Packet<*>, player as ServerPlayer?) + resultConverter.convert(result, packet) + } + } + + private fun createResultConverter(returnType: Class<*>): ListenerResultConverter<*> = when { + returnType == Void.TYPE -> ListenerResultConverter { _, p -> p } + returnType == PacketListenerResult::class.java -> ListenerResultConverter { result, packet -> + if (result == PacketListenerResult.CANCEL) null else packet + } + + Packet::class.java.isAssignableFrom(returnType) -> ListenerResultConverter?> { result, original -> + result + } + + else -> error("Unsupported return type for packet listener method: $returnType! Only void, PacketListenerResult, or a subclass of Packet is supported.") + } + + + override fun unregisterListeners(listener: PacketListener) { + for (methods in clientboundListenerMethods.values) { + methods.removeIf { it.listener == listener } + } + for (methods in serverboundListenerMethods.values) { + methods.removeIf { it.listener == listener } + } + } + + override fun handleClientboundPacket(packet: Any, serverPlayer: Any?): Any? { + packet as Packet<*> + serverPlayer as ServerPlayer? + + val methods = clientboundListenerMethods[packet.javaClass] ?: return packet + var result: Packet<*>? = packet + + try { + for (listenerMethod in methods) { + result = listenerMethod.invoker.invoke(result ?: break, serverPlayer) + if (result == null) break + } + } catch (t: Throwable) { + log.atSevere() + .withCause(t) + .log("Failed to handle clientbound packet") + } + + return result + } + + override fun handleServerboundPacket(packet: Any, serverPlayer: Any?): Any? { + packet as Packet<*> + serverPlayer as ServerPlayer? + + val methods = serverboundListenerMethods[packet.javaClass] ?: return packet + var result: Packet<*>? = packet + + try { + for (listenerMethod in methods) { + result = listenerMethod.invoker.invoke(result ?: break, serverPlayer) + if (result == null) break + } + } catch (t: Throwable) { + log.atSevere() + .withCause(t) + .log("Failed to handle serverbound packet") + } + + return result + } + + fun interface ListenerResultConverter { + fun convert(result: T?, packet: Packet<*>?): Packet<*>? + } + + fun interface ListenerInvoker { + fun invoke(packet: Packet<*>, serverPlayer: ServerPlayer?): Packet<*>? + } + + private data class ListenerMethod( + val listener: PacketListener, + val invoker: ListenerInvoker, + ) +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsBridgeImpl.kt new file mode 100644 index 000000000..e982c2691 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsBridgeImpl.kt @@ -0,0 +1,128 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import com.google.common.flogger.StackSize +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.api.nms.listener.NmsClientboundPacketListener +import dev.slne.surf.api.paper.api.nms.listener.NmsServerboundPacketListener +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.InternalNmsBridge +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket +import dev.slne.surf.api.paper.packet.listener.listener.PacketListenerResult +import org.bukkit.entity.Player +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.CopyOnWriteArraySet + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsBridgeImpl : InternalNmsBridge { + private typealias PacketListenerMap = ConcurrentHashMap, CopyOnWriteArraySet> + + private val log = logger() + + private val serverboundPacketListeners = PacketListenerMap>() + private val clientboundPacketListeners = PacketListenerMap>() + + override fun registerServerboundPacketListener(listener: NmsServerboundPacketListener<*>) { + val packetClass = listener.packetClass + val added = + serverboundPacketListeners.computeIfAbsent(packetClass) { CopyOnWriteArraySet() } + .add(listener) + + if (!added) { + log.atWarning() + .withStackTrace(StackSize.MEDIUM) + .log("Serverbound packet listener $listener is already registered") + } + } + + override fun unregisterServerboundPacketListener(listener: NmsServerboundPacketListener<*>) { + val removed = serverboundPacketListeners[listener.packetClass]?.remove(listener) == true + + if (!removed) { + log.atWarning() + .withStackTrace(StackSize.MEDIUM) + .log("Serverbound packet listener $listener is not registered") + } + } + + override fun registerClientboundPacketListener(listener: NmsClientboundPacketListener<*>) { + val packetClass = listener.packetClass + val added = + clientboundPacketListeners.computeIfAbsent(packetClass) { CopyOnWriteArraySet() } + .add(listener) + + if (!added) { + log.atWarning() + .withStackTrace(StackSize.MEDIUM) + .log("Clientbound packet listener $listener is already registered") + } + } + + override fun unregisterClientboundPacketListener(listener: NmsClientboundPacketListener<*>) { + val removed = clientboundPacketListeners[listener.packetClass]?.remove(listener) == true + + if (!removed) { + log.atWarning() + .withStackTrace(StackSize.MEDIUM) + .log("Clientbound packet listener $listener is not registered") + } + } + + @Suppress("UNCHECKED_CAST") + override fun handleServerboundPacket( + packet: Packet, + player: Player?, + ): Packet? { + val clazz = packet.packetClass + val listener = serverboundPacketListeners[clazz] ?: return packet + + var cancel = false + for (listener in listener) { + listener as NmsServerboundPacketListener + val result = try { + listener.handleEarlyServerboundPacket(packet, player) + } catch (e: Throwable) { + log.atSevere() + .withCause(e) + .log("Failed to handle serverbound packet $clazz for listener $listener") + PacketListenerResult.CONTINUE + } + + if (result == PacketListenerResult.CANCEL) { + cancel = true + } + } + + return if (cancel) null else packet + } + + @Suppress("UNCHECKED_CAST") + override fun handleClientboundPacket( + packet: Packet, + player: Player?, + ): Packet? { + val listeners = clientboundPacketListeners[packet.packetClass] ?: return packet + + if (listeners.isEmpty()) return packet + + var cancel = false + for (listener in listeners) { + listener as NmsClientboundPacketListener + val result = try { + listener.handleEarlyClientboundPacket(packet, player) + } catch (e: Throwable) { + log.atSevere() + .withCause(e) + .log("Failed to handle clientbound packet ${packet.packetClass} for listener $listener") + PacketListenerResult.CONTINUE + } + + if (result == PacketListenerResult.CANCEL) { + cancel = true + } + } + + return if (cancel) null else packet + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsCommandArgumentTypesBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsCommandArgumentTypesBridgeImpl.kt new file mode 100644 index 000000000..221c24dfe --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsCommandArgumentTypesBridgeImpl.kt @@ -0,0 +1,108 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import com.mojang.brigadier.arguments.ArgumentType +import com.mojang.brigadier.context.CommandContext +import com.mojang.brigadier.exceptions.CommandSyntaxException +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommandArgumentTypesBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.AdventureNBT +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection +import net.bytebuddy.ByteBuddy +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy +import net.bytebuddy.dynamic.scaffold.TypeValidation +import net.bytebuddy.implementation.InvocationHandlerAdapter +import net.bytebuddy.implementation.bind.annotation.RuntimeType +import net.bytebuddy.matcher.ElementMatchers +import net.kyori.adventure.nbt.CompoundBinaryTag +import net.minecraft.commands.arguments.CompoundTagArgument +import java.lang.reflect.InvocationHandler +import java.util.concurrent.ConcurrentHashMap + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsCommandArgumentTypesBridgeImpl : SurfPaperNmsCommandArgumentTypesBridge { + + override fun compoundTag(): ArgumentType<*> { + return CompoundTagArgument.compoundTag() + } + + override fun getCompoundTag(ctx: CommandContext<*>, key: String): CompoundBinaryTag { + val nms = CompoundTagArgument.getCompoundTag(ctx, key) + return AdventureNBT.fromNms(nms) + } + + @Suppress("UNCHECKED_CAST") + private fun wrap( + base: ArgumentType, + converter: OpenedResultConverter + ): ArgumentType { + val wrappedConverter = OpenedResultConverterImpl.of(converter) + val wrapped = V26_1Reflection.VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY.wrap( + V26_1Reflection.VANILLA_ARGUMENT_PROVIDER_PROXY.provider(), + base, + wrappedConverter + ) as ArgumentType + + return wrapped + } + + + fun interface OpenedResultConverter { + @Throws(CommandSyntaxException::class) + fun convert(type: T): R + } + + object OpenedResultConverterImpl { + private val converterCache = ConcurrentHashMap() + + @Suppress("UNCHECKED_CAST") + fun of(converter: OpenedResultConverter): Any { + val cacheKey = "${converter.javaClass.name}_${System.identityHashCode(converter)}" + + return converterCache.computeIfAbsent(cacheKey) { + createConverter(converter) + } + } + + @Suppress("UNCHECKED_CAST") + private fun createConverter(converter: OpenedResultConverter): Any { + val resultConverterInterface = Class.forName( + "io.papermc.paper.command.brigadier.argument.VanillaArgumentProviderImpl\$ResultConverter" + ) + + val handler = InvocationHandler { _, method, args -> + when (method.name) { + "convert" -> converter.convert(args[0] as B) + else -> throw UnsupportedOperationException("Unknown method: ${method.name}") + } + } + + val dynamicType = ByteBuddy() + .with(TypeValidation.DISABLED) + .subclass(Any::class.java) + .implement(resultConverterInterface) + .name("io.papermc.paper.command.brigadier.argument.GeneratedResultConverter\$${System.nanoTime()}") + .method(ElementMatchers.any()) + .intercept(InvocationHandlerAdapter.of(handler)) + .make() + + val loadedClass = dynamicType.load( + resultConverterInterface.classLoader, + ClassLoadingStrategy.Default.INJECTION + ).loaded + + return loadedClass.getDeclaredConstructor().newInstance() + } + + + class InterceptorHolder( + private val converter: OpenedResultConverter + ) { + @RuntimeType + @Throws(Exception::class) + fun convert(@RuntimeType input: B): C { + return converter.convert(input) + } + } + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsCommonBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsCommonBridgeImpl.kt new file mode 100644 index 000000000..c00cba923 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsCommonBridgeImpl.kt @@ -0,0 +1,91 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import dev.slne.surf.api.paper.dialog.noticeDialogWithBuilder +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommonBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNmsBlock +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNmsItem +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection +import io.papermc.paper.configuration.GlobalConfiguration +import net.kyori.adventure.text.Component +import net.minecraft.network.protocol.common.ClientboundClearDialogPacket +import net.minecraft.server.MinecraftServer +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.ComposterBlock +import org.bukkit.Bukkit +import org.bukkit.Material +import org.bukkit.block.data.BlockData +import org.bukkit.entity.Player +import java.net.InetSocketAddress + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsCommonBridgeImpl : SurfPaperNmsCommonBridge { + + @Suppress("DEPRECATION") + override fun nextEntityId(): Int { + return Bukkit.getUnsafe().nextEntityId() + } + + override fun getStateId(material: Material): Int { + return Block.getId(material.toNmsBlock().defaultBlockState()) + } + + override fun getStateId(blockData: BlockData): Int { + return Block.getId(blockData.toNms()) + } + + override fun generateNextInventoryId(player: Player): Int { + return player.toNms().nextContainerCounter() + } + + override fun addCompostable(material: Material, levelIncreaseChance: Float) { + require(material.isItem) { "material must be an item" } + + ComposterBlock.COMPOSTABLES.put(material.toNmsItem(), levelIncreaseChance) + } + + override fun removeCompostable(material: Material) { + require(material.isItem) { "material must be an item" } + ComposterBlock.COMPOSTABLES.removeFloat(material.toNmsItem()) + } + + override fun setVelocityEnabled(enabled: Boolean) { + GlobalConfiguration.get().proxies.velocity.enabled = enabled + } + + override fun isVelocityEnabled(): Boolean { + return GlobalConfiguration.get().proxies.velocity.enabled + } + + override fun setVelocitySecret(secret: String) { + GlobalConfiguration.get().proxies.velocity.secret = secret + } + + override fun getVelocitySecret(): String { + return GlobalConfiguration.get().proxies.velocity.secret + } + + override fun setOnlineMode(enabled: Boolean) { + MinecraftServer.getServer().setUsesAuthentication(enabled) + } + + override fun clearDialogs(player: Player, showEmptyDialogBefore: Boolean) { + if (showEmptyDialogBefore) { + player.showDialog(noticeDialogWithBuilder(Component.empty()) {}) + } + + player.toNms().connection.send(ClientboundClearDialogPacket.INSTANCE) + } + + override fun getServerIp(): InetSocketAddress { + val channels = + V26_1Reflection.SERVER_CONNECTION_LISTENER_PROXY.getChannels(MinecraftServer.getServer().connection) + val channel = + channels.firstOrNull() ?: error("No channels found in server connection listener proxy") + + return channel.channel().localAddress() as? InetSocketAddress + ?: error("Local address is not an instance of InetSocketAddress") + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsEntityBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsEntityBridgeImpl.kt new file mode 100644 index 000000000..afab07b30 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsEntityBridgeImpl.kt @@ -0,0 +1,54 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import ca.spottedleaf.moonrise.common.util.TickThread +import com.mojang.brigadier.exceptions.CommandSyntaxException +import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsEntityBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.AdventureNBT +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNmsHolder +import dev.slne.surf.api.paper.util.chunkX +import dev.slne.surf.api.paper.util.chunkZ +import io.papermc.paper.math.FinePosition +import net.kyori.adventure.nbt.CompoundBinaryTag +import net.minecraft.server.MinecraftServer +import net.minecraft.server.commands.SummonCommand +import org.bukkit.World +import org.bukkit.entity.EntityType + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsEntityBridgeImpl : SurfPaperNmsEntityBridge { + + @Suppress("UnstableApiUsage") + override fun createEntityByNbt( + world: World, + type: EntityType, + pos: FinePosition, + tag: CompoundBinaryTag + ) { + val worldNMS = world.toNms() + TickThread.ensureTickThread( + worldNMS, + pos.chunkX, + pos.chunkZ, + "Cannot create entity asynchronously" + ) + + val source = MinecraftServer.getServer().createCommandSourceStack() + .withLevel(worldNMS) + + try { + SummonCommand.createEntity( + source, + type.toNmsHolder(), + pos.toNms(), + AdventureNBT.toNms(tag), + false + ) + } catch (e: CommandSyntaxException) { + throw WrapperCommandSyntaxException(e) + } + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsGlowingBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsGlowingBridgeImpl.kt similarity index 54% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsGlowingBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsGlowingBridgeImpl.kt index 9e6a3957f..904bcbd17 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsGlowingBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsGlowingBridgeImpl.kt @@ -1,29 +1,28 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v26_1.bridges -import com.google.auto.service.AutoService import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsGlowingBridge import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation -import dev.slne.surf.api.paper.server.impl.glow.GlowingPacketListener -import dev.slne.surf.api.paper.server.impl.glow.TeamData -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.nms.toNms -import dev.slne.surf.api.paper.server.reflection.Reflection +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1TeamData +import dev.slne.surf.api.paper.server.nms.v26_1.packet.listener.V26_1GlowingPacketListener +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket import net.minecraft.network.syncher.SynchedEntityData.DataValue import org.bukkit.entity.Entity @NmsUseWithCaution -@AutoService(SurfPaperNmsGlowingBridge::class) -class SurfPaperNmsGlowingBridgeImpl : SurfPaperNmsGlowingBridge { - fun createTeam(data: TeamData): PacketOperation = - PacketOperationImpl.simple { +@Suppress("ClassName") +object V26_1SurfPaperNmsGlowingBridgeImpl : SurfPaperNmsGlowingBridge { + fun createTeam(data: V26_1TeamData): PacketOperation = + V26_1PacketOperationImpl.simple { ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(data.team, true) } - fun addEntityToTeam(data: TeamData, entry: String): PacketOperation = - PacketOperationImpl.simple { + fun addEntityToTeam(data: V26_1TeamData, entry: String): PacketOperation = + V26_1PacketOperationImpl.simple { ClientboundSetPlayerTeamPacket.createPlayerPacket( data.team, entry, @@ -31,8 +30,8 @@ class SurfPaperNmsGlowingBridgeImpl : SurfPaperNmsGlowingBridge { ) } - fun removeEntityFromTeam(data: TeamData, entry: String): PacketOperation = - PacketOperationImpl.simple { + fun removeEntityFromTeam(data: V26_1TeamData, entry: String): PacketOperation = + V26_1PacketOperationImpl.simple { ClientboundSetPlayerTeamPacket.createPlayerPacket( data.team, entry, @@ -41,22 +40,18 @@ class SurfPaperNmsGlowingBridgeImpl : SurfPaperNmsGlowingBridge { } fun setEntityFlags(entityId: Int, flags: Byte, ignorePacket: Boolean = false): PacketOperation = - PacketOperationImpl.simple { - val dataAccessor = Reflection.ENTITY_PROXY.getDataFlagsSharedId() + V26_1PacketOperationImpl.simple { + val dataAccessor = V26_1Reflection.ENTITY_PROXY.getDataFlagsSharedId() val data = DataValue(dataAccessor.id(), dataAccessor.serializer, flags) ClientboundSetEntityDataPacket(entityId, listOf(data)).also { if (ignorePacket) { - GlowingPacketListener.ignorePacket(it) + V26_1GlowingPacketListener.ignorePacket(it) } } } override fun getCurrentFlags(entity: Entity): Byte { - val dataAccessor = Reflection.ENTITY_PROXY.getDataFlagsSharedId() + val dataAccessor = V26_1Reflection.ENTITY_PROXY.getDataFlagsSharedId() return entity.toNms().entityData.get(dataAccessor) } - - companion object { - val INSTANCE get() = SurfPaperNmsGlowingBridge.INSTANCE as SurfPaperNmsGlowingBridgeImpl - } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsItemBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsItemBridgeImpl.kt new file mode 100644 index 000000000..aa16475b7 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsItemBridgeImpl.kt @@ -0,0 +1,26 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsItemBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.nms +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection +import net.minecraft.core.component.DataComponentMap +import net.minecraft.core.component.DataComponents +import org.bukkit.inventory.ItemType + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsItemBridgeImpl : SurfPaperNmsItemBridge { + override fun setDefaultMaxStackSize(item: ItemType, maxStackSize: Int) { + require(maxStackSize in 1..100) { "Max stack size must be between 1 and 100" } + + val nmsItem = item.nms + val updatedComponents = DataComponentMap.builder() + .addAll(nmsItem.components()) + .set(DataComponents.MAX_STACK_SIZE, maxStackSize) + .build() + + + V26_1Reflection.ITEM_PROXY.setComponents(nmsItem, updatedComponents) + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsLootTableBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsLootTableBridgeImpl.kt new file mode 100644 index 000000000..a08e77409 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsLootTableBridgeImpl.kt @@ -0,0 +1,56 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import dev.slne.surf.api.core.util.emptyObjectList +import dev.slne.surf.api.core.util.mutableObjectListOf +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsLootTableBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toBukkit +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import net.minecraft.server.MinecraftServer +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.storage.loot.LootParams +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets +import net.minecraft.world.level.storage.loot.parameters.LootContextParams +import org.bukkit.damage.DamageSource +import org.bukkit.entity.EntityType +import org.bukkit.entity.LivingEntity +import org.bukkit.inventory.ItemStack +import kotlin.jvm.optionals.getOrNull + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsLootTableBridgeImpl : SurfPaperNmsLootTableBridge { + override fun getDifferentLootTable( + entity: LivingEntity, + damageSource: DamageSource, + replacement: EntityType, + causedByPlayer: Boolean, + ): Collection { + val lootTableKey = + replacement.toNms().defaultLootTable.getOrNull() ?: return emptyObjectList() + val lootTable = + MinecraftServer.getServer().reloadableRegistries().getLootTable(lootTableKey) + val nmsEntity = entity.toNms() + val nmsDamageSource = damageSource.toNms() + + val lootParamsBuilder = LootParams.Builder(nmsEntity.level() as ServerLevel) + .withParameter(LootContextParams.THIS_ENTITY, nmsEntity) + .withParameter(LootContextParams.ORIGIN, nmsEntity.position()) + .withParameter(LootContextParams.DAMAGE_SOURCE, nmsDamageSource) + .withOptionalParameter(LootContextParams.ATTACKING_ENTITY, nmsDamageSource.entity) + .withOptionalParameter( + LootContextParams.DIRECT_ATTACKING_ENTITY, + nmsDamageSource.directEntity + ) + + val lastHurtByPlayer = nmsEntity.getLastHurtByPlayer() + if (causedByPlayer && lastHurtByPlayer != null) { + lootParamsBuilder.withParameter(LootContextParams.LAST_DAMAGE_PLAYER, lastHurtByPlayer) + .withLuck(lastHurtByPlayer.luck) + } + + val lootParams = lootParamsBuilder.create(LootContextParamSets.ENTITY) + return lootTable.getRandomItems(lootParams, nmsEntity.lootTableSeed) + .mapTo(mutableObjectListOf()) { it.toBukkit() } + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsNbtBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsNbtBridgeImpl.kt similarity index 86% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsNbtBridgeImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsNbtBridgeImpl.kt index 53ff32738..95268d1c8 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsNbtBridgeImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsNbtBridgeImpl.kt @@ -1,11 +1,10 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges +package dev.slne.surf.api.paper.server.nms.v26_1.bridges -import com.google.auto.service.AutoService import dev.slne.surf.api.core.util.logger import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsNbtBridge -import dev.slne.surf.api.paper.server.nms.toBukkit -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toBukkit +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms import net.minecraft.core.component.DataComponentPatch import net.minecraft.core.component.DataComponents import net.minecraft.nbt.CompoundTag @@ -15,10 +14,9 @@ import org.bukkit.entity.EntityType import org.bukkit.inventory.ItemStack import kotlin.jvm.optionals.getOrNull -@AutoService(SurfPaperNmsNbtBridge::class) @NmsUseWithCaution -class SurfPaperNmsNbtBridgeImpl : SurfPaperNmsNbtBridge { - +@Suppress("ClassName") +class V26_1SurfPaperNmsNbtBridgeImpl : SurfPaperNmsNbtBridge { private val log = logger() override fun makeItemStackEntityInvisible( diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsStatsBridgeImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsStatsBridgeImpl.kt new file mode 100644 index 000000000..c00489e6e --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/V26_1SurfPaperNmsStatsBridgeImpl.kt @@ -0,0 +1,22 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsStatsBridge +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection +import org.bukkit.entity.Player + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsStatsBridgeImpl : SurfPaperNmsStatsBridge { + + override fun getPlayerStatsAsJson(player: Player): String { + val gson = V26_1Reflection.SERVER_STATS_COUNTER_PROXY.getGson() + val jsonElement = V26_1Reflection.SERVER_STATS_COUNTER_PROXY.toJson(player.toNms().stats) + return gson.toJson(jsonElement) + } + + override fun savePlayerStatsToFile(player: Player) { + player.toNms().stats.save() + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/PacketOperationImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/V26_1PacketOperationImpl.kt similarity index 76% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/PacketOperationImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/V26_1PacketOperationImpl.kt index 99b7afed5..61a5752ae 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/PacketOperationImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/V26_1PacketOperationImpl.kt @@ -1,15 +1,16 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets import com.google.common.flogger.FluentLogger import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms import net.minecraft.network.protocol.Packet import net.minecraft.network.protocol.game.ClientGamePacketListener import net.minecraft.network.protocol.game.ClientboundBundlePacket import org.bukkit.entity.Player import java.util.* -class PacketOperationImpl : PacketOperation { +@Suppress("ClassName") +class V26_1PacketOperationImpl : PacketOperation { private var operation: Operation private constructor(operation: Operation) { @@ -39,8 +40,8 @@ class PacketOperationImpl : PacketOperation { connection.send(ClientboundBundlePacket(packets)) } - override fun add(operation: PacketOperation): PacketOperationImpl { - require(operation is PacketOperationImpl) { "operation must be an instance of PacketOperationImpl" } + override fun add(operation: PacketOperation): V26_1PacketOperationImpl { + require(operation is V26_1PacketOperationImpl) { "operation must be an instance of V26_1PacketOperationImpl" } this.operation = this.operation.andThen(operation.operation) return this @@ -89,24 +90,24 @@ class PacketOperationImpl : PacketOperation { private val logger: FluentLogger = FluentLogger.forEnclosingClass() @JvmStatic - fun empty(): PacketOperationImpl { - return PacketOperationImpl() + fun empty(): V26_1PacketOperationImpl { + return V26_1PacketOperationImpl() } @JvmStatic - fun complex(operation: Operation): PacketOperationImpl { - return PacketOperationImpl(operation) + fun complex(operation: Operation): V26_1PacketOperationImpl { + return V26_1PacketOperationImpl(operation) } - fun simple(packetSupplier: (Player) -> Packet): PacketOperationImpl { - return PacketOperationImpl { player, packets -> + fun simple(packetSupplier: (Player) -> Packet): V26_1PacketOperationImpl { + return V26_1PacketOperationImpl { player, packets -> packets.add(packetSupplier(player)) packets } } - fun task(task: (Player) -> Unit): PacketOperationImpl { - return PacketOperationImpl { player, packets -> + fun task(task: (Player) -> Unit): V26_1PacketOperationImpl { + return V26_1PacketOperationImpl { player, packets -> task(player) packets } diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/V26_1SurfPaperNmsPacketBridgesImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/V26_1SurfPaperNmsPacketBridgesImpl.kt new file mode 100644 index 000000000..b4ad45f67 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/V26_1SurfPaperNmsPacketBridgesImpl.kt @@ -0,0 +1,13 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.SurfPaperNmsPacketBridges + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsPacketBridgesImpl : SurfPaperNmsPacketBridges { + + override fun createEmptyPacketOperation(): V26_1PacketOperationImpl { + return V26_1PacketOperationImpl.empty() + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/block/SurfPaperNmsBlockPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/block/V26_1SurfPaperNmsBlockPacketsImpl.kt similarity index 53% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/block/SurfPaperNmsBlockPacketsImpl.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/block/V26_1SurfPaperNmsBlockPacketsImpl.kt index c301a011c..0b0c8f3b0 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/block/SurfPaperNmsBlockPacketsImpl.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/block/V26_1SurfPaperNmsBlockPacketsImpl.kt @@ -1,26 +1,21 @@ @file:Suppress("UnstableApiUsage") -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets.block +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.block -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.packets.block.SurfPaperNmsBlockPackets -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms import io.papermc.paper.math.BlockPosition import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket import org.bukkit.block.data.BlockData -@AutoService(SurfPaperNmsBlockPackets::class) @NmsUseWithCaution -class SurfPaperNmsBlockPacketsImpl : SurfPaperNmsBlockPackets { - init { - checkInstantiationByServiceLoader() - } +@Suppress("ClassName") +class V26_1SurfPaperNmsBlockPacketsImpl : SurfPaperNmsBlockPackets { override fun updateBlockData(position: BlockPosition, blockData: BlockData) = - PacketOperationImpl.simple { + V26_1PacketOperationImpl.simple { ClientboundBlockUpdatePacket( position.toNms(), blockData.toNms() @@ -28,11 +23,10 @@ class SurfPaperNmsBlockPacketsImpl : SurfPaperNmsBlockPackets { } - override fun resetBlock(position: BlockPosition) = PacketOperationImpl.simple { + override fun resetBlock(position: BlockPosition) = V26_1PacketOperationImpl.simple { ClientboundBlockUpdatePacket( it.toNms().level(), position.toNms() ) } } - diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/entity/V26_1SurfPaperNmsSpawnPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/entity/V26_1SurfPaperNmsSpawnPacketsImpl.kt new file mode 100644 index 000000000..b555a7ed5 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/entity/V26_1SurfPaperNmsSpawnPacketsImpl.kt @@ -0,0 +1,207 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.entity + +import com.google.common.flogger.StackSize +import com.mojang.math.Transformation +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.entity.* +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import io.papermc.paper.math.BlockPosition +import io.papermc.paper.math.FinePosition +import it.unimi.dsi.fastutil.ints.IntList +import net.minecraft.core.HolderLookup +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtOps +import net.minecraft.network.protocol.game.* +import net.minecraft.server.MinecraftServer +import net.minecraft.world.entity.Display +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.EntityType +import net.minecraft.world.entity.PositionMoveRotation +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.entity.SignText +import net.minecraft.world.phys.Vec3 +import org.bukkit.entity.TextDisplay.TextAlignment +import kotlin.experimental.and +import kotlin.experimental.inv +import kotlin.experimental.or + +@Suppress("UnstableApiUsage", "ClassName") +@NmsUseWithCaution +class V26_1SurfPaperNmsSpawnPacketsImpl : SurfPaperNmsSpawnPackets { + private val log = logger() + + override fun despawn(entityIds: IntList) = + V26_1PacketOperationImpl.simple { ClientboundRemoveEntitiesPacket(entityIds) } + + override fun despawn(vararg entityId: Int) = + V26_1PacketOperationImpl.simple { ClientboundRemoveEntitiesPacket(*entityId) } + + + override fun spawnItemDisplay( + entityId: Int, + position: FinePosition, + settings: ItemDisplaySettings, + ) = V26_1PacketOperationImpl.complex { player, packets -> + val serverPlayer = player.toNms() + val display = Display.ItemDisplay(EntityType.ITEM_DISPLAY, serverPlayer.level()).apply { + id = entityId + + setPosition(position) + applySettings(settings) + + itemStack = settings.itemStack.toNms() + itemTransform = settings.itemDisplayTransform.toNms() + } + + packets.add(ClientboundAddEntityPacket(display, 0, display.blockPosition())) + packets.add(createSetEntityDataPacket(entityId, display)) + packets + } + + override fun spawnTextDisplay( + entityId: Int, + position: FinePosition, + settings: TextDisplaySettings, + ) = V26_1PacketOperationImpl.complex { player, packets -> + val serverPlayer = player.toNms() + val display = Display.TextDisplay(EntityType.TEXT_DISPLAY, serverPlayer.level()).apply { + id = entityId + + setPosition(position) + applySettings(settings) + + text = settings.text.toNms() + + val data = getEntityData() + data[Display.TextDisplay.DATA_LINE_WIDTH_ID] = settings.lineWidth + data[Display.TextDisplay.DATA_BACKGROUND_COLOR_ID] = settings.backgroundColor.value() + + when (settings.textAlignment) { + TextAlignment.CENTER -> { + setFlag(Display.TextDisplay.FLAG_ALIGN_LEFT, false) + setFlag(Display.TextDisplay.FLAG_ALIGN_RIGHT, false) + } + + TextAlignment.LEFT -> { + setFlag(Display.TextDisplay.FLAG_ALIGN_LEFT, true) + setFlag(Display.TextDisplay.FLAG_ALIGN_RIGHT, false) + } + + TextAlignment.RIGHT -> { + setFlag(Display.TextDisplay.FLAG_ALIGN_LEFT, false) + setFlag(Display.TextDisplay.FLAG_ALIGN_RIGHT, true) + } + } + } + + + packets.add(ClientboundAddEntityPacket(display, 0, display.blockPosition())) + packets.add(createSetEntityDataPacket(entityId, display)) + packets + } + + override fun updateSign( + entityId: Int, + position: BlockPosition, + settings: SignBlockUpdateSettings, + ) = V26_1PacketOperationImpl.complex { player, packets -> + val nbt = CompoundTag() + val registryLookup = MinecraftServer.getServer().registryAccess() + writeUpdateSignToTag(nbt, registryLookup, settings.frontText, settings.backText) + + packets.add(ClientboundBlockEntityDataPacket(position.toNms(), BlockEntityType.SIGN, nbt)) + packets + } + + override fun spawnBlockDisplay( + entityId: Int, + position: FinePosition, + settings: BlockDisplaySettings, + ) = V26_1PacketOperationImpl.complex { player, packets -> + val serverPlayer = player.toNms() + val display = Display.BlockDisplay(EntityType.BLOCK_DISPLAY, serverPlayer.level()).apply { + id = entityId + + setPosition(position) + applySettings(settings) + blockState = settings.blockData.toNms() + } + + packets.add(ClientboundAddEntityPacket(display, 0, display.blockPosition())) + packets.add(createSetEntityDataPacket(entityId, display)) + packets + } + + override fun teleport( + entityId: Int, + position: FinePosition, + yaw: Float, + pitch: Float, + deltaMovement: FinePosition?, + onGround: Boolean, + ) = V26_1PacketOperationImpl.simple { + ClientboundTeleportEntityPacket.teleport( + entityId, + PositionMoveRotation(position.toNms(), deltaMovement?.toNms() ?: Vec3.ZERO, yaw, pitch), + emptySet(), + onGround + ) + } + + private fun createSetEntityDataPacket(entityId: Int, entity: Entity) = + ClientboundSetEntityDataPacket(entityId, entity.getEntityData().packAll()) + + private fun writeUpdateSignToTag( + nbt: CompoundTag, + registryLookup: HolderLookup.Provider, + frontText: SignBlockUpdateSettings.SignText, + backText: SignBlockUpdateSettings.SignText, + ) { + writeTextToTag(nbt, registryLookup, frontText, "front_text", true) + writeTextToTag(nbt, registryLookup, backText, "back_text", false) + } + + private fun writeTextToTag( + nbt: CompoundTag, + registryLookup: HolderLookup.Provider, + text: SignBlockUpdateSettings.SignText, + tagText: String, + isFrontText: Boolean, + ) { + val nbtOps = registryLookup.createSerializationContext(NbtOps.INSTANCE) + val textTag = SignText.DIRECT_CODEC.encodeStart(nbtOps, text.toNms()) + textTag.resultOrPartial { logFailedEncodeText(it, isFrontText) } + .ifPresent { nbt.put(tagText, it) } + } + + private fun logFailedEncodeText(string: String, front: Boolean) { + log.atSevere() + .withStackTrace(StackSize.MEDIUM) + .atMostEvery(5, java.util.concurrent.TimeUnit.SECONDS) + .log("Failed to encode %s text: %s", if (front) "front" else "back", string) + } + + private fun getTransformation(settings: DisplaySettings) = Transformation( + settings.translation.toNms(), + settings.leftRotation.toNms(), + settings.scale.toNms(), + settings.rightRotation.toNms() + ) + + private fun Display.applySettings(settings: DisplaySettings) { + xRot = settings.pitch + yRot = settings.yaw + setTransformation(getTransformation(settings)) + billboardConstraints = settings.billboardConstraints.toNms() + } + + private fun Entity.setPosition(position: FinePosition) { + setPosRaw(position.x(), position.y(), position.z()) + } + + private fun Display.TextDisplay.setFlag(flag: Byte, set: Boolean) { + flags = if (set) flags or flag else flags and flag.inv() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerChatPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerChatPacketsImpl.kt new file mode 100644 index 000000000..b26d9870f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerChatPacketsImpl.kt @@ -0,0 +1,65 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.player + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.nms.bridges.packets.player.LastSeenMessagesPacked +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerChatPackets +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import net.kyori.adventure.chat.SignedMessage +import net.kyori.adventure.text.Component +import net.minecraft.network.chat.ChatType +import net.minecraft.network.chat.FilterMask +import net.minecraft.network.chat.LastSeenMessages +import net.minecraft.network.chat.SignedMessageBody +import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket +import net.minecraft.server.MinecraftServer +import java.time.Instant +import java.util.* +import net.minecraft.network.chat.MessageSignature as NmsMessageSignature + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsPlayerChatPacketsImpl : SurfPaperNmsPlayerChatPackets { + override fun sendPlayerChatMessagePacket( + senderUuid: UUID, + senderDisplayName: Component, + globalIndex: Int, + index: Int, + signature: SignedMessage.Signature?, + salt: Long, + timestamp: Instant, + content: String, + unsignedContent: Component?, + lastSeen: LastSeenMessagesPacked, + ): PacketOperation = V26_1PacketOperationImpl.simple { player -> + val messageSignature = signature?.let { NmsMessageSignature(it.bytes()) } + val signedBody = SignedMessageBody.Packed(content, timestamp, salt, lastSeen.toNms()) + + ClientboundPlayerChatPacket( + globalIndex, + senderUuid, + index, + messageSignature, + signedBody, + unsignedContent?.toNms(), + FilterMask.PASS_THROUGH, + ChatType.bind( + ChatType.CHAT, + MinecraftServer.getServer().registryAccess(), + senderDisplayName.toNms() + ) + ) + } + + private fun LastSeenMessagesPacked.toNms(): LastSeenMessages.Packed { + val list = mutableListOf() + + for ((id, signature) in this) { + val nmsSignature = signature?.let { NmsMessageSignature(it.bytes()) } + list.add(NmsMessageSignature.Packed(id, nmsSignature)) + } + + return LastSeenMessages.Packed(list) + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerPacketsImpl.kt new file mode 100644 index 000000000..c46222214 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerPacketsImpl.kt @@ -0,0 +1,55 @@ +@file:Suppress("UnstableApiUsage") + +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.player + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerPackets +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import io.papermc.paper.math.BlockPosition +import net.kyori.adventure.text.Component +import net.minecraft.network.protocol.game.ClientboundContainerClosePacket +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket +import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket +import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket +import org.bukkit.event.inventory.InventoryType +import org.bukkit.inventory.ItemStack + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsPlayerPacketsImpl : SurfPaperNmsPlayerPackets { + + override fun openSignEditor( + position: BlockPosition, + frontSide: Boolean, + ) = V26_1PacketOperationImpl.simple { ClientboundOpenSignEditorPacket(position.toNms(), frontSide) } + + override fun openInventory( + syncId: Int, + type: InventoryType, + title: Component, + ) = V26_1PacketOperationImpl.simple { + ClientboundOpenScreenPacket( + syncId, + type.toNms(), + title.toNms() + ) + } + + override fun setInventorySlot( + syncId: Int, + revision: Int, + slot: Int, + item: ItemStack, + ) = V26_1PacketOperationImpl.simple { + ClientboundContainerSetSlotPacket( + syncId, + revision, + slot, + item.toNms() + ) + } + + override fun closeInventory(syncId: Int) = + V26_1PacketOperationImpl.simple { ClientboundContainerClosePacket(syncId) } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerToastPacketsImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerToastPacketsImpl.kt new file mode 100644 index 000000000..cc969ea12 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/bridges/packets/player/V26_1SurfPaperNmsPlayerToastPacketsImpl.kt @@ -0,0 +1,61 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.player + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerToastPackets +import dev.slne.surf.api.paper.nms.bridges.packets.player.toast.Toast +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import net.minecraft.advancements.Advancement +import net.minecraft.advancements.AdvancementProgress +import net.minecraft.advancements.AdvancementRequirements +import net.minecraft.network.chat.Component +import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket +import net.minecraft.resources.Identifier +import java.util.* + + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SurfPaperNmsPlayerToastPacketsImpl : SurfPaperNmsPlayerToastPackets { + override fun showToast(toast: Toast) = V26_1PacketOperationImpl.complex { _, packets -> + val id = Identifier.fromNamespaceAndPath("surfapi", "toast_${UUID.randomUUID()}") + + packets.add(showPacket(id, toast)) + packets.add(hidePacket(id)) + + packets + } + + private fun showPacket(id: Identifier, toast: Toast) = + ClientboundUpdateAdvancementsPacket( + false, listOf(createAdvancement(id, toast)), emptySet(), mapOf( + id to AdvancementProgress().apply { + update(requirements) + grantProgress(CRITERION_ID) + }), true + ) + + private fun hidePacket(id: Identifier) = ClientboundUpdateAdvancementsPacket( + false, emptyList(), setOf(id), emptyMap(), false + ) + + private fun createAdvancement(id: Identifier, toast: Toast) = + Advancement.Builder.recipeAdvancement() + .display( + toast.icon.toNms().item, + toast.title.toNms(), + Component.empty(), + null, + toast.frame.toNms(), + true, + false, + false + ) + .requirements(requirements) + .build(id) + + companion object { + private const val CRITERION_ID = "surfapi_toast" + private val requirements by lazy { AdvancementRequirements.allOf(listOf(CRITERION_ID)) } + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/nms/AdventureNBT.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/extensions/AdventureNBT.kt similarity index 98% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/nms/AdventureNBT.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/extensions/AdventureNBT.kt index 80ee2ca13..2b7c4c305 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/nms/AdventureNBT.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/extensions/AdventureNBT.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.nms +package dev.slne.surf.api.paper.server.nms.v26_1.extensions import net.kyori.adventure.nbt.* import net.minecraft.nbt.* @@ -93,4 +93,4 @@ object AdventureNBT { adventure.build() } } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/nms/nms-extensions.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/extensions/nms-extensions.kt similarity index 99% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/nms/nms-extensions.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/extensions/nms-extensions.kt index 2c27f1a6f..5fce86c03 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/nms/nms-extensions.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/extensions/nms-extensions.kt @@ -1,6 +1,6 @@ @file:Suppress("UnstableApiUsage") -package dev.slne.surf.api.paper.server.nms +package dev.slne.surf.api.paper.server.nms.v26_1.extensions import dev.slne.surf.api.paper.extensions.server import dev.slne.surf.api.paper.nms.bridges.packets.entity.SignBlockUpdateSettings @@ -147,4 +147,4 @@ fun AdvancementDisplay.Frame.toNms() = when (this) { CHALLENGE -> AdvancementType.CHALLENGE GOAL -> AdvancementType.GOAL TASK -> AdvancementType.TASK -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1GlowingLifecycleHandler.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1GlowingLifecycleHandler.kt new file mode 100644 index 000000000..703c314d3 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1GlowingLifecycleHandler.kt @@ -0,0 +1,36 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.glow + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.nms.common.GlowingLifecycleHandler +import dev.slne.surf.api.paper.util.chunkX +import dev.slne.surf.api.paper.util.chunkZ +import org.bukkit.World +import org.bukkit.entity.Player + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1GlowingLifecycleHandler : GlowingLifecycleHandler { + override fun removeAllGlowingOnQuit(player: Player) { + V26_1SurfGlowingApiImpl.removeAllGlowingOnQuit(player) + } + + override fun getBlockGlowSpawnOperationForChunk( + player: Player, + chunkX: Int, + chunkZ: Int, + world: World + ): PacketOperation? { + val playerData = V26_1SurfGlowingApiImpl.getBlockPlayerData(player) ?: return null + val blockDataList = playerData.blocks + if (blockDataList.isEmpty()) return null + + val spawnOperation = PacketOperation.start() + for ((loc, block) in blockDataList) { + if (loc.chunkX != chunkX || loc.chunkZ != chunkZ || loc.world != world) continue + spawnOperation.add(block.spawn()) + } + + return spawnOperation + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1SurfGlowingApiImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1SurfGlowingApiImpl.kt new file mode 100644 index 000000000..4a73bcfa8 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1SurfGlowingApiImpl.kt @@ -0,0 +1,170 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.glow + +import com.github.shynixn.mccoroutine.folia.entityDispatcher +import com.github.shynixn.mccoroutine.folia.launch +import dev.slne.surf.api.paper.extensions.server +import dev.slne.surf.api.paper.glow.SurfGlowingApi +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.nms.common.NmsProvider +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.V26_1SurfPaperNmsGlowingBridgeImpl +import dev.slne.surf.api.paper.server.nms.v26_1.glow.block.BlockGlowingData +import dev.slne.surf.api.paper.server.nms.v26_1.glow.block.BlockPlayerData +import dev.slne.surf.api.paper.server.nms.v26_1.glow.entity.EntityGlowingData +import dev.slne.surf.api.paper.server.nms.v26_1.glow.entity.EntityPlayerData +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection +import dev.slne.surf.api.paper.util.isChunkVisible +import io.papermc.paper.adventure.PaperAdventure +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.Location +import org.bukkit.block.Block +import org.bukkit.entity.Entity +import org.bukkit.entity.Player +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +@NmsUseWithCaution +@Suppress("ClassName") +object V26_1SurfGlowingApiImpl : SurfGlowingApi { + private val entityPlayerData = ConcurrentHashMap() + private val blockPlayerData = ConcurrentHashMap() + + val glowingFlag = 1 shl V26_1Reflection.ENTITY_PROXY.getFlagGlowing() + + override fun makeGlowing( + target: Entity, + viewer: Player, + color: NamedTextColor?, + ) { + makeGlowing( + target.entityId, + teamIdFor(target), + viewer, + color, + V26_1SurfPaperNmsGlowingBridgeImpl.getCurrentFlags(target) + ) + } + + override fun makeGlowing( + targetId: Int, + teamId: String, + viewer: Player, + color: NamedTextColor?, + otherFlags: Byte, + ) { + val nmsColor = color?.let { PaperAdventure.asVanilla(it) } + val uuid = viewer.uniqueId + val playerData = entityPlayerData.computeIfAbsent(uuid) { EntityPlayerData(uuid) } + val glowingData = playerData.entities[targetId] + val operation = PacketOperation.start() + + if (glowingData == null) { + val newData = EntityGlowingData( + playerData, + targetId, + teamId, + nmsColor, + otherFlags + ) + playerData.entities[targetId] = newData + + operation.add(newData.sendGlowingFlag(enabled = true, ignorePacket = true)) + if (nmsColor != null) { + operation.add(newData.sendTeamColor()) + } + operation.execute(viewer) + return + } + + if (nmsColor == glowingData.color) return + if (nmsColor == null) { + operation.add(glowingData.removeFromTeam()) + glowingData.color = null + } else { + glowingData.color = nmsColor + operation.add(glowingData.sendTeamColor()) + } + + operation.execute(viewer) + } + + override fun makeGlowing(block: Block, viewer: Player, color: NamedTextColor) { + makeGlowing(block.location, viewer, color) + } + + override fun makeGlowing(location: Location, viewer: Player, color: NamedTextColor) { + location.checkFinite() + val blockLocation = location.toBlockLocation() + val uuid = viewer.uniqueId + val playerData = blockPlayerData.getOrPut(uuid) { BlockPlayerData(uuid) } + val blockData = playerData.blocks[blockLocation] + + if (blockData == null) { + val newData = BlockGlowingData(playerData, blockLocation, color) + playerData.blocks[blockLocation] = newData + + val plugin = NmsProvider.current.plugin + plugin.launch(plugin.entityDispatcher(viewer)) { + if (viewer.isChunkVisible(blockLocation)) { + newData.spawn().execute(viewer) + } + } + } else { + blockData.color = color + blockData.updateColor() + } + } + + override fun removeGlowing(target: Entity, viewer: Player) { + removeGlowing(target.entityId, viewer) + } + + fun removeGlowing(targetId: Int, viewer: UUID) { + val player = server.getPlayer(viewer) + + if (player == null) { + entityPlayerData[viewer]?.entities?.remove(targetId) + } else { + removeGlowing(targetId, player) + } + } + + override fun removeGlowing(targetId: Int, viewer: Player) { + val playerData = entityPlayerData[viewer.uniqueId] ?: return + val glowingData = playerData.entities.remove(targetId) ?: return + val operation = glowingData.sendGlowingFlag(enabled = false) + glowingData.removeFromTeam() + operation.execute(viewer) + } + + override fun removeGlowing(block: Block, viewer: Player) { + removeGlowing(block.location, viewer) + } + + override fun removeGlowing(location: Location, viewer: Player) { + location.checkFinite() + val blockLocation = location.toBlockLocation() + val playerData = blockPlayerData[viewer.uniqueId] ?: return + val blockData = playerData.blocks.remove(blockLocation) ?: return + + blockData.remove() + if (playerData.blocks.isEmpty()) { + blockPlayerData.remove(viewer.uniqueId) + } + } + + private fun teamIdFor(entity: Entity) = (entity as? Player)?.name ?: entity.uniqueId.toString() + + + fun getEntityPlayerData(player: Player): EntityPlayerData? = + entityPlayerData[player.uniqueId] + + fun getBlockPlayerData(player: Player): BlockPlayerData? = + blockPlayerData[player.uniqueId] + + fun removeAllGlowingOnQuit(player: Player) { + val uuid = player.uniqueId + V26_1TeamData.removeFromAll(uuid) + entityPlayerData.remove(uuid)?.entities?.clear() + blockPlayerData.remove(uuid)?.blocks?.clear() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1TeamData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1TeamData.kt new file mode 100644 index 000000000..2d98ff548 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/V26_1TeamData.kt @@ -0,0 +1,41 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.glow + +import net.minecraft.ChatFormatting +import net.minecraft.world.scores.PlayerTeam +import net.minecraft.world.scores.Scoreboard +import net.minecraft.world.scores.Team +import java.util.* +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicInteger + +@Suppress("ClassName") +class V26_1TeamData(color: ChatFormatting) { + private val scoreboard = Scoreboard() + val teamId = "glow-${uid()}${color.char}" + val team = PlayerTeam(scoreboard, teamId).apply { + collisionRule = Team.CollisionRule.NEVER + this.color = color + } + + private val seenBy = ConcurrentHashMap.newKeySet() + + fun markSeen(uniqueId: UUID) = seenBy.add(uniqueId) + fun isSeen(uniqueId: UUID): Boolean = seenBy.contains(uniqueId) + fun removeSeen(uniqueId: UUID) = seenBy.remove(uniqueId) + + companion object { + private val lastUid = AtomicInteger() + fun uid(): Int = lastUid.getAndIncrement() + + private val teams = EnumMap(ChatFormatting::class.java) + + fun getByColor(color: ChatFormatting): V26_1TeamData = + teams.computeIfAbsent(color) { V26_1TeamData(color) } + + fun getByColorOrNull(color: ChatFormatting): V26_1TeamData? = teams[color] + + fun removeFromAll(uuid: UUID) { + teams.values.forEach { it.removeSeen(uuid) } + } + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/block/BlockGlowingData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/block/BlockGlowingData.kt similarity index 70% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/block/BlockGlowingData.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/block/BlockGlowingData.kt index ef207ea16..403bf294f 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/block/BlockGlowingData.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/block/BlockGlowingData.kt @@ -1,13 +1,13 @@ -package dev.slne.surf.api.paper.server.impl.glow.block +package dev.slne.surf.api.paper.server.nms.v26_1.glow.block import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommonBridge import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation import dev.slne.surf.api.paper.nms.bridges.packets.entity.SurfPaperNmsSpawnPackets -import dev.slne.surf.api.paper.server.impl.glow.SurfGlowingApiImpl -import dev.slne.surf.api.paper.server.impl.nms.bridges.SurfPaperNmsGlowingBridgeImpl -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import dev.slne.surf.api.paper.server.reflection.Reflection +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.V26_1SurfPaperNmsGlowingBridgeImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection import glm_.shl import net.kyori.adventure.text.format.NamedTextColor import net.minecraft.network.protocol.game.ClientboundAddEntityPacket @@ -30,7 +30,7 @@ class BlockGlowingData( fun spawn(): PacketOperation { initialize() - val spawnOperation = PacketOperationImpl.simple { + val spawnOperation = V26_1PacketOperationImpl.simple { ClientboundAddEntityPacket( entityId, uuid, @@ -45,16 +45,15 @@ class BlockGlowingData( 0.0 ) } - val invisibleOperation = SurfPaperNmsGlowingBridgeImpl.INSTANCE - .setEntityFlags(entityId, invisibleFlag) - + val invisibleOperation = V26_1SurfPaperNmsGlowingBridgeImpl.setEntityFlags(entityId, invisibleFlag) + return spawnOperation + invisibleOperation } fun updateColor() { val player = playerData.player ?: return - SurfGlowingApiImpl.INSTANCE.makeGlowing( + V26_1SurfGlowingApiImpl.makeGlowing( entityId, uuid.toString(), player, @@ -65,7 +64,7 @@ class BlockGlowingData( fun remove() { playerData.player?.let { SurfPaperNmsSpawnPackets.despawn(entityId).execute(it) } - SurfGlowingApiImpl.INSTANCE.removeGlowing(entityId, playerData.uuid) + V26_1SurfGlowingApiImpl.removeGlowing(entityId, playerData.uuid) } private fun initialize() { @@ -75,6 +74,6 @@ class BlockGlowingData( } companion object { - val invisibleFlag = 1.toByte() shl Reflection.ENTITY_PROXY.getFlagInvisible() + val invisibleFlag = 1.toByte() shl V26_1Reflection.ENTITY_PROXY.getFlagInvisible() } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/block/BlockPlayerData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/block/BlockPlayerData.kt new file mode 100644 index 000000000..21bb86ba7 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/block/BlockPlayerData.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.glow.block + +import dev.slne.surf.api.paper.extensions.server +import org.bukkit.Location +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +class BlockPlayerData(val uuid: UUID) { + val blocks = ConcurrentHashMap() + val player get() = server.getPlayer(uuid) +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/entity/EntityGlowingData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/entity/EntityGlowingData.kt new file mode 100644 index 000000000..37cfa5348 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/entity/EntityGlowingData.kt @@ -0,0 +1,75 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.glow.entity + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.V26_1SurfPaperNmsGlowingBridgeImpl +import dev.slne.surf.api.paper.server.nms.v26_1.bridges.packets.V26_1PacketOperationImpl +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1TeamData +import glm_.and +import glm_.or +import net.minecraft.ChatFormatting + +@NmsUseWithCaution +@Suppress("ClassName") +data class EntityGlowingData( + val playerData: EntityPlayerData, + val entityId: Int, + val teamId: String, + var color: ChatFormatting?, + var otherFlags: Byte, +) { + + @OptIn(NmsUseWithCaution::class) + fun sendTeamColor(): PacketOperation { + val color = color ?: return V26_1PacketOperationImpl.empty() + val teamData = V26_1TeamData.getByColor(color) + + val operation = PacketOperation.start() + if (teamData.markSeen(playerData.uuid)) { + operation.add(V26_1SurfPaperNmsGlowingBridgeImpl.createTeam(teamData)) + } + operation.add(V26_1SurfPaperNmsGlowingBridgeImpl.addEntityToTeam(teamData, teamId)) + + return operation + } + + @OptIn(NmsUseWithCaution::class) + fun removeFromTeam(): PacketOperation { + val color = color ?: return V26_1PacketOperationImpl.empty() + val teamData = V26_1TeamData.getByColorOrNull(color) ?: return V26_1PacketOperationImpl.empty() + + val operation = PacketOperation.start() + if (teamData.removeSeen(playerData.uuid)) { + operation.add( + V26_1SurfPaperNmsGlowingBridgeImpl.removeEntityFromTeam( + teamData, + teamId + ) + ) + } + + return operation + } + + @OptIn(NmsUseWithCaution::class) + fun sendGlowingFlag(enabled: Boolean, ignorePacket: Boolean = false): PacketOperation { + val newFlags = if (enabled) { + otherFlags or V26_1SurfGlowingApiImpl.glowingFlag + } else { + otherFlags and V26_1SurfGlowingApiImpl.glowingFlag.inv() + } + + return V26_1SurfPaperNmsGlowingBridgeImpl.setEntityFlags( + entityId, + newFlags, + ignorePacket + ) + } + + fun computeFlags(): Byte { + return (otherFlags and V26_1SurfGlowingApiImpl.glowingFlag.inv()).or( + if (color != null) V26_1SurfGlowingApiImpl.glowingFlag else 0 + ) + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/entity/EntityPlayerData.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/entity/EntityPlayerData.kt new file mode 100644 index 000000000..e1578d04e --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/glow/entity/EntityPlayerData.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.glow.entity + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +@NmsUseWithCaution +@Suppress("ClassName") +data class EntityPlayerData(val uuid: UUID) { + val entities = ConcurrentHashMap() +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/V26_1NmsPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/V26_1NmsPacketImpl.kt new file mode 100644 index 000000000..dad8fafdd --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/V26_1NmsPacketImpl.kt @@ -0,0 +1,25 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.NmsPacket +import net.minecraft.network.PacketListener +import net.minecraft.network.protocol.Packet + +@NmsUseWithCaution +@Suppress("ClassName") +abstract class V26_1NmsPacketImpl, Listener : PacketListener>(var nmsPacket: Nms) : + NmsPacket { + val nmsClass = nmsPacket.javaClass + + override val packetClass = + javaClass.interfaces.find { NmsPacket::class.java.isAssignableFrom(it) } + ?: error("No packet interface found for ${javaClass.name}") + + companion object { + @JvmStatic + fun getFromApi(nmsPacket: NmsPacket): V26_1NmsPacketImpl<*, *> { + require(nmsPacket is V26_1NmsPacketImpl<*, *>) { "Invalid NmsPacket implementation: " + nmsPacket.javaClass.getName() } + return nmsPacket + } + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/PacketRegistry.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/V26_1PacketRegistry.kt similarity index 66% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/PacketRegistry.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/V26_1PacketRegistry.kt index b7fbdecf4..2ddace3bb 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/PacketRegistry.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/V26_1PacketRegistry.kt @@ -1,15 +1,15 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets -import dev.slne.surf.api.core.util.mutableObject2ObjectMapOf import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket import dev.slne.surf.api.paper.nms.listener.packets.serverbound.NmsServerboundPacket -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.clientbound.ClientboundDisconnectPacketImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.clientbound.ClientboundSystemChatPacketImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound.CommandSuggestionPacketImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound.RenameItemPacketImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound.ServerboundCustomPayloadPacketImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound.SignUpdatePacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.clientbound.V26_1ClientboundDisconnectPacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.clientbound.V26_1ClientboundSystemChatPacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound.V26_1CommandSuggestionPacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound.V26_1RenameItemPacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound.V26_1ServerboundCustomPayloadPacketImpl +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound.V26_1SignUpdatePacketImpl +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import net.minecraft.network.protocol.Packet import net.minecraft.network.protocol.common.ClientCommonPacketListener import net.minecraft.network.protocol.common.ClientboundDisconnectPacket @@ -22,23 +22,24 @@ import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket import kotlin.reflect.KClass @OptIn(NmsUseWithCaution::class) -object PacketRegistry { - private val SERVERBOUND_PACKETS = - mutableObject2ObjectMapOf>, ServerboundPacketFactory<*, *>>() - private val CLIENTBOUND_PACKETS = - mutableObject2ObjectMapOf>, ClientboundPacketFactory<*, *>>() +@Suppress("ClassName") +object V26_1PacketRegistry { + private typealias PacketMap = Object2ObjectOpenHashMap>, F> + + private val SERVERBOUND_PACKETS = PacketMap>() + private val CLIENTBOUND_PACKETS = PacketMap>() init { // @formatter:off // Serverbound packets - registerServerboundPacket(ServerboundSignUpdatePacket::class) { SignUpdatePacketImpl(it) } - registerServerboundPacket(ServerboundRenameItemPacket::class) { RenameItemPacketImpl(it) } - registerServerboundPacket(ServerboundCommandSuggestionPacket::class) { CommandSuggestionPacketImpl(it) } - registerServerboundPacket(ServerboundCustomPayloadPacket::class) { ServerboundCustomPayloadPacketImpl(it) } + registerServerboundPacket(ServerboundSignUpdatePacket::class) { V26_1SignUpdatePacketImpl(it) } + registerServerboundPacket(ServerboundRenameItemPacket::class) { V26_1RenameItemPacketImpl(it) } + registerServerboundPacket(ServerboundCommandSuggestionPacket::class) { V26_1CommandSuggestionPacketImpl(it) } + registerServerboundPacket(ServerboundCustomPayloadPacket::class) { V26_1ServerboundCustomPayloadPacketImpl(it) } // Clientbound packets - registerClientboundPacket(ClientboundDisconnectPacket::class) { ClientboundDisconnectPacketImpl(it) } - registerClientboundPacket(ClientboundSystemChatPacket::class) { ClientboundSystemChatPacketImpl(it) } + registerClientboundPacket(ClientboundDisconnectPacket::class) { V26_1ClientboundDisconnectPacketImpl(it) } + registerClientboundPacket(ClientboundSystemChatPacket::class) { V26_1ClientboundSystemChatPacketImpl(it) } // @formatter:on } diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1ClientboundDisconnectPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1ClientboundDisconnectPacketImpl.kt new file mode 100644 index 000000000..201fc9214 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1ClientboundDisconnectPacketImpl.kt @@ -0,0 +1,15 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.clientbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.DisconnectPacket +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toBukkit +import net.minecraft.network.protocol.common.ClientCommonPacketListener +import net.minecraft.network.protocol.common.ClientboundDisconnectPacket + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1ClientboundDisconnectPacketImpl(nmsPacket: ClientboundDisconnectPacket) : + V26_1NmsClientboundPacketImpl(nmsPacket), + DisconnectPacket { + override val reason get() = nmsPacket.reason.toBukkit() +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1ClientboundSystemChatPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1ClientboundSystemChatPacketImpl.kt new file mode 100644 index 000000000..edcf03ff4 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1ClientboundSystemChatPacketImpl.kt @@ -0,0 +1,26 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.clientbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.SystemChatPacket +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toBukkit +import net.kyori.adventure.text.Component +import net.minecraft.network.protocol.game.ClientGamePacketListener +import net.minecraft.network.protocol.game.ClientboundSystemChatPacket + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1ClientboundSystemChatPacketImpl(nmsPacket: ClientboundSystemChatPacket) : + V26_1NmsClientboundPacketImpl(nmsPacket), + SystemChatPacket { + override var content: Component + get() = nmsPacket.content().toBukkit() + set(value) { + nmsPacket = ClientboundSystemChatPacket(value, nmsPacket.overlay) + } + + override var overlay: Boolean + get() = nmsPacket.overlay() + set(value) { + nmsPacket = ClientboundSystemChatPacket(nmsPacket.content(), value) + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1NmsClientboundPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1NmsClientboundPacketImpl.kt new file mode 100644 index 000000000..ea1dd3f93 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/clientbound/V26_1NmsClientboundPacketImpl.kt @@ -0,0 +1,13 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.clientbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.V26_1NmsPacketImpl +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.common.ClientCommonPacketListener + +@NmsUseWithCaution +@Suppress("ClassName") +abstract class V26_1NmsClientboundPacketImpl, Listener : ClientCommonPacketListener>( + nmsPacket: Nms, +) : NmsClientboundPacket, V26_1NmsPacketImpl(nmsPacket) diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1CommandSuggestionPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1CommandSuggestionPacketImpl.kt new file mode 100644 index 000000000..101bc0e51 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1CommandSuggestionPacketImpl.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.CommandSuggestionPacket +import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1CommandSuggestionPacketImpl(nmsPacket: ServerboundCommandSuggestionPacket) : + V26_1NmsServerboundPacketImpl(nmsPacket), + CommandSuggestionPacket { + override val completionId get() = nmsPacket.id + override val command get() = nmsPacket.command +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1NmsServerboundPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1NmsServerboundPacketImpl.kt new file mode 100644 index 000000000..50a53f218 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1NmsServerboundPacketImpl.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.V26_1NmsPacketImpl +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.common.ServerCommonPacketListener + +@NmsUseWithCaution +@Suppress("ClassName") +abstract class V26_1NmsServerboundPacketImpl>(nmsPacket: Nms) : + V26_1NmsPacketImpl(nmsPacket) diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1RenameItemPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1RenameItemPacketImpl.kt new file mode 100644 index 000000000..f607aebef --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1RenameItemPacketImpl.kt @@ -0,0 +1,12 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.RenameItemPacket +import net.minecraft.network.protocol.game.ServerboundRenameItemPacket + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1RenameItemPacketImpl(nmsPacket: ServerboundRenameItemPacket) : + V26_1NmsServerboundPacketImpl(nmsPacket), RenameItemPacket { + override val newName: String get() = nmsPacket.name +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1ServerboundCustomPayloadPacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1ServerboundCustomPayloadPacketImpl.kt new file mode 100644 index 000000000..acc03a7e8 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1ServerboundCustomPayloadPacketImpl.kt @@ -0,0 +1,43 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import io.papermc.paper.adventure.PaperAdventure +import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket +import net.minecraft.network.protocol.common.custom.BrandPayload +import net.minecraft.network.protocol.common.custom.CustomPacketPayload +import net.minecraft.network.protocol.common.custom.DiscardedPayload +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.ServerboundCustomPayloadPacket.Payload as ApiPayload + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1ServerboundCustomPayloadPacketImpl( + nmsPacket: ServerboundCustomPayloadPacket +) : V26_1NmsServerboundPacketImpl(nmsPacket), + dev.slne.surf.api.paper.nms.listener.packets.serverbound.ServerboundCustomPayloadPacket { + + override var payload: ApiPayload + get() = toApiPayload(nmsPacket.payload); + set(value) { + nmsPacket = ServerboundCustomPayloadPacket(toNmsPayload(value)) + } + + companion object { + private fun toApiPayload(nmsPayload: CustomPacketPayload): ApiPayload = when (nmsPayload) { + is BrandPayload -> ApiPayload.Brand(nmsPayload.brand) + is DiscardedPayload -> ApiPayload.Discarded( + id = PaperAdventure.asAdventure(nmsPayload.id), + data = nmsPayload.data + ) + + else -> error("Unknown CustomPacketPayload type: ${nmsPayload.type()}") + } + + private fun toNmsPayload(apiPayload: ApiPayload): CustomPacketPayload = when (apiPayload) { + is ApiPayload.Brand -> BrandPayload(apiPayload.brand) + is ApiPayload.Discarded -> DiscardedPayload( + PaperAdventure.asVanilla(apiPayload.id), + apiPayload.data + ) + } + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1SignUpdatePacketImpl.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1SignUpdatePacketImpl.kt new file mode 100644 index 000000000..1c8b603f7 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/listener/packets/serverbound/V26_1SignUpdatePacketImpl.kt @@ -0,0 +1,20 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.listener.packets.serverbound + +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.listener.packets.serverbound.SignUpdatePacket +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toBukkit +import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket + +@NmsUseWithCaution +@Suppress("ClassName") +class V26_1SignUpdatePacketImpl(nmsPacket: ServerboundSignUpdatePacket) : + V26_1NmsServerboundPacketImpl(nmsPacket), SignUpdatePacket { + override val position get() = nmsPacket.pos.toBukkit() + override val lines: Array get() = nmsPacket.lines + override val isFrontText get() = nmsPacket.isFrontText + + override fun getLine(line: Int): String { + require(line in 1..4) { "Line must be between 1 and 4" } + return lines[line - 1] + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/listener/V26_1ChannelInjector.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/listener/V26_1ChannelInjector.kt new file mode 100644 index 000000000..4d9be3043 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/listener/V26_1ChannelInjector.kt @@ -0,0 +1,98 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.packet.listener + +import dev.slne.surf.api.core.reflection.Field +import dev.slne.surf.api.core.reflection.SurfProxy +import dev.slne.surf.api.core.reflection.SurfReflection +import dev.slne.surf.api.core.reflection.createProxy +import dev.slne.surf.api.core.util.logger +import dev.slne.surf.api.paper.nms.common.AbstractChannelInjector +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import io.netty.channel.Channel +import io.papermc.paper.connection.PaperPlayerLoginConnection +import io.papermc.paper.connection.ReadablePlayerCookieConnectionImpl +import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent +import io.papermc.paper.network.ChannelInitializeListenerHolder +import net.kyori.adventure.key.Key +import net.minecraft.network.Connection +import net.minecraft.network.HandlerNames +import net.minecraft.network.protocol.Packet +import net.minecraft.server.level.ServerPlayer +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.player.PlayerJoinEvent + +@Suppress("ClassName", "UnstableApiUsage") +object V26_1ChannelInjector : AbstractChannelInjector() { + private val log = logger() + + override fun registerChannelInitializeListener( + key: Key, + listener: (Channel) -> Unit + ) { + ChannelInitializeListenerHolder.addListener(key, listener) + } + + override fun unregisterChannelInitializeListener(key: Key) { + ChannelInitializeListenerHolder.removeListener(key) + } + + override fun createPacketHandler() = PacketHandler() + override fun getNmsChannelHandlerName(): String = HandlerNames.PACKET_HANDLER + + @EventHandler + fun onPlayerLogin(event: PlayerConnectionValidateLoginEvent) { + val paperConnection = event.connection + if (paperConnection is PaperPlayerLoginConnection) { + val profile = paperConnection.authenticatedProfile + + if (profile == null) { + event.kickMessage(createFailedToInjectPacketListenerDisconnectReason()) + + log.atWarning() + .log("Failed to inject packet listener for player (${paperConnection.unsafeProfile}) with unauthenticated profile: ${paperConnection.address} - ${paperConnection.clientAddress}") + return + } + + val connection = + ReadablePlayerCookieConnectionImplProxy.instance.getConnection(paperConnection) + val channel = connection.channel + getOrInjectPacketHandler(channel).connection = connection + } + } + + @EventHandler(priority = EventPriority.LOWEST) + fun onPlayerJoin(event: PlayerJoinEvent) { + val player = event.player.toNms() + val connection = player.connection.connection + val channel = connection.channel + + getOrInjectPacketHandler(channel).connection = connection + } + + class PacketHandler : AbstractPacketHandler() { + @Volatile + var connection: Connection? = null + + override fun isPacket(msg: Any): Boolean = msg is Packet<*> + override fun getPlayerFromConnection(): Any? { + val connection = this.connection ?: return NO_CONNECTION_SENTINEL + return connection.player as ServerPlayer? + } + + override fun getBukkitPlayer(player: Any?): Player? { + return (player as? ServerPlayer)?.bukkitEntity + } + } + + @SurfProxy(ReadablePlayerCookieConnectionImpl::class) + interface ReadablePlayerCookieConnectionImplProxy { + + @Field("connection", Field.Type.GETTER) + fun getConnection(instance: ReadablePlayerCookieConnectionImpl): Connection + + companion object { + val instance = SurfReflection.createProxy() + } + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingPacketListener.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/listener/V26_1GlowingPacketListener.kt similarity index 81% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingPacketListener.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/listener/V26_1GlowingPacketListener.kt index 5645ef977..3e0fafef1 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingPacketListener.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/listener/V26_1GlowingPacketListener.kt @@ -1,4 +1,4 @@ -package dev.slne.surf.api.paper.server.impl.glow +package dev.slne.surf.api.paper.server.nms.v26_1.packet.listener import com.github.benmanes.caffeine.cache.Caffeine import com.sksamuel.aedile.core.expireAfterWrite @@ -7,7 +7,8 @@ import dev.slne.surf.api.core.util.toMutableObjectList import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.packet.listener.listener.PacketListener import dev.slne.surf.api.paper.packet.listener.listener.annotation.ClientboundListener -import dev.slne.surf.api.paper.server.reflection.Reflection +import dev.slne.surf.api.paper.server.nms.v26_1.glow.V26_1SurfGlowingApiImpl +import dev.slne.surf.api.paper.server.nms.v26_1.reflection.V26_1Reflection import glm_.or import net.minecraft.network.protocol.Packet import net.minecraft.network.protocol.game.ClientboundBundlePacket @@ -17,7 +18,8 @@ import org.bukkit.entity.Player import kotlin.time.Duration.Companion.seconds @OptIn(NmsUseWithCaution::class) -object GlowingPacketListener : PacketListener { +@Suppress("ClassName") +object V26_1GlowingPacketListener : PacketListener { val ignoreCache = Caffeine.newBuilder() .weakKeys() @@ -59,13 +61,13 @@ object GlowingPacketListener : PacketListener { return packet } - val playerData = SurfGlowingApiImpl.getEntityPlayerData(player) ?: return packet - val glowingData = playerData.entities.get(packet.id) ?: return packet + val playerData = V26_1SurfGlowingApiImpl.getEntityPlayerData(player) ?: return packet + val glowingData = playerData.entities[packet.id] ?: return packet val incoming = packet.packedItems var flagsFound = false var edited = false val newItems = mutableObjectListOf>(incoming.size + 1) - val dataFlagsShared = Reflection.ENTITY_PROXY.getDataFlagsSharedId() + val dataFlagsShared = V26_1Reflection.ENTITY_PROXY.getDataFlagsSharedId() val dataFlagsSharedId = dataFlagsShared.id for (dataValue in incoming) { @@ -73,7 +75,7 @@ object GlowingPacketListener : PacketListener { flagsFound = true val current = dataValue.value as Byte glowingData.otherFlags = current - val withGlow: Byte = current or SurfGlowingApiImpl.glowingFlag + val withGlow: Byte = current or V26_1SurfGlowingApiImpl.glowingFlag if (withGlow != current) { edited = true @@ -87,7 +89,7 @@ object GlowingPacketListener : PacketListener { } if (!edited && !flagsFound) { - val withGlow = glowingData.otherFlags or SurfGlowingApiImpl.glowingFlag + val withGlow = glowingData.otherFlags or V26_1SurfGlowingApiImpl.glowingFlag if (withGlow != 0.toByte()) { edited = true newItems.add(DataValue(dataFlagsSharedId, dataFlagsShared.serializer, withGlow)) @@ -96,4 +98,4 @@ object GlowingPacketListener : PacketListener { return if (edited) ClientboundSetEntityDataPacket(packet.id, newItems) else packet } -} \ No newline at end of file +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PacketLoreListener.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/lore/V26_1PacketLoreListener.kt similarity index 97% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PacketLoreListener.kt rename to surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/lore/V26_1PacketLoreListener.kt index 475134c82..ef14bab69 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PacketLoreListener.kt +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/lore/V26_1PacketLoreListener.kt @@ -1,12 +1,12 @@ -package dev.slne.surf.api.paper.server.packet.lore +package dev.slne.surf.api.paper.server.nms.v26_1.packet.lore import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.packet.listener.listener.PacketListener import dev.slne.surf.api.paper.packet.listener.listener.annotation.ClientboundListener import dev.slne.surf.api.paper.packet.listener.listener.annotation.ServerboundListener import dev.slne.surf.api.paper.packet.lore.SurfPaperPacketLoreHandler -import dev.slne.surf.api.paper.server.nms.toBukkit -import dev.slne.surf.api.paper.server.nms.toNms +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toBukkit +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms import dev.slne.surf.api.paper.util.namespacedKey import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectArrayList @@ -28,7 +28,8 @@ import net.minecraft.network.chat.Component as MinecraftComponent * handling the modification of lore on item stacks in packet events. */ @OptIn(NmsUseWithCaution::class) -object PacketLoreListener : PacketListener { +@Suppress("ClassName") +object V26_1PacketLoreListener : PacketListener { private val globalHandlersByPlugin = Object2ObjectLinkedOpenHashMap>() diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/lore/V26_1PacketLoreRegistry.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/lore/V26_1PacketLoreRegistry.kt new file mode 100644 index 000000000..174adba35 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/packet/lore/V26_1PacketLoreRegistry.kt @@ -0,0 +1,25 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.packet.lore + +import dev.slne.surf.api.paper.nms.common.PacketLoreRegistry +import dev.slne.surf.api.paper.packet.lore.SurfPaperPacketLoreHandler +import org.bukkit.NamespacedKey +import org.bukkit.plugin.Plugin + +@Suppress("ClassName") +class V26_1PacketLoreRegistry : PacketLoreRegistry { + override fun register(plugin: Plugin, identifier: NamespacedKey, listener: SurfPaperPacketLoreHandler) { + V26_1PacketLoreListener.register(plugin, identifier, listener) + } + + override fun register(plugin: Plugin, listener: SurfPaperPacketLoreHandler) { + V26_1PacketLoreListener.register(plugin, listener) + } + + override fun unregister(identifier: NamespacedKey) { + V26_1PacketLoreListener.unregister(identifier) + } + + override fun unregister(plugin: Plugin) { + V26_1PacketLoreListener.unregister(plugin) + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1EntityProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1EntityProxy.kt new file mode 100644 index 000000000..d71202c80 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1EntityProxy.kt @@ -0,0 +1,24 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import net.minecraft.network.syncher.EntityDataAccessor +import net.minecraft.world.entity.Entity +import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter +import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies +import xyz.jpenilla.reflectionremapper.proxy.annotation.Static + +@Proxies(Entity::class) +@Suppress("ClassName") +interface V26_1EntityProxy { + + @FieldGetter("FLAG_GLOWING") + @Static + fun getFlagGlowing(): Int + + @FieldGetter("FLAG_INVISIBLE") + @Static + fun getFlagInvisible(): Int + + @FieldGetter("DATA_SHARED_FLAGS_ID") + @Static + fun getDataFlagsSharedId(): EntityDataAccessor +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ItemProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ItemProxy.kt new file mode 100644 index 000000000..8d6349e96 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ItemProxy.kt @@ -0,0 +1,13 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import net.minecraft.core.component.DataComponentMap +import net.minecraft.world.item.Item +import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter +import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies + +@Proxies(Item::class) +@Suppress("ClassName") +interface V26_1ItemProxy { + @FieldSetter("components") + fun setComponents(item: Item, components: DataComponentMap) +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1Reflection.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1Reflection.kt new file mode 100644 index 000000000..bc62d38b4 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1Reflection.kt @@ -0,0 +1,42 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import dev.slne.surf.api.core.reflection.SurfReflection +import dev.slne.surf.api.core.reflection.createProxy +import dev.slne.surf.api.paper.util.reflectionProxy +import xyz.jpenilla.reflectionremapper.ReflectionRemapper +import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory + +@Suppress("ClassName") +object V26_1Reflection { + lateinit var SERVER_STATS_COUNTER_PROXY: V26_1ServerStatsCounterProxy + private set + lateinit var ENTITY_PROXY: V26_1EntityProxy + private set + lateinit var ITEM_PROXY: V26_1ItemProxy + private set + lateinit var SERVER_CONNECTION_LISTENER_PROXY: V26_1ServerConnectionListenerProxy + private set + lateinit var VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY: V26_1VanillaArgumentProviderImplProxy + private set + lateinit var VANILLA_ARGUMENT_PROVIDER_PROXY: V26_1VanillaArgumentProviderProxy + private set + + fun initialize() { + val remapper = ReflectionRemapper.forReobfMappingsInPaperJar() + val proxyFactory = + ReflectionProxyFactory.create(remapper, V26_1Reflection::class.java.classLoader) + + SERVER_STATS_COUNTER_PROXY = proxyFactory.reflectionProxy() + ENTITY_PROXY = proxyFactory.reflectionProxy() + ITEM_PROXY = proxyFactory.reflectionProxy() + SERVER_CONNECTION_LISTENER_PROXY = + proxyFactory.reflectionProxy() + VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY = + SurfReflection.createProxy() + VANILLA_ARGUMENT_PROVIDER_PROXY = + SurfReflection.createProxy() + + // gc the remapper + System.gc() + } +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ServerConnectionListenerProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ServerConnectionListenerProxy.kt new file mode 100644 index 000000000..a2ab7a92f --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ServerConnectionListenerProxy.kt @@ -0,0 +1,13 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import io.netty.channel.ChannelFuture +import net.minecraft.server.network.ServerConnectionListener +import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter +import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies + +@Proxies(ServerConnectionListener::class) +@Suppress("ClassName") +interface V26_1ServerConnectionListenerProxy { + @FieldGetter("channels") + fun getChannels(instance: ServerConnectionListener): List +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ServerStatsCounterProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ServerStatsCounterProxy.kt new file mode 100644 index 000000000..28f64682a --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1ServerStatsCounterProxy.kt @@ -0,0 +1,21 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import com.google.gson.Gson +import com.google.gson.JsonElement +import net.minecraft.stats.ServerStatsCounter +import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter +import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName +import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies +import xyz.jpenilla.reflectionremapper.proxy.annotation.Static + +@Proxies(ServerStatsCounter::class) +@Suppress("ClassName") +interface V26_1ServerStatsCounterProxy { + + @MethodName("toJson") + fun toJson(statsCounter: ServerStatsCounter): JsonElement + + @FieldGetter("GSON") + @Static + fun getGson(): Gson +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1VanillaArgumentProviderImplProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1VanillaArgumentProviderImplProxy.kt new file mode 100644 index 000000000..802b7f9f8 --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1VanillaArgumentProviderImplProxy.kt @@ -0,0 +1,16 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import com.mojang.brigadier.arguments.ArgumentType +import com.mojang.brigadier.exceptions.CommandSyntaxException +import dev.slne.surf.api.core.reflection.Name +import dev.slne.surf.api.core.reflection.SurfProxy +import io.papermc.paper.command.brigadier.argument.VanillaArgumentProviderImpl + +@SurfProxy(VanillaArgumentProviderImpl::class) +@Suppress("ClassName") +interface V26_1VanillaArgumentProviderImplProxy { + + @Name("wrap") + @Throws(CommandSyntaxException::class) + fun wrap(instance: Any, base: Any, converter: Any): ArgumentType<*> +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1VanillaArgumentProviderProxy.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1VanillaArgumentProviderProxy.kt new file mode 100644 index 000000000..2a7ed7d0e --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/reflection/V26_1VanillaArgumentProviderProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.reflection + +import dev.slne.surf.api.core.reflection.Name +import dev.slne.surf.api.core.reflection.Static +import dev.slne.surf.api.core.reflection.SurfProxy + +@SurfProxy(qualifiedName = "io.papermc.paper.command.brigadier.argument.VanillaArgumentProvider") +@Suppress("ClassName") +interface V26_1VanillaArgumentProviderProxy { + + @Static + @Name("provider") + fun provider(): Any +} diff --git a/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/region/V26_1TickThreadGuard.kt b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/region/V26_1TickThreadGuard.kt new file mode 100644 index 000000000..5cf29bbfd --- /dev/null +++ b/surf-api-paper/surf-api-paper-nms/surf-api-paper-nms-v26-1/src/main/kotlin/dev/slne/surf/api/paper/server/nms/v26_1/region/V26_1TickThreadGuard.kt @@ -0,0 +1,65 @@ +package dev.slne.surf.api.paper.server.nms.v26_1.region + +import ca.spottedleaf.moonrise.common.util.TickThread +import dev.slne.surf.api.paper.region.TickThreadGuard +import dev.slne.surf.api.paper.server.nms.v26_1.extensions.toNms +import dev.slne.surf.api.paper.util.chunkX +import dev.slne.surf.api.paper.util.chunkZ +import io.papermc.paper.math.Position +import net.minecraft.core.BlockPos +import net.minecraft.world.phys.AABB +import org.bukkit.World +import org.bukkit.entity.Entity +import org.bukkit.util.BoundingBox + +@Suppress("UnstableApiUsage", "ClassName") +class V26_1TickThreadGuard : TickThreadGuard { + + override fun ensureTickThread(world: World, pos: Position, reason: String) { + TickThread.ensureTickThread(world.toNms(), pos.chunkX, pos.chunkZ, reason) + } + + override fun ensureTickThread( + world: World, + pos: Position, + blockRadius: Int, + reason: String + ) { + TickThread.ensureTickThread( + world.toNms(), + BlockPos(pos.blockX(), pos.blockY(), pos.blockZ()), + blockRadius, + reason + ) + } + + override fun ensureTickThread( + world: World, + chunkX: Int, + chunkZ: Int, + reason: String + ) { + TickThread.ensureTickThread(world.toNms(), chunkX, chunkZ, reason) + } + + override fun ensureTickThread(entity: Entity, reason: String) { + TickThread.ensureTickThread(entity.toNms(), reason) + } + + override fun ensureTickThread(world: World, box: BoundingBox, reason: String) { + TickThread.ensureTickThread( + world.toNms(), + AABB(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ), + reason + ) + } + + override fun ensureTickThread( + world: World, + blockX: Double, + blockZ: Double, + reason: String + ) { + TickThread.ensureTickThread(world.toNms(), blockX, blockZ, reason) + } +} diff --git a/surf-api-paper/surf-api-paper-server/build.gradle.kts b/surf-api-paper/surf-api-paper-server/build.gradle.kts index eb16d18ae..46031b32d 100644 --- a/surf-api-paper/surf-api-paper-server/build.gradle.kts +++ b/surf-api-paper/surf-api-paper-server/build.gradle.kts @@ -6,7 +6,7 @@ plugins { `core-convention` alias(libs.plugins.plugin.yml.paper) - id("io.papermc.paperweight.userdev") apply true +// id("io.papermc.paperweight.userdev") apply true } kotlin { @@ -18,8 +18,13 @@ kotlin { dependencies { api(projects.surfApiPaper.surfApiPaper) api(projects.surfApiCore.surfApiCoreServer) + api(projects.surfApiPaper.surfApiPaperNms.surfApiPaperNmsCommon) + compileOnly(libs.paper.api) - paperweight.paperDevBundle(libs.paper.api.get().version) +// paperweight.paperDevBundle(libs.paper.api.get().version) + + runtimeOnly(projects.surfApiPaper.surfApiPaperNms.surfApiPaperNmsV12111) + runtimeOnly(projects.surfApiPaper.surfApiPaperNms.surfApiPaperNmsV261) compileOnly(libs.placeholder.api) @@ -93,6 +98,7 @@ paper { tasks { shadowJar { + mergeServiceFiles() val relocationPrefix: String by project relocate("me.devnatan.inventoryframework", "$relocationPrefix.devnatan.inventoryframework") } diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/PaperInstance.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/PaperInstance.kt index 8336850df..856b2f02d 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/PaperInstance.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/PaperInstance.kt @@ -2,18 +2,20 @@ package dev.slne.surf.api.paper.server import dev.slne.surf.api.core.server.CoreInstance import dev.slne.surf.api.paper.SurfApiPaper +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsProvider import dev.slne.surf.api.paper.server.impl.SurfApiPaperImpl import dev.slne.surf.api.paper.server.inventory.framework.InventoryLoader import dev.slne.surf.api.paper.server.listener.ListenerManager import dev.slne.surf.api.paper.server.packet.PacketApiLoader -import dev.slne.surf.api.paper.server.reflection.Reflection +import org.bukkit.Bukkit +@OptIn(NmsUseWithCaution::class) object PaperInstance : CoreInstance() { override suspend fun onLoad() { super.onLoad() - initObjects() PacketApiLoader.onLoad() InventoryLoader.load() } @@ -21,6 +23,12 @@ object PaperInstance : CoreInstance() { override suspend fun onEnable() { super.onEnable() + val pluginVersion = plugin.pluginMeta.version + val mcVersion = Bukkit.getMinecraftVersion() + val nmsVersion = NmsProvider.current.version + + plugin.logger.info("\u001B[36m\u001B[1mLoading surf-api v$pluginVersion for minecraft $mcVersion with nms $nmsVersion") + PacketApiLoader.onEnable() InventoryLoader.enable() ListenerManager.registerListeners() @@ -34,8 +42,4 @@ object PaperInstance : CoreInstance() { PacketApiLoader.onDisable() InventoryLoader.disable() } - - private fun initObjects() { - Reflection - } } \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingListener.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingListener.kt index 21d80683b..137947ccc 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingListener.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/GlowingListener.kt @@ -1,32 +1,34 @@ package dev.slne.surf.api.paper.server.impl.glow -import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation -import dev.slne.surf.api.paper.util.chunkX -import dev.slne.surf.api.paper.util.chunkZ +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.GlowingLifecycleHandler +import dev.slne.surf.api.paper.nms.common.NmsProvider import io.papermc.paper.event.packet.PlayerChunkLoadEvent import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.event.player.PlayerQuitEvent +@OptIn(NmsUseWithCaution::class) object GlowingListener : Listener { + private val glowingLifecycleHandler: GlowingLifecycleHandler by lazy { + NmsProvider.current.createGlowingLifecycleHandler() + } + @EventHandler fun onPlayerQuit(event: PlayerQuitEvent) { - SurfGlowingApiImpl.removeAllGlowingOnQuit(event.player) + glowingLifecycleHandler.removeAllGlowingOnQuit(event.player) } @EventHandler fun onPlayerChunkLoad(event: PlayerChunkLoadEvent) { - val playerData = SurfGlowingApiImpl.getBlockPlayerData(event.player) ?: return - val blockDataList = playerData.blocks - if (blockDataList.isEmpty()) return - - val spawnOperation = PacketOperation.start() - for ((loc, block) in blockDataList) { - val chunk = event.chunk - if (loc.chunkX != chunk.x || loc.chunkZ != chunk.z || loc.world != chunk.world) continue - spawnOperation.add(block.spawn()) - } + val chunk = event.chunk + val operation = glowingLifecycleHandler.getBlockGlowSpawnOperationForChunk( + event.player, + chunk.x, + chunk.z, + chunk.world + ) ?: return - spawnOperation.execute(event.player) + operation.execute(event.player) } } \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/block/BlockPlayerData.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/block/BlockPlayerData.kt deleted file mode 100644 index 0af3d594f..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/block/BlockPlayerData.kt +++ /dev/null @@ -1,11 +0,0 @@ -package dev.slne.surf.api.paper.server.impl.glow.block - -import dev.slne.surf.api.core.util.mutableObject2ObjectMapOf -import dev.slne.surf.api.paper.extensions.server -import org.bukkit.Location -import java.util.* - -class BlockPlayerData(val uuid: UUID) { - val blocks = mutableObject2ObjectMapOf() - val player get() = server.getPlayer(uuid) -} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/entity/EntityGlowingData.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/entity/EntityGlowingData.kt deleted file mode 100644 index 05e945d1e..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/glow/entity/EntityGlowingData.kt +++ /dev/null @@ -1,73 +0,0 @@ -package dev.slne.surf.api.paper.server.impl.glow.entity - -import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.nms.bridges.packets.PacketOperation -import dev.slne.surf.api.paper.server.impl.glow.SurfGlowingApiImpl -import dev.slne.surf.api.paper.server.impl.glow.TeamData -import dev.slne.surf.api.paper.server.impl.nms.bridges.SurfPaperNmsGlowingBridgeImpl -import dev.slne.surf.api.paper.server.impl.nms.bridges.packets.PacketOperationImpl -import glm_.and -import glm_.or -import net.minecraft.ChatFormatting - -data class EntityGlowingData( - val playerData: EntityPlayerData, - val entityId: Int, - val teamId: String, - var color: ChatFormatting?, - var otherFlags: Byte, -) { - - @OptIn(NmsUseWithCaution::class) - fun sendTeamColor(): PacketOperation { - val color = color ?: return PacketOperationImpl.empty() - val teamData = TeamData.getByColor(color) - - val operation = PacketOperation.start() - if (teamData.markSeen(playerData.uuid)) { - operation.add(SurfPaperNmsGlowingBridgeImpl.INSTANCE.createTeam(teamData)) - } - operation.add(SurfPaperNmsGlowingBridgeImpl.INSTANCE.addEntityToTeam(teamData, teamId)) - - return operation - } - - @OptIn(NmsUseWithCaution::class) - fun removeFromTeam(): PacketOperation { - val color = color ?: return PacketOperationImpl.empty() - val teamData = TeamData.getByColorOrNull(color) ?: return PacketOperationImpl.empty() - - val operation = PacketOperation.start() - if (teamData.removeSeen(playerData.uuid)) { - operation.add( - SurfPaperNmsGlowingBridgeImpl.INSTANCE.removeEntityFromTeam( - teamData, - teamId - ) - ) - } - - return operation - } - - @OptIn(NmsUseWithCaution::class) - fun sendGlowingFlag(enabled: Boolean, ignorePacket: Boolean = false): PacketOperation { - val newFlags = if (enabled) { - otherFlags or SurfGlowingApiImpl.glowingFlag - } else { - otherFlags and SurfGlowingApiImpl.glowingFlag.inv() - } - - return SurfPaperNmsGlowingBridgeImpl.INSTANCE.setEntityFlags( - entityId, - newFlags, - ignorePacket - ) - } - - fun computeFlags(): Byte { - return (otherFlags and SurfGlowingApiImpl.glowingFlag.inv()).or( - if (color != null) SurfGlowingApiImpl.glowingFlag else 0 - ) - } -} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsStatsBridgeImpl.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsStatsBridgeImpl.kt deleted file mode 100644 index 52579d90a..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/SurfPaperNmsStatsBridgeImpl.kt +++ /dev/null @@ -1,27 +0,0 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges - -import com.google.auto.service.AutoService -import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader -import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsStatsBridge -import dev.slne.surf.api.paper.server.nms.toNms -import dev.slne.surf.api.paper.server.reflection.Reflection -import org.bukkit.entity.Player - -@AutoService(SurfPaperNmsStatsBridge::class) -@NmsUseWithCaution -class SurfPaperNmsStatsBridgeImpl : SurfPaperNmsStatsBridge { - init { - checkInstantiationByServiceLoader() - } - - override fun getPlayerStatsAsJson(player: Player): String { - val gson = Reflection.SERVER_STATS_COUNTER_PROXY.getGson() - val jsonElement = Reflection.SERVER_STATS_COUNTER_PROXY.toJson(player.toNms().stats) - return gson.toJson(jsonElement) - } - - override fun savePlayerStatsToFile(player: Player) { - player.toNms().stats.save() - } -} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/NmsClientboundPacketImpl.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/NmsClientboundPacketImpl.kt deleted file mode 100644 index 6ce087623..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/clientbound/NmsClientboundPacketImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.clientbound - -import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.nms.listener.packets.clientbound.NmsClientboundPacket -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.NmsPacketImpl -import net.minecraft.network.protocol.Packet -import net.minecraft.network.protocol.common.ClientCommonPacketListener - -@NmsUseWithCaution -abstract class NmsClientboundPacketImpl, Listener : ClientCommonPacketListener>( - nmsPacket: Nms, -) : NmsClientboundPacket, NmsPacketImpl(nmsPacket) \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/NmsServerboundPacketImpl.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/NmsServerboundPacketImpl.kt deleted file mode 100644 index 5e9dbea8f..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/listener/packets/serverbound/NmsServerboundPacketImpl.kt +++ /dev/null @@ -1,10 +0,0 @@ -package dev.slne.surf.api.paper.server.impl.nms.listener.packets.serverbound - -import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.NmsPacketImpl -import net.minecraft.network.protocol.Packet -import net.minecraft.network.protocol.common.ServerCommonPacketListener - -@NmsUseWithCaution -abstract class NmsServerboundPacketImpl>(nmsPacket: Nms) : - NmsPacketImpl(nmsPacket) diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/SurfPaperPacketApiImpl.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/SurfPaperPacketApiImpl.kt index 816d34886..7e0891c61 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/SurfPaperPacketApiImpl.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/packet/SurfPaperPacketApiImpl.kt @@ -2,14 +2,19 @@ package dev.slne.surf.api.paper.server.impl.packet import com.google.auto.service.AutoService import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsProvider +import dev.slne.surf.api.paper.nms.common.PacketLoreRegistry import dev.slne.surf.api.paper.packet.SurfPaperPacketApi import dev.slne.surf.api.paper.packet.lore.SurfPaperPacketLoreHandler -import dev.slne.surf.api.paper.server.packet.lore.PacketLoreListener import org.bukkit.NamespacedKey import org.bukkit.plugin.Plugin +@NmsUseWithCaution @AutoService(SurfPaperPacketApi::class) class SurfPaperPacketApiImpl : SurfPaperPacketApi { + private val packetLoreRegistry: PacketLoreRegistry = NmsProvider.current.createPacketLoreRegistry() + init { checkInstantiationByServiceLoader() } @@ -19,21 +24,21 @@ class SurfPaperPacketApiImpl : SurfPaperPacketApi { identifier: NamespacedKey, listener: SurfPaperPacketLoreHandler ) { - PacketLoreListener.register(plugin, identifier, listener) + packetLoreRegistry.register(plugin, identifier, listener) } override fun registerPacketLoreListenerGlobal( plugin: Plugin, listener: SurfPaperPacketLoreHandler ) { - PacketLoreListener.register(plugin, listener) + packetLoreRegistry.register(plugin, listener) } override fun unregisterPacketLoreListener(plugin: Plugin) { - PacketLoreListener.unregister(plugin) + packetLoreRegistry.unregister(plugin) } override fun unregisterPacketLoreListener(identifier: NamespacedKey) { - PacketLoreListener.unregister(identifier) + packetLoreRegistry.unregister(identifier) } } diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/LibLoader.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/LibLoader.kt index 57d4b275d..6b66b3a2e 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/LibLoader.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/LibLoader.kt @@ -3,15 +3,11 @@ package dev.slne.surf.api.paper.server.libs import dev.slne.surf.api.core.util.logger -import dev.slne.surf.api.core.util.setFinalField import dev.slne.surf.api.core.util.toEnumeration -import dev.slne.surf.api.paper.server.libs.reflection.LibReflection -import dev.slne.surf.api.paper.server.nms.commodore -import dev.slne.surf.api.paper.server.nms.craftServer +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsProvider import dev.slne.surf.api.paper.server.plugin -import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader -import org.bukkit.craftbukkit.util.ApiVersion import java.io.IOException import java.io.InputStream import java.net.URL @@ -28,9 +24,11 @@ import kotlin.io.path.outputStream import kotlin.math.max import kotlin.math.min +@OptIn(NmsUseWithCaution::class) class LibLoader(pluginClassLoader: ClassLoader) { private val logger = logger() - private val pluginClassLoader = pluginClassLoader as PaperPluginClassLoader + private val bridge by lazy { NmsProvider.current.getLibLoaderBridge() } + private val pluginClassLoader = pluginClassLoader as URLClassLoader fun loadLibs() { } @@ -93,11 +91,11 @@ class LibLoader(pluginClassLoader: ClassLoader) { } private fun remapClass(jarName: String, clazz: ByteArray, apiVersion: String) = - commodore.convert( + bridge.convertWithCommodore( clazz, jarName, - ApiVersion.getOrCreateVersion(apiVersion), - craftServer.activeCompatibilities + apiVersion, + bridge.getActiveCompatibilities() ) private fun loadTempFileFromResource(fileName: String): Path? { @@ -136,18 +134,14 @@ class LibLoader(pluginClassLoader: ClassLoader) { @Suppress("DEPRECATION") private fun getOrCreateSurfLibClassLoader(): SurfLibJoinClassLoader { - val libraryLoader = - LibReflection.PAPER_PLUGIN_CLASS_LOADER_PROXY.getLibraryLoader(pluginClassLoader) + val libraryLoader = bridge.getLibraryLoader(pluginClassLoader) if (libraryLoader is SurfLibJoinClassLoader) { return libraryLoader } val surfLoader = SurfLibJoinClassLoader(libraryLoader) - PaperPluginClassLoader::class.java.getDeclaredField("libraryLoader").apply { - setAccessible(true) - setFinalField(this, pluginClassLoader, surfLoader) - } + bridge.overwriteLibraryLoader(pluginClassLoader, surfLoader) return surfLoader } @@ -157,7 +151,8 @@ class LibLoader(pluginClassLoader: ClassLoader) { private inner class SurfLibJoinClassLoader( parent: URLClassLoader, vararg delegateClassLoaders: URLClassLoader, - ) : URLClassLoader(parent.urLs, parent), ConfiguredPluginClassLoader by pluginClassLoader { + ) : URLClassLoader(parent.urLs, parent), + ConfiguredPluginClassLoader by pluginClassLoader as ConfiguredPluginClassLoader { private val delegateClassLoaders = delegateClassLoaders.toMutableList() override fun findClass(name: String): Class<*>? { diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/reflection/LibReflection.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/reflection/LibReflection.kt deleted file mode 100644 index f9bc6298d..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/reflection/LibReflection.kt +++ /dev/null @@ -1,9 +0,0 @@ -package dev.slne.surf.api.paper.server.libs.reflection - -import dev.slne.surf.api.core.reflection.SurfReflection -import dev.slne.surf.api.core.reflection.createProxy - -object LibReflection { - @JvmField - val PAPER_PLUGIN_CLASS_LOADER_PROXY = SurfReflection.createProxy() -} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/reflection/PaperPluginClassLoaderProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/reflection/PaperPluginClassLoaderProxy.kt deleted file mode 100644 index 6a97c8c63..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/libs/reflection/PaperPluginClassLoaderProxy.kt +++ /dev/null @@ -1,16 +0,0 @@ -package dev.slne.surf.api.paper.server.libs.reflection - -import dev.slne.surf.api.core.reflection.Field -import dev.slne.surf.api.core.reflection.Field.Type -import dev.slne.surf.api.core.reflection.SurfProxy -import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader -import java.net.URLClassLoader - -@SurfProxy(PaperPluginClassLoader::class) -interface PaperPluginClassLoaderProxy { - @Field("libraryLoader", Type.SETTER, overrideFinal = true) - fun setLibraryLoader(instance: PaperPluginClassLoader, libraryLoader: URLClassLoader) - - @Field("libraryLoader", Type.GETTER) - fun getLibraryLoader(instance: PaperPluginClassLoader): URLClassLoader -} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/PacketApiLoader.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/PacketApiLoader.kt index 76266c379..85569bfde 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/PacketApiLoader.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/PacketApiLoader.kt @@ -5,16 +5,19 @@ import dev.slne.surf.api.core.extensions.packetEvents import dev.slne.surf.api.paper.event.register import dev.slne.surf.api.paper.event.unregister import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.AbstractChannelInjector +import dev.slne.surf.api.paper.nms.common.NmsProvider import dev.slne.surf.api.paper.packet.listener.SurfPaperPacketListenerApi -import dev.slne.surf.api.paper.server.impl.glow.GlowingPacketListener -import dev.slne.surf.api.paper.server.packet.listener.PlayerChannelInjector -import dev.slne.surf.api.paper.server.packet.lore.PacketLoreListener +import dev.slne.surf.api.paper.packet.listener.listener.PacketListener import dev.slne.surf.api.paper.server.packet.lore.PluginDisablePacketLoreListener import dev.slne.surf.api.paper.server.plugin import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder +@OptIn(NmsUseWithCaution::class) object PacketApiLoader { + private var versionPacketListeners: List = emptyList() + fun onLoad() { setupPacketEvents() } @@ -22,19 +25,33 @@ object PacketApiLoader { @OptIn(NmsUseWithCaution::class) fun onEnable() { packetEvents.init() - SurfPaperPacketListenerApi.registerListeners(PacketLoreListener) - SurfPaperPacketListenerApi.registerListeners(GlowingPacketListener) - PlayerChannelInjector.register() + // Register version-specific packet listeners from NmsProvider + val provider = NmsProvider.current + provider.initialize() + + versionPacketListeners = provider.createPacketListeners() + for (listener in versionPacketListeners) { + SurfPaperPacketListenerApi.registerListeners(listener) + } + + AbstractChannelInjector.instance.register() PluginDisablePacketLoreListener.register() } @OptIn(NmsUseWithCaution::class) fun onDisable() { + val provider = NmsProvider.current + packetEvents.terminate() - SurfPaperPacketListenerApi.unregisterListeners(PacketLoreListener) + for (listener in versionPacketListeners) { + SurfPaperPacketListenerApi.unregisterListeners(listener) + } + versionPacketListeners = emptyList() + PluginDisablePacketLoreListener.unregister() - PlayerChannelInjector.unregister() + AbstractChannelInjector.instance.unregister() + provider.shutdown() } private fun setupPacketEvents() { diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/listener/PlayerChannelInjector.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/listener/PlayerChannelInjector.kt deleted file mode 100644 index 20eb74efe..000000000 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/listener/PlayerChannelInjector.kt +++ /dev/null @@ -1,246 +0,0 @@ -package dev.slne.surf.api.paper.server.packet.listener - -import dev.slne.surf.api.core.messages.Colors -import dev.slne.surf.api.core.messages.CommonComponents -import dev.slne.surf.api.core.messages.adventure.text -import dev.slne.surf.api.core.reflection.Field -import dev.slne.surf.api.core.reflection.SurfProxy -import dev.slne.surf.api.core.reflection.SurfReflection -import dev.slne.surf.api.core.reflection.createProxy -import dev.slne.surf.api.core.util.logger -import dev.slne.surf.api.paper.nms.NmsUseWithCaution -import dev.slne.surf.api.paper.nms.SurfPaperNmsBridge -import dev.slne.surf.api.paper.packet.listener.SurfPaperPacketListenerApi -import dev.slne.surf.api.paper.server.impl.nms.SurfPaperNmsBridgeImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.NmsPacketImpl -import dev.slne.surf.api.paper.server.impl.nms.listener.packets.PacketRegistry -import dev.slne.surf.api.paper.server.impl.packet.listener.SurfPaperPacketListenerApiImpl -import dev.slne.surf.api.paper.server.nms.toNms -import dev.slne.surf.api.paper.server.plugin -import io.netty.channel.Channel -import io.netty.channel.ChannelDuplexHandler -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelPromise -import io.netty.util.AttributeKey -import io.papermc.paper.connection.PaperPlayerLoginConnection -import io.papermc.paper.connection.ReadablePlayerCookieConnectionImpl -import io.papermc.paper.event.connection.PlayerConnectionValidateLoginEvent -import io.papermc.paper.network.ChannelInitializeListenerHolder -import net.kyori.adventure.key.Key -import net.minecraft.network.Connection -import net.minecraft.network.HandlerNames -import net.minecraft.network.protocol.Packet -import net.minecraft.server.level.ServerPlayer -import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority -import org.bukkit.event.Listener -import org.bukkit.event.player.PlayerJoinEvent -import dev.slne.surf.api.paper.event.register as registerListener -import dev.slne.surf.api.paper.event.unregister as unregisterListener - -@Suppress("UnstableApiUsage") -object PlayerChannelInjector : Listener { - private val log = logger() - - private val CHANNEL_KEY = Key.key("surf-api", "packet-listener") - private const val CHANNEL_NAME = "surf_api_packet_listener" - - private val packetHandlerKey = - AttributeKey.newInstance("surf_api_packet_handler") - - fun register() { - ChannelInitializeListenerHolder.addListener(CHANNEL_KEY) { this.getOrInjectPacketHandler(it) } - registerListener(plugin) - } - - fun unregister() { - unregisterListener() - ChannelInitializeListenerHolder.removeListener(CHANNEL_KEY) - } - - private fun getOrInjectPacketHandler(channel: Channel): PacketHandler { - val handler = PacketHandler() - val attr = channel.attr(packetHandlerKey) - - if (!attr.compareAndSet(null, handler)) { - return attr.get() - } - - val command = Runnable { - if (channel.pipeline().get(CHANNEL_NAME) == null) { - channel.pipeline().addBefore(HandlerNames.PACKET_HANDLER, CHANNEL_NAME, handler) - } - } - - if (channel.eventLoop().inEventLoop()) { - command.run() - } else { - channel.eventLoop().execute(command) - } - - return handler - } - - @EventHandler - fun onPlayerLogin(event: PlayerConnectionValidateLoginEvent) { - val paperConnection = event.connection - if (paperConnection is PaperPlayerLoginConnection) { - val profile = paperConnection.authenticatedProfile - - if (profile == null) { - event.kickMessage( - CommonComponents.renderDisconnectMessage( - "FAILED TO INJECT PACKET LISTENER", - { - text( - "Dein Profil ist nicht authentifiziert, daher können wir den Paket-Listener nicht einbinden. Dies ist wahrscheinlich ein Problem mit deiner Verbindung zu den Authentifizierungsservern von Mojang.", - Colors.ERROR - ) - }, - issue = true - ) - ) - - log.atWarning() - .log("Failed to inject packet listener for player (${paperConnection.unsafeProfile}) with unauthenticated profile: ${paperConnection.address} - ${paperConnection.clientAddress}") - return - } - - val connection = - ReadablePlayerCookieConnectionImplProxy.instance.getConnection(paperConnection) - val channel = connection.channel - getOrInjectPacketHandler(channel).connection = connection - } - } - - @EventHandler(priority = EventPriority.LOWEST) - fun onPlayerJoin(event: PlayerJoinEvent) { - val player = event.player.toNms() - val connection = player.connection.connection - val channel = connection.channel - - getOrInjectPacketHandler(channel).connection = connection - } - - @OptIn(NmsUseWithCaution::class) - private class PacketHandler : ChannelDuplexHandler() { - private val bridge = SurfPaperNmsBridge.INSTANCE as SurfPaperNmsBridgeImpl - private val packetListenerApi = - SurfPaperPacketListenerApi.INSTANCE as SurfPaperPacketListenerApiImpl - - @Volatile - var connection: Connection? = null - - @OptIn(NmsUseWithCaution::class) - override fun write( - ctx: ChannelHandlerContext, - msg: Any, - promise: ChannelPromise, - ) { // server -> client - handlePacket( - originalMsg = msg, - passthrough = { super.write(ctx, it, promise) }, - nmsHandler = packetListenerApi::handleClientboundPacket, - bridgeHandler = ::handleClientboundPacketFromBridge - ) - } - - @OptIn(NmsUseWithCaution::class) - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { // client -> server - handlePacket( - originalMsg = msg, - passthrough = { super.channelRead(ctx, it) }, - nmsHandler = packetListenerApi::handleServerboundPacket, - bridgeHandler = ::handleServerboundPacketFromBridge - ) - } - - private inline fun handlePacket( - originalMsg: Any, - passthrough: (Any) -> Unit, - nmsHandler: (Packet<*>, ServerPlayer?) -> Packet<*>?, - bridgeHandler: (ServerPlayer?, Packet<*>) -> Packet<*>? - ) { - var msg = originalMsg - if (msg !is Packet<*>) { - passthrough(msg) - return - } - - val connection = connection - if (connection == null) { - passthrough(msg) - return - } - - val player = connection.player as ServerPlayer? - - try { - msg = nmsHandler(msg, player) ?: return - msg = bridgeHandler(player, msg) ?: return - passthrough(msg) - } catch (outOfMemoryError: OutOfMemoryError) { - throw outOfMemoryError - } catch (t: Throwable) { - log.atSevere().withCause(t).log("Failed to handle packet") - passthrough(msg) - } - } - - @OptIn(NmsUseWithCaution::class) - fun handleServerboundPacketFromBridge( - serverPlayer: ServerPlayer?, - packet: Packet<*>, - ): Packet<*>? { - val apiPacket = PacketRegistry.createServerboundPacketOrNull(packet) - - if (apiPacket != null) { // we have an api packet wrapper for this packet - val resultApi = this.bridge.handleServerboundPacket( - apiPacket, - serverPlayer?.bukkitEntity - ) - - if (resultApi != null) { // we may have a modified packet - return NmsPacketImpl.getFromApi(resultApi).nmsPacket - } - } else { - return packet // no api packet wrapper, so we just return the original packet - } - - return null // the packet was canceled - } - - fun handleClientboundPacketFromBridge( - serverPlayer: ServerPlayer?, - packet: Packet<*>, - ): Packet<*>? { - val apiPacket = PacketRegistry.createClientboundPacketOrNull(packet) - - if (apiPacket != null) { - val resultApi = this.bridge.handleClientboundPacket( - apiPacket, - serverPlayer?.bukkitEntity - ) - - if (resultApi != null) { - return NmsPacketImpl.getFromApi(resultApi).nmsPacket - } - } else { - return packet - } - - return null - } - } - - @SurfProxy(ReadablePlayerCookieConnectionImpl::class) - interface ReadablePlayerCookieConnectionImplProxy { - - @Field("connection", Field.Type.GETTER) - fun getConnection(instance: ReadablePlayerCookieConnectionImpl): Connection - - companion object { - val instance = SurfReflection.createProxy() - } - } -} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PluginDisablePacketLoreListener.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PluginDisablePacketLoreListener.kt index 907051f7c..445cc7e02 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PluginDisablePacketLoreListener.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/packet/lore/PluginDisablePacketLoreListener.kt @@ -1,13 +1,17 @@ package dev.slne.surf.api.paper.server.packet.lore +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsProvider import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.event.server.PluginDisableEvent +@NmsUseWithCaution object PluginDisablePacketLoreListener : Listener { + private val packetLoreRegistry by lazy { NmsProvider.current.createPacketLoreRegistry() } @EventHandler fun onPluginDisable(event: PluginDisableEvent) { - PacketLoreListener.unregister(event.plugin) + packetLoreRegistry.unregister(event.plugin) } } \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfGlowingApiProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfGlowingApiProxy.kt new file mode 100644 index 000000000..3f28ad9bc --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfGlowingApiProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.glow.SurfGlowingApi +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfGlowingApi::class) +class SurfGlowingApiProxy : + SurfGlowingApi by NmsProvider.current.createGlowingApi() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsBlockPacketsProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsBlockPacketsProxy.kt new file mode 100644 index 000000000..7e45205cc --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsBlockPacketsProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.block.SurfPaperNmsBlockPackets +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsBlockPackets::class) +class SurfPaperNmsBlockPacketsProxy : + SurfPaperNmsBlockPackets by NmsProvider.current.createBlockPackets() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsBridgeProxy.kt new file mode 100644 index 000000000..4faebd1de --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsBridgeProxy.kt @@ -0,0 +1,16 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.SurfPaperNmsBridge +import dev.slne.surf.api.paper.nms.common.InternalNmsBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsBridge::class) +class SurfPaperNmsBridgeProxy : InternalNmsBridge by NmsProvider.current.createNmsBridge() { + init { + checkInstantiationByServiceLoader() + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsCommandArgumentTypesBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsCommandArgumentTypesBridgeProxy.kt new file mode 100644 index 000000000..82f95def6 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsCommandArgumentTypesBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommandArgumentTypesBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsCommandArgumentTypesBridge::class) +class SurfPaperNmsCommandArgumentTypesBridgeProxy : + SurfPaperNmsCommandArgumentTypesBridge by NmsProvider.current.createCommandArgumentTypesBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsCommonBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsCommonBridgeProxy.kt new file mode 100644 index 000000000..5a2eb1e5a --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsCommonBridgeProxy.kt @@ -0,0 +1,21 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsCommonBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +/** + * Version-aware proxy for [SurfPaperNmsCommonBridge]. + * + * Loaded via ServiceLoader, delegates to the NMS provider for the current server version. + */ +@NmsUseWithCaution +@AutoService(SurfPaperNmsCommonBridge::class) +class SurfPaperNmsCommonBridgeProxy : + SurfPaperNmsCommonBridge by NmsProvider.current.createCommonBridge() { + init { + checkInstantiationByServiceLoader() + } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsEntityBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsEntityBridgeProxy.kt new file mode 100644 index 000000000..9b9d0d6a2 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsEntityBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsEntityBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsEntityBridge::class) +class SurfPaperNmsEntityBridgeProxy : + SurfPaperNmsEntityBridge by NmsProvider.current.createEntityBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsGlowingBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsGlowingBridgeProxy.kt new file mode 100644 index 000000000..1ae176f93 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsGlowingBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsGlowingBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsGlowingBridge::class) +class SurfPaperNmsGlowingBridgeProxy : + SurfPaperNmsGlowingBridge by NmsProvider.current.createGlowingBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsItemBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsItemBridgeProxy.kt new file mode 100644 index 000000000..efb5b2078 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsItemBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsItemBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsItemBridge::class) +class SurfPaperNmsItemBridgeProxy : + SurfPaperNmsItemBridge by NmsProvider.current.createItemBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsLootTableBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsLootTableBridgeProxy.kt new file mode 100644 index 000000000..961457bc0 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsLootTableBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsLootTableBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsLootTableBridge::class) +class SurfPaperNmsLootTableBridgeProxy : + SurfPaperNmsLootTableBridge by NmsProvider.current.createLootTableBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsNbtBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsNbtBridgeProxy.kt new file mode 100644 index 000000000..bd5023230 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsNbtBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsNbtBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsNbtBridge::class) +class SurfPaperNmsNbtBridgeProxy : + SurfPaperNmsNbtBridge by NmsProvider.current.createNbtBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/SurfPaperNmsPacketBridgesImpl.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPacketBridgesProxy.kt similarity index 50% rename from surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/SurfPaperNmsPacketBridgesImpl.kt rename to surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPacketBridgesProxy.kt index e7be05399..0d6c01e78 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/impl/nms/bridges/packets/SurfPaperNmsPacketBridgesImpl.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPacketBridgesProxy.kt @@ -1,18 +1,14 @@ -package dev.slne.surf.api.paper.server.impl.nms.bridges.packets +package dev.slne.surf.api.paper.server.proxy import com.google.auto.service.AutoService import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader import dev.slne.surf.api.paper.nms.NmsUseWithCaution import dev.slne.surf.api.paper.nms.bridges.packets.SurfPaperNmsPacketBridges +import dev.slne.surf.api.paper.nms.common.NmsProvider @NmsUseWithCaution @AutoService(SurfPaperNmsPacketBridges::class) -class SurfPaperNmsPacketBridgesImpl : SurfPaperNmsPacketBridges { - init { - checkInstantiationByServiceLoader() - } - - override fun createEmptyPacketOperation(): PacketOperationImpl { - return PacketOperationImpl.empty() - } +class SurfPaperNmsPacketBridgesProxy : + SurfPaperNmsPacketBridges by NmsProvider.current.createPacketBridges() { + init { checkInstantiationByServiceLoader() } } diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerChatPacketsProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerChatPacketsProxy.kt new file mode 100644 index 000000000..ad892c22c --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerChatPacketsProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerChatPackets +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsPlayerChatPackets::class) +class SurfPaperNmsPlayerChatPacketsProxy : + SurfPaperNmsPlayerChatPackets by NmsProvider.current.createPlayerChatPackets() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerPacketsProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerPacketsProxy.kt new file mode 100644 index 000000000..317a3735c --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerPacketsProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerPackets +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsPlayerPackets::class) +class SurfPaperNmsPlayerPacketsProxy : + SurfPaperNmsPlayerPackets by NmsProvider.current.createPlayerPackets() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerToastPacketsProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerToastPacketsProxy.kt new file mode 100644 index 000000000..3a7bd170f --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsPlayerToastPacketsProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.player.SurfPaperNmsPlayerToastPackets +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsPlayerToastPackets::class) +class SurfPaperNmsPlayerToastPacketsProxy : + SurfPaperNmsPlayerToastPackets by NmsProvider.current.createPlayerToastPackets() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsSpawnPacketsProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsSpawnPacketsProxy.kt new file mode 100644 index 000000000..6dc97319b --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsSpawnPacketsProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.packets.entity.SurfPaperNmsSpawnPackets +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsSpawnPackets::class) +class SurfPaperNmsSpawnPacketsProxy : + SurfPaperNmsSpawnPackets by NmsProvider.current.createSpawnPackets() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsStatsBridgeProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsStatsBridgeProxy.kt new file mode 100644 index 000000000..102da7226 --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperNmsStatsBridgeProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.bridges.SurfPaperNmsStatsBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider + +@NmsUseWithCaution +@AutoService(SurfPaperNmsStatsBridge::class) +class SurfPaperNmsStatsBridgeProxy : + SurfPaperNmsStatsBridge by NmsProvider.current.createStatsBridge() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperPacketListenerApiProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperPacketListenerApiProxy.kt new file mode 100644 index 000000000..30d7b77ca --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/SurfPaperPacketListenerApiProxy.kt @@ -0,0 +1,16 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.InternalPacketListenerApiBridge +import dev.slne.surf.api.paper.nms.common.NmsProvider +import dev.slne.surf.api.paper.packet.listener.SurfPaperPacketListenerApi + +@NmsUseWithCaution +@AutoService(SurfPaperPacketListenerApi::class) +class SurfPaperPacketListenerApiProxy : InternalPacketListenerApiBridge by NmsProvider.current.createPacketListenerApi() { + init { + checkInstantiationByServiceLoader() + } +} \ No newline at end of file diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/TickThreadGuardProxy.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/TickThreadGuardProxy.kt new file mode 100644 index 000000000..60bfa9dfd --- /dev/null +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/proxy/TickThreadGuardProxy.kt @@ -0,0 +1,14 @@ +package dev.slne.surf.api.paper.server.proxy + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.util.checkInstantiationByServiceLoader +import dev.slne.surf.api.paper.nms.NmsUseWithCaution +import dev.slne.surf.api.paper.nms.common.NmsProvider +import dev.slne.surf.api.paper.region.TickThreadGuard + +@NmsUseWithCaution +@AutoService(TickThreadGuard::class) +class TickThreadGuardProxy : + TickThreadGuard by NmsProvider.current.createTickThreadGuard() { + init { checkInstantiationByServiceLoader() } +} diff --git a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/Reflection.kt b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/Reflection.kt index de4f9e054..7ff685aef 100644 --- a/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/Reflection.kt +++ b/surf-api-paper/surf-api-paper-server/src/main/kotlin/dev/slne/surf/api/paper/server/reflection/Reflection.kt @@ -2,33 +2,7 @@ package dev.slne.surf.api.paper.server.reflection import dev.slne.surf.api.core.reflection.SurfReflection import dev.slne.surf.api.core.reflection.createProxy -import dev.slne.surf.api.paper.util.reflectionProxy -import xyz.jpenilla.reflectionremapper.ReflectionRemapper -import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory object Reflection { - val SERVER_STATS_COUNTER_PROXY: ServerStatsCounterProxy - val ENTITY_PROXY: EntityProxy - val SERVER_CONNECTION_LISTENER_PROXY: ServerConnectionListenerProxy - val JAVA_PLUGIN_PROXY: JavaPluginProxy - val VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY: VanillaArgumentProviderImplProxy - val VANILLA_ARGUMENT_PROVIDER_PROXY: VanillaArgumentProviderProxy - - init { - val remapper = ReflectionRemapper.forReobfMappingsInPaperJar() - val proxyFactory = - ReflectionProxyFactory.create(remapper, Reflection::class.java.classLoader) - - SERVER_STATS_COUNTER_PROXY = proxyFactory.reflectionProxy() - ENTITY_PROXY = proxyFactory.reflectionProxy() - SERVER_CONNECTION_LISTENER_PROXY = - proxyFactory.reflectionProxy() - JAVA_PLUGIN_PROXY = SurfReflection.createProxy() - VANILLA_ARGUMENT_PROVIDER_IMPL_PROXY = - SurfReflection.createProxy() - VANILLA_ARGUMENT_PROVIDER_PROXY = SurfReflection.createProxy() - - // gc the remapper - System.gc() - } + val JAVA_PLUGIN_PROXY: JavaPluginProxy = SurfReflection.createProxy() } diff --git a/surf-api-paper/surf-api-paper/api/surf-api-paper.api b/surf-api-paper/surf-api-paper/api/surf-api-paper.api index 20775881a..d9176dcf1 100644 --- a/surf-api-paper/surf-api-paper/api/surf-api-paper.api +++ b/surf-api-paper/surf-api-paper/api/surf-api-paper.api @@ -2286,6 +2286,10 @@ public final class dev/slne/surf/api/paper/util/UtilBukkit { public static final fun getChunkZ (Lio/papermc/paper/math/Position;)I public static final fun getChunkZ (Lorg/bukkit/Location;)I public static final fun getHighestBlockYAtBlockCoordinates (Lorg/bukkit/ChunkSnapshot;II)I + public static final fun getLuckPermsUser (Lorg/bukkit/OfflinePlayer;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getLuckPermsUser (Lorg/bukkit/entity/Player;)Lnet/luckperms/api/model/user/User; + public static final fun getLuckPermsUserOrNull (Lorg/bukkit/entity/Player;)Lnet/luckperms/api/model/user/User; + public static final fun getPrefixedName (Lorg/bukkit/entity/Player;)Lnet/kyori/adventure/text/Component; public static final fun getXFromChunkKey (J)I public static final fun getZFromChunkKey (J)I public static final fun isChunkVisible (Lorg/bukkit/entity/Player;Lorg/bukkit/Location;)Z diff --git a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/util/bukkit-util.kt b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/util/bukkit-util.kt index a1cc40154..a1d738cc8 100644 --- a/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/util/bukkit-util.kt +++ b/surf-api-paper/surf-api-paper/src/main/kotlin/dev/slne/surf/api/paper/util/bukkit-util.kt @@ -6,6 +6,9 @@ package dev.slne.surf.api.paper.util import com.github.shynixn.mccoroutine.folia.SuspendingPlugin import com.github.shynixn.mccoroutine.folia.entityDispatcher import com.github.shynixn.mccoroutine.folia.regionDispatcher +import dev.slne.surf.api.core.luckperms.LuckPermsAccess +import dev.slne.surf.api.core.luckperms.prefix +import dev.slne.surf.api.core.minimessage.miniMessage import dev.slne.surf.api.core.util.getCallerClass import dev.slne.surf.api.core.util.mutableObjectListOf import dev.slne.surf.api.paper.SurfApiPaper @@ -263,6 +266,20 @@ suspend fun World.getBlockAtAsync(pos: BlockPosition): Block { } } + +fun Player.getLuckPermsUser() = LuckPermsAccess.getUser(this.uniqueId) + ?: error("LuckPerms user not found for online player ${this.name}") + +fun Player.getLuckPermsUserOrNull() = LuckPermsAccess.getUser(this.uniqueId) + +suspend fun OfflinePlayer.getLuckPermsUser() = withContext(Dispatchers.IO) { + LuckPermsAccess.getUser(this@getLuckPermsUser.uniqueId) + ?: LuckPermsAccess.loadUser(this@getLuckPermsUser.uniqueId) +} + +fun Player.getPrefixedName() = + miniMessage.deserialize("${this.getLuckPermsUserOrNull()?.prefix ?: ""}${this.name}") + /** * Constructs a human-readable string representing the location, including coordinates and optionally * rotation data. diff --git a/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderConfig.kt b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderConfig.kt new file mode 100644 index 000000000..3e05f21b2 --- /dev/null +++ b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderConfig.kt @@ -0,0 +1,12 @@ +package dev.slne.surf.api.shared.internal.nms + +import kotlinx.serialization.json.Json + +object NmsProviderConfig { + const val NMS_PROVIDERS_DIRECTORY = "META-INF/surf-api/nms-providers" + val json = Json { + prettyPrint = true + ignoreUnknownKeys = true + prettyPrintIndent = " " + } +} \ No newline at end of file diff --git a/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderMarker.kt b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderMarker.kt new file mode 100644 index 000000000..5a73dc19d --- /dev/null +++ b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderMarker.kt @@ -0,0 +1,5 @@ +package dev.slne.surf.api.shared.internal.nms + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CLASS) +annotation class NmsProviderMarker(val version: NmsVersion) diff --git a/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderMeta.kt b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderMeta.kt new file mode 100644 index 000000000..4d07c513f --- /dev/null +++ b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsProviderMeta.kt @@ -0,0 +1,9 @@ +package dev.slne.surf.api.shared.internal.nms + +import kotlinx.serialization.Serializable + +@Serializable +data class NmsProviderMeta( + val version: NmsVersion, + val implementation: String +) \ No newline at end of file diff --git a/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsVersion.kt b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsVersion.kt new file mode 100644 index 000000000..7c6f0a6db --- /dev/null +++ b/surf-api-shared/surf-api-shared-internal/src/main/kotlin/dev/slne/surf/api/shared/internal/nms/NmsVersion.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.api.shared.internal.nms + +/** + * Represents the supported Minecraft NMS versions. + * + * @property versionPrefix The version prefix used to match `Bukkit.getMinecraftVersion()`. + */ +enum class NmsVersion(val versionPrefix: String) { + V1_21_11("1.21.11"), + V26_1("26.1"); +} \ No newline at end of file diff --git a/surf-api-velocity/surf-api-velocity/api/surf-api-velocity.api b/surf-api-velocity/surf-api-velocity/api/surf-api-velocity.api index 31c58e6c9..d6c54c593 100644 --- a/surf-api-velocity/surf-api-velocity/api/surf-api-velocity.api +++ b/surf-api-velocity/surf-api-velocity/api/surf-api-velocity.api @@ -160,3 +160,9 @@ public final class dev/slne/surf/api/velocity/command/executors/SuspendCommandEx public static final fun sendSyntaxMessageOrRethrow (Lcom/velocitypowered/api/command/CommandSource;Ljava/lang/String;Ljava/lang/Throwable;)V } +public final class dev/slne/surf/api/velocity/util/Velocity_utilKt { + public static final fun getLuckPermsUser (Lcom/velocitypowered/api/proxy/Player;)Lnet/luckperms/api/model/user/User; + public static final fun getLuckPermsUserOrNull (Lcom/velocitypowered/api/proxy/Player;)Lnet/luckperms/api/model/user/User; + public static final fun getPrefixedName (Lcom/velocitypowered/api/proxy/Player;)Lnet/kyori/adventure/text/Component; +} + diff --git a/surf-api-velocity/surf-api-velocity/src/main/kotlin/dev/slne/surf/api/velocity/util/velocity-util.kt b/surf-api-velocity/surf-api-velocity/src/main/kotlin/dev/slne/surf/api/velocity/util/velocity-util.kt index 160927c42..cd5a20966 100644 --- a/surf-api-velocity/surf-api-velocity/src/main/kotlin/dev/slne/surf/api/velocity/util/velocity-util.kt +++ b/surf-api-velocity/surf-api-velocity/src/main/kotlin/dev/slne/surf/api/velocity/util/velocity-util.kt @@ -1,2 +1,14 @@ package dev.slne.surf.api.velocity.util +import com.velocitypowered.api.proxy.Player +import dev.slne.surf.api.core.luckperms.LuckPermsAccess +import dev.slne.surf.api.core.luckperms.prefix +import dev.slne.surf.api.core.minimessage.miniMessage + +fun Player.getLuckPermsUser() = LuckPermsAccess.getUser(this.uniqueId) + ?: error("LuckPerms user not found for online player ${this.username}") + +fun Player.getPrefixedName() = + miniMessage.deserialize("${this.getLuckPermsUserOrNull()?.prefix ?: ""}${this.username}") + +fun Player.getLuckPermsUserOrNull() = LuckPermsAccess.getUser(this.uniqueId) \ No newline at end of file