From 22e46cdeb363f85bb02620f41b0a0f733ca21756 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Tue, 24 Mar 2026 17:04:19 -0400 Subject: [PATCH 01/18] Initial update to Spigot 26.1 - Use Java 25 for CIs - Dropped now-unneeded remapping/reobfuscation configurations and pre-compiled script plugin - Copied all previously-shared classes into Spigot-specific packaging - This will potentially result in duplicated code maintenance, but makes it much easier to catch new server implementation differences at compile time. - Repackage Spigot internals --- .github/workflows/ci.yml | 4 +- buildSrc/build.gradle.kts | 1 - .../jikoo/openinv/BuildToolsValueSource.kt | 27 +- .../openinv/SpigotDependencyExtension.kt | 2 +- .../com/github/jikoo/openinv/SpigotReobf.kt | 56 --- .../github/jikoo/openinv/SpigotReobfTask.kt | 85 ----- .../com/github/jikoo/openinv/SpigotSetup.kt | 13 +- gradle/libs.versions.toml | 2 - internal/common/build.gradle.kts | 25 -- internal/spigot/build.gradle.kts | 23 +- .../internal/spigot26_1/InternalAccessor.java | 80 +++++ .../container/AnySilentContainer.java | 8 +- .../container/BaseOpenInventory.java | 335 ++++++++++++++++++ .../spigot26_1/container/OpenEnderChest.java | 201 +++++++++++ .../spigot26_1/container/OpenInventory.java | 49 +++ .../container/bukkit/OpenDummyInventory.java | 168 +++++++++ .../bukkit/OpenDummyPlayerInventory.java | 137 +++++++ .../container/bukkit/OpenPlayerInventory.java | 8 +- .../bukkit/OpenPlayerInventorySelf.java | 26 ++ .../container/menu/OpenChestMenu.java | 288 +++++++++++++++ .../container/menu/OpenEnderChestMenu.java | 54 +++ .../container/menu/OpenInventoryMenu.java | 265 ++++++++++++++ .../container/menu/OpenSyncMenu.java | 237 +++++++++++++ .../spigot26_1/container/slot/Content.java | 69 ++++ .../container/slot/ContentCrafting.java | 132 +++++++ .../container/slot/ContentCraftingResult.java | 48 +++ .../container/slot/ContentCursor.java | 118 ++++++ .../container/slot/ContentDrop.java | 89 +++++ .../container/slot/ContentEquipment.java | 8 +- .../container/slot/ContentList.java | 58 +++ .../container/slot/ContentOffHand.java | 4 +- .../container/slot/ContentViewOnly.java | 56 +++ .../container/slot/SlotPlaceholder.java | 20 ++ .../container/slot/SlotViewOnly.java | 151 ++++++++ .../slot/placeholder/PlaceholderLoader.java | 40 +++ .../placeholder/PlaceholderLoaderBase.java | 180 ++++++++++ .../slot/placeholder/Placeholders.java | 37 ++ .../spigot26_1}/player/OpenPlayer.java | 6 +- .../spigot26_1}/player/PlayerManager.java | 14 +- jitpack.yml | 4 +- plugin/build.gradle.kts | 6 +- .../lishid/openinv/util/InternalAccessor.java | 23 +- 42 files changed, 2912 insertions(+), 245 deletions(-) delete mode 100644 buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotReobf.kt delete mode 100644 buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotReobfTask.kt create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java rename internal/spigot/src/main/java/com/{lishid/openinv/internal/reobf => github/jikoo/openinv/internal/spigot26_1}/container/AnySilentContainer.java (96%) create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenEnderChest.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyInventory.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyPlayerInventory.java rename internal/spigot/src/main/java/com/{lishid/openinv/internal/reobf => github/jikoo/openinv/internal/spigot26_1}/container/bukkit/OpenPlayerInventory.java (95%) create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenChestMenu.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenEnderChestMenu.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenSyncMenu.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/Content.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCrafting.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCraftingResult.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCursor.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentDrop.java rename internal/spigot/src/main/java/com/{lishid/openinv/internal/reobf => github/jikoo/openinv/internal/spigot26_1}/container/slot/ContentEquipment.java (91%) create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentList.java rename internal/spigot/src/main/java/com/{lishid/openinv/internal/reobf => github/jikoo/openinv/internal/spigot26_1}/container/slot/ContentOffHand.java (91%) create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentViewOnly.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotPlaceholder.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotViewOnly.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoader.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoaderBase.java create mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/Placeholders.java rename internal/spigot/src/main/java/com/{lishid/openinv/internal/reobf => github/jikoo/openinv/internal/spigot26_1}/player/OpenPlayer.java (97%) rename internal/spigot/src/main/java/com/{lishid/openinv/internal/reobf => github/jikoo/openinv/internal/spigot26_1}/player/PlayerManager.java (94%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53226e20..a3014bdd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/setup-java@v5 with: distribution: 'temurin' - java-version: '21' + java-version: '25' # We can't use 'maven' prebuilt cache setup because it requires that the project have a pom file. # BuildTools installs to Maven local if available, so it's easier to just rely on that. @@ -36,7 +36,7 @@ jobs: - uses: gradle/actions/setup-gradle@v5 - name: Build with Gradle - run: ./gradlew clean build + run: ./gradlew build # Upload artifacts - name: Upload Distributable Jar diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index aef4e143..08bf5248 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -9,6 +9,5 @@ repositories { dependencies { val libs = project.extensions.getByType(VersionCatalogsExtension::class.java).named("libs") - implementation(libs.findLibrary("specialsource").orElseThrow()) implementation(libs.findLibrary("errorprone-gradle").orElseThrow()) } diff --git a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/BuildToolsValueSource.kt b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/BuildToolsValueSource.kt index 2bedf878..6ddd7113 100644 --- a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/BuildToolsValueSource.kt +++ b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/BuildToolsValueSource.kt @@ -16,7 +16,7 @@ abstract class BuildToolsValueSource : ValueSource + val installDir: DirectoryProperty val workingDir: DirectoryProperty val spigotVersion: Property @@ -31,11 +31,11 @@ abstract class BuildToolsValueSource : ValueSource { - - companion object { - const val ARTIFACT_CONFIG = "reobf" - } - - override fun apply(target: Project) { - // Re-use extension from Spigot dependency declaration if available to reduce configuration requirements. - val spigotExt = target.dependencies.extensions.findByType(SpigotDependencyExtension::class.java) - ?: target.dependencies.extensions.create( - "spigot", - SpigotDependencyExtension::class.java, - target.objects - ) - - val mvnLocal = target.repositories.mavenLocal() - - val reobfTask = target.tasks.register("reobfTask") { - dependsOn(target.tasks.named("shadowJar")) - // ShadowJar extends Jar, so this should be a safe way to get the result without having - // to jump through hoops and shift around shadow declarations in the rest of the project. - inputFile.convention(target.tasks.named("shadowJar").get().archiveFile) - spigotVersion.convention(spigotExt.version) - getMavenLocal().set(Paths.get(mvnLocal.url).toFile()) - } - - // Set up configuration for producing reobf jar. - target.configurations.consumable(ARTIFACT_CONFIG) { - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, target.objects.named(Category.LIBRARY)) - attribute(Usage.USAGE_ATTRIBUTE, target.objects.named(Usage.JAVA_RUNTIME)) - attribute(Bundling.BUNDLING_ATTRIBUTE, target.objects.named(Bundling.EXTERNAL)) - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, target.objects.named(LibraryElements.JAR)) - } - } - - // Add artifact from reobf task. - target.artifacts { - add(ARTIFACT_CONFIG, reobfTask) - } - } - -} diff --git a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotReobfTask.kt b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotReobfTask.kt deleted file mode 100644 index e9e12ede..00000000 --- a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotReobfTask.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.github.jikoo.openinv - -import net.md_5.specialsource.Jar -import net.md_5.specialsource.JarMapping -import net.md_5.specialsource.JarRemapper -import net.md_5.specialsource.RemapperProcessor -import net.md_5.specialsource.provider.JarProvider -import net.md_5.specialsource.provider.JointProvider -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.TaskAction -import java.io.File - -abstract class SpigotReobfTask : org.gradle.api.tasks.bundling.Jar() { - - @get:Input - val spigotVersion: Property = objectFactory.property(String::class.java) - - @get:InputFile - val inputFile: RegularFileProperty = objectFactory.fileProperty() - - @get:Input - val intermediaryClassifier: Property = objectFactory.property(String::class.java).convention("mojang-mapped") - - private val mavenLocal: Property = objectFactory.property(File::class.java) - - init { - archiveClassifier.convention(SpigotReobf.ARTIFACT_CONFIG) - } - - @TaskAction - override fun copy() { - val spigotVer = spigotVersion.get() - val inFile = inputFile.get().asFile - val obfPath = inFile.resolveSibling(inFile.name.replace(".jar", "-${intermediaryClassifier.get()}.jar")) - - // https://www.spigotmc.org/threads/510208/#post-4184317 - val repo = mavenLocal.get() - val spigotDir = repo.resolve("org/spigotmc/spigot/$spigotVer/") - val mappingDir = repo.resolve("org/spigotmc/minecraft-server/$spigotVer/") - - // Remap original Mojang-mapped jar to obfuscated intermediary - val mojangServer = spigotDir.resolve("spigot-$spigotVer-remapped-mojang.jar") - val mojangMappings = mappingDir.resolve("minecraft-server-$spigotVer-maps-mojang.txt") - remapPartial(mojangServer, mojangMappings, inFile, obfPath, true) - - // Remap obfuscated intermediary jar to Spigot and replace original - val obfServer = spigotDir.resolve("spigot-$spigotVer-remapped-obf.jar") - val spigotMappings = mappingDir.resolve("minecraft-server-$spigotVer-maps-spigot.csrg") - remapPartial(obfServer, spigotMappings, obfPath, archiveFile.get().asFile, false) - } - - private fun remapPartial(server: File, mapping: File, input: File, output: File, reverse: Boolean) { - val jarMapping = JarMapping() - jarMapping.loadMappings(mapping.path, reverse, false, null, null) - - val inheritance = JointProvider() - jarMapping.setFallbackInheritanceProvider(inheritance) - - // Equivalent of --live with server jar on classpath. - val serverJar = Jar.init(server) - inheritance.add(JarProvider(serverJar)) - - val inputJar = Jar.init(input) - inheritance.add(JarProvider(inputJar)) - - // Remap reflective access. - val preprocessor = RemapperProcessor(null, jarMapping, null) - - val remapper = JarRemapper(preprocessor, jarMapping, null) - remapper.remapJar(inputJar, output, emptySet()) - - serverJar.close() - inputJar.close() - } - - @Internal - internal fun getMavenLocal(): Property { - return mavenLocal - } - -} diff --git a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt index 8cdfae20..37698726 100644 --- a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt +++ b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt @@ -4,8 +4,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaPluginExtension import org.gradle.jvm.toolchain.JavaToolchainService -import org.gradle.kotlin.dsl.create -import java.nio.file.Paths +import java.io.File import javax.inject.Inject abstract class SpigotSetup : Plugin { @@ -24,17 +23,15 @@ abstract class SpigotSetup : Plugin { target.objects ) - val mvnLocal = target.repositories.mavenLocal() - target.afterEvaluate { // Get Java requirements, defaulting to version used for compilation. spigotExt.java.convention(target.extensions.getByType(JavaPluginExtension::class.java).toolchain) val launcher = javaToolchainService.launcherFor(spigotExt.java.get()).get() // Install Spigot with BuildTools. - target.providers.of(BuildToolsValueSource::class.java) { + val spigot: File = target.providers.of(BuildToolsValueSource::class.java) { parameters { - mavenLocal.set(Paths.get(mvnLocal.url).toFile()) + installDir.set(target.layout.buildDirectory.dir("tmp/spigot")) workingDir.set(target.layout.buildDirectory.dir("tmp/buildtools")) spigotVersion.set(spigotExt.version) spigotRevision.set(spigotExt.revision) @@ -45,9 +42,7 @@ abstract class SpigotSetup : Plugin { }.get() // Add Spigot dependency. - val dependency = target.dependencies.create( - "org.spigotmc:spigot:${spigotExt.version.get()}:${spigotExt.classifier.getOrElse("")}" - ) + val dependency = target.dependencies.create(files(spigot)) target.dependencies.add("compileOnly", dependency) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6dcd2cb7..572b1fc6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,5 @@ [versions] spigotapi = "1.21.5-R0.1-SNAPSHOT" -specialsource = "1.11.6" planarwrappers = "3.3.0" annotations = "26.1.0" paperweight = "2.0.0-beta.17" @@ -13,7 +12,6 @@ sqlite-jdbc = "3.49.1.0" [libraries] spigotapi = { module = "org.spigotmc:spigot-api", version.ref = "spigotapi" } -specialsource = { module = "net.md-5:SpecialSource", version.ref = "specialsource" } planarwrappers = { module = "com.github.jikoo:planarwrappers", version.ref = "planarwrappers" } annotations = { module = "org.jetbrains:annotations", version.ref = "annotations" } folia-scheduler-wrapper = { module = "com.github.NahuLD.folia-scheduler-wrapper:folia-scheduler-wrapper", version.ref = "folia-scheduler-wrapper" } diff --git a/internal/common/build.gradle.kts b/internal/common/build.gradle.kts index 71ca46d2..e94b4ea3 100644 --- a/internal/common/build.gradle.kts +++ b/internal/common/build.gradle.kts @@ -1,5 +1,3 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - plugins { `openinv-base` alias(libs.plugins.paperweight) @@ -35,26 +33,3 @@ dependencies { paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") } - -val spigot = tasks.register("spigotRelocations") { - dependsOn(tasks.jar) - from(sourceSets.main.get().output) - relocate("com.lishid.openinv.internal.common", "com.lishid.openinv.internal.reobf") - relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.${rootProject.extra["craftbukkitPackage"]}") - archiveClassifier = "spigot" -} - -configurations { - consumable("spigotRelocated") { - attributes { - attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY)) - attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) - attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL)) - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR)) - } - } -} - -artifacts { - add("spigotRelocated", spigot) -} diff --git a/internal/spigot/build.gradle.kts b/internal/spigot/build.gradle.kts index 526d5998..ee8f8d6c 100644 --- a/internal/spigot/build.gradle.kts +++ b/internal/spigot/build.gradle.kts @@ -1,5 +1,4 @@ import com.github.jikoo.openinv.SpigotDependencyExtension -import com.github.jikoo.openinv.SpigotReobf import com.github.jikoo.openinv.SpigotSetup plugins { @@ -7,12 +6,11 @@ plugins { alias(libs.plugins.shadow) } -apply() -apply() +java { + toolchain.languageVersion = JavaLanguageVersion.of(25) +} -val spigotVer = "1.21.11-R0.2-SNAPSHOT" -// Used by common adapter to relocate Craftbukkit classes to a versioned package. -rootProject.extra["craftbukkitPackage"] = "v1_21_R7" +apply() configurations.all { resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { @@ -30,15 +28,12 @@ configurations.all { dependencies { compileOnly(libs.spigotapi) - extensions.getByType(SpigotDependencyExtension::class.java).version = spigotVer + extensions.getByType(SpigotDependencyExtension::class.java).version = "26.1-R0.1-SNAPSHOT" + compileOnly("com.mojang:logging:1.6.11") + compileOnly("com.mojang:brigadier:1.3.10") + compileOnly("com.mojang:datafixerupper:9.0.19") + compileOnly("com.mojang:authlib:7.0.62") compileOnly(project(":openinvapi")) compileOnly(project(":openinvcommon")) - - // Reduce duplicate code by lightly remapping common adapter. - implementation(project(":openinvadaptercommon", configuration = "spigotRelocated")) -} - -tasks.shadowJar { - relocate("com.lishid.openinv.internal.common", "com.lishid.openinv.internal.reobf") } diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java new file mode 100644 index 00000000..7ac4bd1f --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java @@ -0,0 +1,80 @@ +package com.github.jikoo.openinv.internal.spigot26_1; + +import com.github.jikoo.openinv.internal.spigot26_1.container.AnySilentContainer; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.PlaceholderLoader; +import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; +import com.lishid.openinv.internal.Accessor; +import com.lishid.openinv.internal.IAnySilentContainer; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.util.lang.LanguageManager; +import net.minecraft.world.Container; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class InternalAccessor implements Accessor { + + protected final @NotNull Logger logger; + private final @NotNull PlayerManager manager; + private final @NotNull AnySilentContainer anySilentContainer; + + public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { + this.logger = logger; + manager = new PlayerManager(logger); + anySilentContainer = new AnySilentContainer(logger, lang); + } + + @Override + public @NotNull PlayerManager getPlayerManager() { + return manager; + } + + @Override + public @NotNull IAnySilentContainer getAnySilentContainer() { + return anySilentContainer; + } + + @Override + public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) { + return new OpenInventory(player); + } + + @Override + public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) { + return new OpenEnderChest(player); + } + + @Override + public @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class clazz) { + if (!(bukkitInventory instanceof CraftInventory craftInventory)) { + return null; + } + Container container = craftInventory.getInventory(); + if (clazz.isInstance(container)) { + return clazz.cast(container); + } + return null; + } + + @Override + public void reload(@NotNull ConfigurationSection config) { + ConfigurationSection placeholders = config.getConfigurationSection("placeholders"); + try { + // Reset placeholders to defaults and try to load configuration. + new PlaceholderLoader().load(placeholders); + } catch (Exception e) { + logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e); + } + } + +} diff --git a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/AnySilentContainer.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/AnySilentContainer.java similarity index 96% rename from internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/AnySilentContainer.java rename to internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/AnySilentContainer.java index 87ad310a..99865095 100644 --- a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/AnySilentContainer.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/AnySilentContainer.java @@ -1,8 +1,8 @@ -package com.lishid.openinv.internal.reobf.container; +package com.github.jikoo.openinv.internal.spigot26_1.container; import com.lishid.openinv.internal.AnySilentContainerBase; -import com.lishid.openinv.internal.reobf.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.reobf.player.PlayerManager; +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; +import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; import com.lishid.openinv.util.ReflectionHelper; import com.lishid.openinv.util.lang.LanguageManager; import net.minecraft.core.BlockPos; @@ -205,7 +205,7 @@ protected org.bukkit.block.BlockState getState(@NotNull org.bukkit.block.Block b } @Override - protected InventoryHolder getHolder(@NotNull Inventory inventory) { + protected @Nullable InventoryHolder getHolder(@NotNull Inventory inventory) { return inventory.getHolder(); } diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java new file mode 100644 index 00000000..f513bdb5 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java @@ -0,0 +1,335 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container; + +import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenPlayerInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenInventoryMenu; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.Content; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCrafting; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCraftingResult; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCursor; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentDrop; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentEquipment; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentList; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentOffHand; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentViewOnly; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.SlotViewOnly; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalOwned; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +public abstract class BaseOpenInventory implements Container, InternalOwned, ISpecialPlayerInventory { + + protected final List slots; + private final int size; + protected ServerPlayer owner; + private int maxStackSize = 99; + protected CraftInventory bukkitEntity; + public List transaction = new ArrayList<>(); + + public BaseOpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) { + owner = PlayerManager.getHandle(bukkitPlayer); + + // Get total size, rounding up to nearest 9 for client compatibility. + int rawSize = owner.getInventory().getContainerSize() + owner.inventoryMenu.getCraftSlots().getContainerSize() + 1; + size = ((int) Math.ceil(rawSize / 9.0)) * 9; + + slots = NonNullList.withSize(size, new ContentViewOnly(owner)); + setupSlots(); + } + + protected void setupSlots() { + // Top of inventory: Regular contents. + int nextIndex = addMainInventory(); + + // If inventory is expected size, we can arrange slots to be pretty. + Inventory ownerInv = owner.getInventory(); + if (ownerInv.getNonEquipmentItems().size() == 36 + && owner.inventoryMenu.getCraftSlots().getContainerSize() == 4 + && (Inventory.EQUIPMENT_SLOT_MAPPING.size() == 5 || Inventory.EQUIPMENT_SLOT_MAPPING.size() == 7)) { + // Armor slots: Bottom left. + addArmor(36); + // Off-hand: Below chestplate. + addOffHand(46); + // Drop slot: Bottom right. + slots.set(53, new ContentDrop(owner)); + // Cursor slot: Above drop. + slots.set(44, new ContentCursor(owner)); + + // Crafting is displayed in the bottom right corner. + // As we're using the pretty view, this is a 3x2. + addCrafting(41, true); + return; + } + + // Otherwise we'll just add elements linearly. + nextIndex = addArmor(nextIndex); + nextIndex = addOffHand(nextIndex); + nextIndex = addCrafting(nextIndex, false); + slots.set(nextIndex, new ContentCursor(owner)); + // Drop slot last. + slots.set(slots.size() - 1, new ContentDrop(owner)); + } + + private int addMainInventory() { + int listSize = owner.getInventory().getNonEquipmentItems().size(); + // Hotbar slots are 0-8. We want those to appear on the bottom of the inventory like a normal player inventory, + // so everything else needs to move up a row. + int hotbarDiff = listSize - 9; + for (int localIndex = 0; localIndex < listSize; ++localIndex) { + InventoryType.SlotType type; + int invIndex; + if (localIndex < hotbarDiff) { + invIndex = localIndex + 9; + type = InventoryType.SlotType.CONTAINER; + } else { + type = InventoryType.SlotType.QUICKBAR; + invIndex = localIndex - hotbarDiff; + } + + slots.set( + localIndex, + new ContentList(owner, invIndex, type) { + @Override + public void setHolder(@NotNull ServerPlayer holder) { + items = holder.getInventory().getNonEquipmentItems(); + } + } + ); + } + return listSize; + } + + private int addArmor(int startIndex) { + // Armor slots go bottom to top; boots are first and helmet is last. + // Since we have to display horizontally due to space restrictions, + // making the left side the "top" is more user-friendly. + EquipmentSlot[] sorted = Inventory.EQUIPMENT_SLOT_MAPPING.int2ObjectEntrySet() + .stream() + .sorted(Comparator.comparingInt(Int2ObjectMap.Entry::getIntKey)) + .map(Map.Entry::getValue) + .toArray(EquipmentSlot[]::new); + int localIndex = 0; + for (int i = sorted.length - 1; i >= 0; --i) { + // Skip off-hand, handled separately. Also skip non-player slots. + if (sorted[i].getType() != EquipmentSlot.Type.HUMANOID_ARMOR) { + continue; + } + + slots.set(startIndex + localIndex, new ContentEquipment(owner, sorted[i])); + ++localIndex; + } + + return startIndex + localIndex; + } + + private int addOffHand(int startIndex) { + // No off-hand? + if (!Inventory.EQUIPMENT_SLOT_MAPPING.containsValue(EquipmentSlot.OFFHAND)) { + return startIndex; + } + + slots.set(startIndex, new ContentOffHand(owner)); + return startIndex + 1; + } + + private int addCrafting(int startIndex, boolean pretty) { + int listSize = owner.inventoryMenu.getCraftSlots().getContents().size(); + pretty &= listSize == 4; + + for (int localIndex = 0; localIndex < listSize; ++localIndex) { + // Pretty display is a 2x2 rather than linear. + // If index is in top row, grid is not 2x2, or pretty is disabled, just use current index. + // Otherwise, subtract 2 and add 9 to start in the same position on the next row. + int modIndex = startIndex + (localIndex < 2 || !pretty ? localIndex : localIndex + 7); + + slots.set(modIndex, new ContentCrafting(owner, localIndex)); + } + + if (pretty) { + slots.set(startIndex + 2, new ContentViewOnly(owner) { + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y) { + @Override + public ItemStack getOrDefault() { + return Placeholders.craftingOutput; + } + }; + } + } + ); + slots.set(startIndex + 11, getCraftingResult(owner)); + } + + return startIndex + listSize; + } + + protected Content getCraftingResult(@NotNull ServerPlayer serverPlayer) { + return new ContentCraftingResult(serverPlayer); + } + + public Slot getMenuSlot(int index, int x, int y) { + return slots.get(index).asSlot(this, index, x, y); + } + + public InventoryType.SlotType getSlotType(int index) { + return slots.get(index).getSlotType(); + } + + public abstract Component getTitle(ServerPlayer player, @Nullable OpenChestMenu menu); + + @Override + public ServerPlayer getOwnerHandle() { + return owner; + } + + @Override + public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { + if (bukkitEntity == null) { + bukkitEntity = new OpenPlayerInventory(this); + } + return bukkitEntity; + } + + @Override + public void setPlayerOnline(@NotNull org.bukkit.entity.Player player) { + ServerPlayer newOwner = PlayerManager.getHandle(player); + // Only transfer regular inventory - crafting and cursor slots are transient. + newOwner.getInventory().replaceWith(owner.getInventory()); + owner = newOwner; + // Update slots to point to new inventory. + slots.forEach(slot -> slot.setHolder(newOwner)); + } + + @Override + public boolean isInUse() { + return !transaction.isEmpty(); + } + + @Override + public @NotNull org.bukkit.entity.Player getPlayer() { + return getOwner(); + } + + @Override + public int getContainerSize() { + return size; + } + + @Override + public boolean isEmpty() { + return slots.stream().map(Content::get).allMatch(ItemStack::isEmpty); + } + + @Override + public @NotNull ItemStack getItem(int index) { + return slots.get(index).get(); + } + + @Override + public @NotNull ItemStack removeItem(int index, int amount) { + return slots.get(index).removePartial(amount); + } + + @Override + public @NotNull ItemStack removeItemNoUpdate(int index) { + return slots.get(index).remove(); + } + + @Override + public void setItem(int index, @NotNull ItemStack itemStack) { + slots.get(index).set(itemStack); + } + + @Override + public int getMaxStackSize() { + return maxStackSize; + } + + @Override + public void setMaxStackSize(int maxStackSize) { + this.maxStackSize = maxStackSize; + } + + @Override + public void setChanged() { + } + + @Override + public boolean stillValid(@NotNull Player player) { + return true; + } + + @Override + public @NotNull List getContents() { + NonNullList contents = NonNullList.withSize(getContainerSize(), ItemStack.EMPTY); + for (int i = 0; i < getContainerSize(); ++i) { + contents.set(i, getItem(i)); + } + return contents; + } + + @Override + public void onOpen(@NotNull CraftHumanEntity viewer) { + transaction.add(viewer); + } + + @Override + public void onClose(@NotNull CraftHumanEntity viewer) { + transaction.remove(viewer); + } + + @Override + public @NotNull List getViewers() { + return transaction; + } + + @Override + public @NotNull org.bukkit.entity.Player getOwner() { + return owner.getBukkitEntity(); + } + + @Override + public @NotNull Location getLocation() { + return owner.getBukkitEntity().getLocation(); + } + + @Override + public void clearContent() { + owner.getInventory().clearContent(); + owner.inventoryMenu.getCraftSlots().clearContent(); + owner.inventoryMenu.slotsChanged(owner.inventoryMenu.getCraftSlots()); + owner.containerMenu.setCarried(ItemStack.EMPTY); + } + + public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenEnderChest.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenEnderChest.java new file mode 100644 index 00000000..3d91dd46 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenEnderChest.java @@ -0,0 +1,201 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container; + +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenEnderChestMenu; +import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.InternalOwned; +import net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.player.StackedItemContents; +import net.minecraft.world.inventory.StackedContentsCompatible; +import net.minecraft.world.item.ItemStack; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class OpenEnderChest implements Container, StackedContentsCompatible, InternalOwned, + ISpecialEnderChest { + + private CraftInventory inventory; + private @NotNull ServerPlayer owner; + private NonNullList items; + private int maxStack = 64; + private final List transaction = new ArrayList<>(); + + public OpenEnderChest(@NotNull org.bukkit.entity.Player player) { + this.owner = PlayerManager.getHandle(player); + this.items = owner.getEnderChestInventory().items; + } + + @Override + public @NotNull ServerPlayer getOwnerHandle() { + return owner; + } + + @Override + public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { + if (inventory == null) { + inventory = new CraftInventory(this) { + @Override + public @NotNull InventoryType getType() { + return InventoryType.ENDER_CHEST; + } + }; + } + return inventory; + } + + @Override + public void setPlayerOnline(@NotNull org.bukkit.entity.Player player) { + owner = PlayerManager.getHandle(player); + NonNullList activeItems = owner.getEnderChestInventory().items; + + // Guard against size changing. Theoretically on Purpur all row variations still have 6 rows internally. + int max = Math.min(items.size(), activeItems.size()); + for (int index = 0; index < max; ++index) { + activeItems.set(index, items.get(index)); + } + + items = activeItems; + } + + @Override + public @NotNull org.bukkit.entity.Player getPlayer() { + return owner.getBukkitEntity(); + } + + @Override + public int getContainerSize() { + return items.size(); + } + + @Override + public boolean isEmpty() { + return items.stream().allMatch(ItemStack::isEmpty); + } + + @Override + public @NotNull ItemStack getItem(int index) { + return index >= 0 && index < items.size() ? items.get(index) : ItemStack.EMPTY; + } + + @Override + public @NotNull ItemStack removeItem(int index, int amount) { + ItemStack itemstack = ContainerHelper.removeItem(items, index, amount); + + if (!itemstack.isEmpty()) { + setChanged(); + } + + return itemstack; + } + + @Override + public @NotNull ItemStack removeItemNoUpdate(int index) { + return index >= 0 && index < items.size() ? items.set(index, ItemStack.EMPTY) : ItemStack.EMPTY; + } + + @Override + public void setItem(int index, @NotNull ItemStack itemStack) { + if (index >= 0 && index < items.size()) { + items.set(index, itemStack); + } + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void setChanged() { + this.owner.getEnderChestInventory().setChanged(); + } + + @Override + public boolean stillValid(@NotNull Player player) { + return true; + } + + @Override + public @NotNull List getContents() { + return items; + } + + @Override + public void onOpen(@NotNull CraftHumanEntity craftHumanEntity) { + transaction.add(craftHumanEntity); + } + + @Override + public void onClose(@NotNull CraftHumanEntity craftHumanEntity) { + transaction.remove(craftHumanEntity); + } + + @Override + public @NotNull List getViewers() { + return transaction; + } + + @Override + public org.bukkit.entity.@NotNull Player getOwner() { + return getPlayer(); + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public @Nullable Location getLocation() { + return null; + } + + @Override + public void clearContent() { + items.clear(); + setChanged(); + } + + @Override + public void fillStackedContents(@NotNull StackedItemContents stackedContents) { + for (ItemStack itemstack : items) { + stackedContents.accountStack(itemstack); + } + } + + public Component getTitle(@Nullable OpenChestMenu menu) { + MutableComponent component; + if (menu != null && menu.isViewOnly()) { + component = Component.translatableWithFallback("openinv.container.enderchest.viewonly", "[RO] "); + } else { + component = Component.translatableWithFallback("openinv.container.enderchest.editable", ""); + } + return component + .append(Component.translatableWithFallback("openinv.container.enderchest.prefix", "", owner.getName())) + .append(Component.translatable("container.enderchest")) + .append(Component.translatableWithFallback("openinv.container.enderchest.suffix", " - %s", owner.getName())); + } + + public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenEnderChestMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java new file mode 100644 index 00000000..3ff8dec9 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java @@ -0,0 +1,49 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container; + +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FontDescription; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.Identifier; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class OpenInventory extends BaseOpenInventory { + + public OpenInventory(@NotNull Player bukkitPlayer) { + super(bukkitPlayer); + } + + @Override + public @NotNull Component getTitle(@Nullable ServerPlayer viewer, @Nullable OpenChestMenu menu) { + MutableComponent component = Component.empty(); + // Prefix for use with custom bitmap image fonts. + if (owner.equals(viewer)) { + component.append( + Component.translatableWithFallback("openinv.container.inventory.self", "") + .withStyle(style -> style + .withFont(new FontDescription.Resource(Identifier.parse("openinv:font/inventory"))) + .withColor(ChatFormatting.WHITE))); + } else { + component.append( + Component.translatableWithFallback("openinv.container.inventory.other", "") + .withStyle(style -> style + .withFont(new FontDescription.Resource(Identifier.parse("openinv:font/inventory"))) + .withColor(ChatFormatting.WHITE))); + } + if (menu != null && menu.isViewOnly()) { + component.append(Component.translatableWithFallback("openinv.container.inventory.viewonly", "[RO] ")); + } else { + component.append(Component.translatableWithFallback("openinv.container.inventory.editable", "")); + } + // Normal title: "Inventory - OwnerName" + component.append(Component.translatableWithFallback("openinv.container.inventory.prefix", "", owner.getName())) + .append(Component.translatable("container.inventory")) + .append(Component.translatableWithFallback("openinv.container.inventory.suffix", " - %s", owner.getName())); + return component; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyInventory.java new file mode 100644 index 00000000..4f19a2b3 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyInventory.java @@ -0,0 +1,168 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.bukkit; + +import com.lishid.openinv.internal.ViewOnly; +import net.minecraft.world.Container; +import org.bukkit.Material; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.ListIterator; + +/** + * A locked down "empty" inventory that rejects plugin interaction. + */ +public class OpenDummyInventory extends CraftInventory implements ViewOnly { + + private final InventoryType type; + + public OpenDummyInventory(Container inventory, InventoryType type) { + super(inventory); + this.type = type; + } + + @Override + public @NotNull InventoryType getType() { + return type; + } + + @Override + public @Nullable ItemStack getItem(int index) { + return null; + } + + @Override + public void setItem(int index, @Nullable ItemStack item) { + + } + + @Override + public @NotNull HashMap addItem(@NotNull ItemStack... items) throws IllegalArgumentException { + return arrayToHashMap(items); + } + + @Override + public @NotNull HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException { + return arrayToHashMap(items); + } + + private static @NotNull HashMap arrayToHashMap(@NotNull ItemStack[] items) { + HashMap ignored = new HashMap<>(); + for (int index = 0; index < items.length; ++index) { + ignored.put(index, items[index]); + } + return ignored; + } + + @Override + public ItemStack @NotNull [] getContents() { + return new ItemStack[getSize()]; + } + + @Override + public void setContents(@NotNull ItemStack[] items) throws IllegalArgumentException { + + } + + @Override + public @NotNull ItemStack @NotNull [] getStorageContents() { + return new ItemStack[getSize()]; + } + + @Override + public void setStorageContents(@NotNull ItemStack[] items) throws IllegalArgumentException { + + } + + @Override + public boolean contains(@NotNull Material material) throws IllegalArgumentException { + return false; + } + + @Override + public boolean contains(@Nullable ItemStack item) { + return false; + } + + @Override + public boolean contains(@NotNull Material material, int amount) throws IllegalArgumentException { + return false; + } + + @Override + public boolean contains(@Nullable ItemStack item, int amount) { + return false; + } + + @Override + public boolean containsAtLeast(@Nullable ItemStack item, int amount) { + return false; + } + + @Override + public @NotNull HashMap all( + @NotNull Material material + ) throws IllegalArgumentException { + return new HashMap<>(); + } + + @Override + public @NotNull HashMap all(@Nullable ItemStack item) { + return new HashMap<>(); + } + + @Override + public int first(@NotNull Material material) throws IllegalArgumentException { + return -1; + } + + @Override + public int first(@NotNull ItemStack item) { + return -1; + } + + @Override + public int firstEmpty() { + return -1; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public void remove(@NotNull Material material) throws IllegalArgumentException { + + } + + @Override + public void remove(@NotNull ItemStack item) { + + } + + @Override + public void clear(int index) { + + } + + @Override + public void clear() { + + } + + @Override + public @NotNull ListIterator iterator() { + return Collections.emptyListIterator(); + } + + @Override + public @NotNull ListIterator iterator(int index) { + return Collections.emptyListIterator(); + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyPlayerInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyPlayerInventory.java new file mode 100644 index 00000000..94651862 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenDummyPlayerInventory.java @@ -0,0 +1,137 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.bukkit; + +import net.minecraft.world.Container; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class OpenDummyPlayerInventory extends OpenDummyInventory implements PlayerInventory { + + public OpenDummyPlayerInventory(Container inventory) { + super(inventory, InventoryType.PLAYER); + } + + @Override + public HumanEntity getHolder() { + return (HumanEntity) super.getHolder(); + } + + @Override + public @NotNull ItemStack @NotNull [] getArmorContents() { + return new ItemStack[4]; + } + + @Override + public @NotNull ItemStack @NotNull [] getExtraContents() { + return new ItemStack[4]; + } + + @Override + public @Nullable ItemStack getHelmet() { + return null; + } + + @Override + public @Nullable ItemStack getChestplate() { + return null; + } + + @Override + public @Nullable ItemStack getLeggings() { + return null; + } + + @Override + public @Nullable ItemStack getBoots() { + return null; + } + + @Override + public void setItem(@NotNull EquipmentSlot slot, @Nullable ItemStack item) { + + } + + @Override + public @NotNull ItemStack getItem(@NotNull EquipmentSlot slot) { + return new ItemStack(Material.AIR); + } + + @Override + public void setArmorContents(ItemStack @NotNull [] items) { + + } + + @Override + public void setExtraContents(ItemStack @NotNull [] items) { + + } + + @Override + public void setHelmet(@Nullable ItemStack helmet) { + + } + + @Override + public void setChestplate(@Nullable ItemStack chestplate) { + + } + + @Override + public void setLeggings(@Nullable ItemStack leggings) { + + } + + @Override + public void setBoots(@Nullable ItemStack boots) { + + } + + @Override + public @NotNull ItemStack getItemInMainHand() { + return new ItemStack(Material.AIR); + } + + @Override + public void setItemInMainHand(@Nullable ItemStack item) { + + } + + @Override + public @NotNull ItemStack getItemInOffHand() { + return new ItemStack(Material.AIR); + } + + @Override + public void setItemInOffHand(@Nullable ItemStack item) { + + } + + @SuppressWarnings("InlineMeSuggester") + @Deprecated + @Override + public @NotNull ItemStack getItemInHand() { + return new ItemStack(Material.AIR); + } + + @Deprecated + @Override + public void setItemInHand(@Nullable ItemStack stack) { + + } + + @Override + public int getHeldItemSlot() { + return 0; + } + + @Override + public void setHeldItemSlot(int slot) { + + } + +} diff --git a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/bukkit/OpenPlayerInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java similarity index 95% rename from internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/bukkit/OpenPlayerInventory.java rename to internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java index 77aefe24..512f5258 100644 --- a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/bukkit/OpenPlayerInventory.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java @@ -1,11 +1,11 @@ -package com.lishid.openinv.internal.reobf.container.bukkit; +package com.github.jikoo.openinv.internal.spigot26_1.container.bukkit; import com.google.common.base.Preconditions; -import com.lishid.openinv.internal.reobf.container.BaseOpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.BaseOpenInventory; import net.minecraft.core.NonNullList; import net.minecraft.world.entity.player.Inventory; -import org.bukkit.craftbukkit.v1_21_R7.inventory.CraftInventory; -import org.bukkit.craftbukkit.v1_21_R7.inventory.CraftItemStack; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.ItemStack; diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java new file mode 100644 index 00000000..7d57a8a6 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java @@ -0,0 +1,26 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.bukkit; + +import com.github.jikoo.openinv.internal.spigot26_1.container.BaseOpenInventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class OpenPlayerInventorySelf extends OpenPlayerInventory { + + private final int offset; + + public OpenPlayerInventorySelf(@NotNull BaseOpenInventory inventory, int offset) { + super(inventory); + this.offset = offset; + } + + @Override + public ItemStack getItem(int index) { + return super.getItem(offset + index); + } + + @Override + public void setItem(int index, ItemStack item) { + super.setItem(offset + index, item); + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenChestMenu.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenChestMenu.java new file mode 100644 index 00000000..92fe5046 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenChestMenu.java @@ -0,0 +1,288 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.menu; + +import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenDummyInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.SlotViewOnly; +import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InternalOwned; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.ContainerInput; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.inventory.CraftInventoryView; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * An extension of {@link AbstractContainerMenu} storing and managing data common to all special inventories. + */ +public abstract class OpenChestMenu> + extends AbstractContainerMenu { + + protected static final int BOTTOM_INVENTORY_SIZE = 36; + + protected final T container; + protected final ServerPlayer viewer; + protected final boolean viewOnly; + protected final boolean ownContainer; + protected final int topSize; + private CraftInventoryView, Inventory> bukkitEntity; + + protected OpenChestMenu( + @NotNull MenuType type, + int containerCounter, + @NotNull T container, + @NotNull ServerPlayer viewer, + boolean viewOnly + ) { + super(type, containerCounter); + this.container = container; + this.viewer = viewer; + this.viewOnly = viewOnly; + ownContainer = container.getOwnerHandle().equals(viewer); + topSize = getTopSize(viewer); + + preSlotSetup(); + + int upperRows = topSize / 9; + // View's upper inventory - our container + for (int row = 0; row < upperRows; ++row) { + for (int col = 0; col < 9; ++col) { + // x and y for client purposes, but hey, we're thorough here. + // Adapted from net.minecraft.world.inventory.ChestMenu + int x = 8 + col * 18; + int y = 18 + row * 18; + int index = row * 9 + col; + + // Guard against weird inventory sizes. + if (index >= container.getContainerSize()) { + addSlot(new SlotViewOnly(container, index, x, y)); + continue; + } + + Slot slot = getUpperSlot(index, x, y); + + addSlot(slot); + } + } + + // View's lower inventory - viewer inventory + int playerInvPad = (upperRows - 4) * 18; + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 9; ++col) { + int x = 8 + col * 18; + int y = playerInvPad + row * 18 + 103; + addSlot(new Slot(viewer.getInventory(), row * 9 + col + 9, x, y)); + } + } + // Hotbar + for (int col = 0; col < 9; ++col) { + int x = 8 + col * 18; + int y = playerInvPad + 161; + addSlot(new Slot(viewer.getInventory(), col, x, y)); + } + } + + public static @NotNull MenuType getChestMenuType(int inventorySize) { + inventorySize = ((int) Math.ceil(inventorySize / 9.0)) * 9; + return switch (inventorySize) { + case 9 -> MenuType.GENERIC_9x1; + case 18 -> MenuType.GENERIC_9x2; + case 27 -> MenuType.GENERIC_9x3; + case 36 -> MenuType.GENERIC_9x4; + case 45 -> MenuType.GENERIC_9x5; + case 54 -> MenuType.GENERIC_9x6; + default -> throw new IllegalArgumentException("Inventory size unsupported: " + inventorySize); + }; + } + + + protected void preSlotSetup() { + } + + protected @NotNull Slot getUpperSlot(int index, int x, int y) { + Slot slot = new Slot(container, index, x, y); + if (viewOnly) { + return SlotViewOnly.wrap(slot); + } + return slot; + } + + public boolean isViewOnly() { + return viewOnly; + } + + @Override + public final @NotNull CraftInventoryView, Inventory> getBukkitView() { + if (bukkitEntity == null) { + bukkitEntity = createBukkitEntity(); + } + + return bukkitEntity; + } + + protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { + Inventory top; + if (viewOnly) { + top = new OpenDummyInventory(container, container.getBukkitType()); + } else { + top = container.getBukkitInventory(); + } + return new CraftInventoryView<>(viewer.getBukkitEntity(), top, this) { + @Override + public @Nullable Inventory getInventory(int rawSlot) { + if (viewOnly) { + return null; + } + return super.getInventory(rawSlot); + } + + @Override + public int convertSlot(int rawSlot) { + if (viewOnly) { + return InventoryView.OUTSIDE; + } + return super.convertSlot(rawSlot); + } + + @Override + public @NotNull InventoryType.SlotType getSlotType(int slot) { + if (viewOnly) { + return InventoryType.SlotType.OUTSIDE; + } + return super.getSlotType(slot); + } + }; + } + + private int getTopSize(ServerPlayer viewer) { + MenuType menuType = getType(); + if (menuType == MenuType.GENERIC_9x1) { + return 9; + } else if (menuType == MenuType.GENERIC_9x2) { + return 18; + } else if (menuType == MenuType.GENERIC_9x3) { + return 27; + } else if (menuType == MenuType.GENERIC_9x4) { + return 36; + } else if (menuType == MenuType.GENERIC_9x5) { + return 45; + } else if (menuType == MenuType.GENERIC_9x6) { + return 54; + } + // This is a bit gross, but allows us a safe fallthrough. + return menuType.create(-1, viewer.getInventory()).slots.size() - BOTTOM_INVENTORY_SIZE; + } + + /** + * Reimplementation of {@link AbstractContainerMenu#moveItemStackTo(ItemStack, int, int, boolean)} that ignores fake + * slots and respects {@link Slot#hasItem()}. + * + * @param itemStack the stack to quick-move + * @param rangeLow the start of the range of slots that can be moved to, inclusive + * @param rangeHigh the end of the range of slots that can be moved to, exclusive + * @param topDown whether to start at the top of the range or bottom + * @return whether the stack was modified as a result of being quick-moved + */ + @Override + protected boolean moveItemStackTo(ItemStack itemStack, int rangeLow, int rangeHigh, boolean topDown) { + boolean modified = false; + boolean stackable = itemStack.isStackable(); + Slot firstEmpty = null; + + for (int index = topDown ? rangeHigh - 1 : rangeLow; + !itemStack.isEmpty() && (topDown ? index >= rangeLow : index < rangeHigh); + index += topDown ? -1 : 1 + ) { + Slot slot = slots.get(index); + // If the slot cannot be added to, check the next slot. + if (slot.isFake() || !slot.mayPlace(itemStack)) { + continue; + } + + if (slot.hasItem()) { + // If the item isn't stackable, check the next slot. + if (!stackable) { + continue; + } + // Otherwise, add as many as we can from our stack to the slot. + modified |= addToExistingStack(itemStack, slot); + } else { + // If this is the first empty slot, keep track of it for later use. + if (firstEmpty == null) { + firstEmpty = slot; + } + // If the item isn't stackable, we've located the slot we're adding it to, so we're done. + if (!stackable) { + break; + } + } + } + + // If the item hasn't been fully added yet, add as many as we can to the first open slot. + if (!itemStack.isEmpty() && firstEmpty != null) { + firstEmpty.setByPlayer(itemStack.split(Math.min(itemStack.getCount(), firstEmpty.getMaxStackSize(itemStack)))); + firstEmpty.setChanged(); + modified = true; + } + + return modified; + } + + private static boolean addToExistingStack(ItemStack itemStack, Slot slot) { + ItemStack existing = slot.getItem(); + + // If the items aren't the same, we can't add our item. + if (!ItemStack.isSameItemSameComponents(itemStack, existing)) { + return false; + } + + int max = slot.getMaxStackSize(existing); + int existingCount = existing.getCount(); + + // If the stack is already full, we can't add more. + if (existingCount >= max) { + return false; + } + + int total = existingCount + itemStack.getCount(); + + // If the existing item can accept the entirety of our item, we're done! + if (total <= max) { + itemStack.setCount(0); + existing.setCount(total); + slot.setChanged(); + return true; + } + + // Otherwise, add as many as we can. + itemStack.shrink(max - existingCount); + existing.setCount(max); + slot.setChanged(); + return true; + } + + @Override + public void clicked(int i, int j, @NotNull ContainerInput clickType, @NotNull Player player) { + if (viewOnly) { + if (clickType == ContainerInput.QUICK_CRAFT) { + sendAllDataToRemote(); + } + return; + } + super.clicked(i, j, clickType, player); + } + + @Override + public boolean stillValid(@NotNull Player player) { + return true; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenEnderChestMenu.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenEnderChestMenu.java new file mode 100644 index 00000000..6669982d --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenEnderChestMenu.java @@ -0,0 +1,54 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.menu; + +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class OpenEnderChestMenu extends OpenSyncMenu { + + public OpenEnderChestMenu( + @NotNull OpenEnderChest enderChest, + @NotNull ServerPlayer viewer, + int containerId, + boolean viewOnly + ) { + super(getChestMenuType(enderChest.getContainerSize()), containerId, enderChest, viewer, viewOnly); + } + + @Override + public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { + if (viewOnly) { + return ItemStack.EMPTY; + } + + // See ChestMenu + Slot slot = this.slots.get(index); + + if (slot.isFake() || !slot.hasItem()) { + return ItemStack.EMPTY; + } + + ItemStack itemStack = slot.getItem(); + ItemStack original = itemStack.copy(); + + if (index < topSize) { + if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemStack, 0, topSize, false)) { + return ItemStack.EMPTY; + } + + if (itemStack.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + return original; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java new file mode 100644 index 00000000..b8e69195 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java @@ -0,0 +1,265 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.menu; + +import com.google.common.base.Preconditions; +import com.lishid.openinv.util.Permissions; +import com.github.jikoo.openinv.internal.spigot26_1.container.BaseOpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenDummyPlayerInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenPlayerInventorySelf; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentDrop; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentEquipment; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.SlotViewOnly; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class OpenInventoryMenu extends OpenSyncMenu { + + private int offset; + + public OpenInventoryMenu(BaseOpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { + super(getMenuType(inventory, viewer), i, inventory, viewer, viewOnly); + } + + private static MenuType getMenuType(BaseOpenInventory inventory, ServerPlayer viewer) { + int size = inventory.getContainerSize(); + // Disallow duplicate access to own main inventory contents. + if (inventory.getOwnerHandle().equals(viewer)) { + size -= viewer.getInventory().getNonEquipmentItems().size(); + size = ((int) Math.ceil(size / 9.0)) * 9; + } + + return getChestMenuType(size); + } + + @Override + protected void preSlotSetup() { + offset = ownContainer ? viewer.getInventory().getNonEquipmentItems().size() : 0; + } + + @Override + protected @NotNull Slot getUpperSlot(int index, int x, int y) { + index += offset; + Slot slot = container.getMenuSlot(index, x, y); + + // If the slot cannot be interacted with there's nothing to configure. + if (slot.getClass().equals(SlotViewOnly.class)) { + return slot; + } + + // Remove drop slot if viewer is not allowed to use it. + if (slot instanceof ContentDrop.SlotDrop + && (viewOnly || !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity()))) { + return new SlotViewOnly(container, index, x, y); + } + + if (slot instanceof ContentEquipment.SlotEquipment equipment) { + if (viewOnly) { + return SlotViewOnly.wrap(slot); + } + + Permissions perm = switch (equipment.getEquipmentSlot()) { + case HEAD -> Permissions.INVENTORY_SLOT_HEAD_ANY; + case CHEST -> Permissions.INVENTORY_SLOT_CHEST_ANY; + case LEGS -> Permissions.INVENTORY_SLOT_LEGS_ANY; + case FEET -> Permissions.INVENTORY_SLOT_FEET_ANY; + // Off-hand can hold anything, not just equipment. + default -> null; + }; + + // If the viewer doesn't have permission, only allow equipment the viewee can equip in the slot. + if (perm != null && !perm.hasPermission(viewer.getBukkitEntity())) { + equipment.onlyEquipmentFor(container.getOwnerHandle()); + } + + // Equipment slots are a core part of the inventory, so they will always be shown. + return slot; + } + + // When viewing own inventory, only allow access to equipment and drop slots (equipment allowed above). + if (ownContainer && !(slot instanceof ContentDrop.SlotDrop)) { + return new SlotViewOnly(container, index, x, y); + } + + if (viewOnly) { + return SlotViewOnly.wrap(slot); + } + + return slot; + } + + @Override + protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { + Inventory bukkitInventory; + if (viewOnly) { + bukkitInventory = new OpenDummyPlayerInventory(container); + } else if (ownContainer) { + bukkitInventory = new OpenPlayerInventorySelf(container, offset); + } else { + bukkitInventory = container.getBukkitInventory(); + } + + return new CraftInventoryView<>(viewer.getBukkitEntity(), bukkitInventory, this) { + @Override + public org.bukkit.inventory.ItemStack getItem(int index) { + if (viewOnly || index < 0) { + return null; + } + + Slot slot = slots.get(index); + return CraftItemStack.asCraftMirror(slot.hasItem() ? slot.getItem() : ItemStack.EMPTY); + } + + @Override + public boolean isInTop(int rawSlot) { + return rawSlot < topSize; + } + + @Override + public @Nullable Inventory getInventory(int rawSlot) { + if (viewOnly) { + return null; + } + if (rawSlot == InventoryView.OUTSIDE || rawSlot == -1) { + return null; + } + Preconditions.checkArgument( + rawSlot >= 0 && rawSlot < topSize + offset + BOTTOM_INVENTORY_SIZE, + "Slot %s outside of inventory", + rawSlot + ); + if (rawSlot > topSize) { + return getBottomInventory(); + } + Slot slot = slots.get(rawSlot); + if (slot.isFake()) { + return null; + } + return getTopInventory(); + } + + @Override + public int convertSlot(int rawSlot) { + if (viewOnly) { + return InventoryView.OUTSIDE; + } + if (rawSlot < 0) { + return rawSlot; + } + if (rawSlot < topSize) { + Slot slot = slots.get(rawSlot); + if (slot.isFake()) { + return InventoryView.OUTSIDE; + } + return rawSlot; + } + + int slot = rawSlot - topSize; + + if (slot >= 27) { + slot -= 27; + } else { + slot += 9; + } + + return slot; + } + + @Override + public @NotNull InventoryType.SlotType getSlotType(int slot) { + if (viewOnly || slot < 0) { + return InventoryType.SlotType.OUTSIDE; + } + if (slot >= topSize) { + slot -= topSize; + if (slot >= 27) { + return InventoryType.SlotType.QUICKBAR; + } + return InventoryType.SlotType.CONTAINER; + } + return OpenInventoryMenu.this.container.getSlotType(offset + slot); + } + + @Override + public int countSlots() { + return topSize + BOTTOM_INVENTORY_SIZE; + } + }; + } + + @Override + public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { + if (viewOnly) { + return ItemStack.EMPTY; + } + + // See ChestMenu and InventoryMenu + Slot slot = this.slots.get(index); + + if (!slot.hasItem() || slot.isFake()) { + return ItemStack.EMPTY; + } + + ItemStack itemStack = slot.getItem(); + ItemStack originalStack = itemStack.copy(); + + if (index < topSize) { + // If we're moving top to bottom, do a normal transfer. + if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { + return ItemStack.EMPTY; + } + } else { + EquipmentSlot equipmentSlot = player.getEquipmentSlotForItem(itemStack); + boolean movedGear = switch (equipmentSlot) { + // If this is gear, try to move it to the correct slot first. + case OFFHAND, FEET, LEGS, CHEST, HEAD -> { + // Locate the correct slot in the contents following the main inventory. + for (int extra = container.getOwnerHandle().getInventory().getNonEquipmentItems().size() - offset; extra < topSize; ++extra) { + Slot extraSlot = getSlot(extra); + if (extraSlot instanceof ContentEquipment.SlotEquipment equipSlot + && equipSlot.getEquipmentSlot() == equipmentSlot) { + // If we've found a matching slot, try to move to it. + // If this succeeds, even partially, we will not attempt to move to other slots. + // Otherwise, armor is already occupied, so we'll fall through to main inventory. + yield this.moveItemStackTo(itemStack, extra, extra + 1, false); + } + } + yield false; + } + // Non-gear gets no special treatment. + default -> false; + }; + + // If main inventory is not available, there's nowhere else to move. + if (offset != 0) { + if (!movedGear) { + return ItemStack.EMPTY; + } + } else { + // If we didn't move to a gear slot, try to move to a main inventory slot. + if (!movedGear && !this.moveItemStackTo(itemStack, 0, container.getOwnerHandle().getInventory().getNonEquipmentItems().size(), true)) { + return ItemStack.EMPTY; + } + } + } + + if (itemStack.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + return originalStack; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenSyncMenu.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenSyncMenu.java new file mode 100644 index 00000000..43186c1e --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenSyncMenu.java @@ -0,0 +1,237 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.menu; + +import com.google.common.base.Suppliers; +import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InternalOwned; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.SlotPlaceholder; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.network.HashedStack; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.inventory.ContainerSynchronizer; +import net.minecraft.world.inventory.DataSlot; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.RemoteSlot; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * An extension of {@link OpenChestMenu} that supports {@link SlotPlaceholder placeholders}. + */ +@SuppressWarnings("HidingField") // Revisit when removing 1.21.4 support +public abstract class OpenSyncMenu> + extends OpenChestMenu { + + // Syncher fields + protected @Nullable ContainerSynchronizer synchronizer; + protected final List dataSlots = new ArrayList<>(); + protected final IntList remoteDataSlots = new IntArrayList(); + protected final List containerListeners = new ArrayList<>(); + private RemoteSlot remoteCarried = RemoteSlot.PLACEHOLDER; + protected boolean suppressRemoteUpdates; + + protected OpenSyncMenu( + @NotNull MenuType type, + int containerCounter, + @NotNull T container, + @NotNull ServerPlayer viewer, + boolean viewOnly + ) { + super(type, containerCounter, container, viewer, viewOnly); + } + + // Overrides from here on are purely to modify the sync process to send placeholder items. + @Override + protected @NotNull Slot addSlot(@NotNull Slot slot) { + slot.index = this.slots.size(); + this.slots.add(slot); + this.lastSlots.add(ItemStack.EMPTY); + this.remoteSlots.add(this.synchronizer != null ? this.synchronizer.createSlot() : RemoteSlot.PLACEHOLDER); + return slot; + } + + @Override + protected @NotNull DataSlot addDataSlot(@NotNull DataSlot dataSlot) { + this.dataSlots.add(dataSlot); + this.remoteDataSlots.add(0); + return dataSlot; + } + + @Override + protected void addDataSlots(ContainerData containerData) { + for (int i = 0; i < containerData.getCount(); i++) { + this.addDataSlot(DataSlot.forContainer(containerData, i)); + } + } + + @Override + public void addSlotListener(@NotNull ContainerListener containerListener) { + if (!this.containerListeners.contains(containerListener)) { + this.containerListeners.add(containerListener); + this.broadcastChanges(); + } + } + + @Override + public void setSynchronizer(@NotNull ContainerSynchronizer containerSynchronizer) { + this.synchronizer = containerSynchronizer; + this.remoteCarried = synchronizer.createSlot(); + this.remoteSlots.replaceAll(slot -> synchronizer.createSlot()); + this.sendAllDataToRemote(); + } + + @Override + public void sendAllDataToRemote() { + List contentsCopy = new ArrayList<>(); + for (int index = 0; index < slots.size(); ++index) { + Slot slot = slots.get(index); + ItemStack itemStack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); + contentsCopy.add(itemStack); + this.remoteSlots.get(index).force(itemStack); + } + + remoteCarried.force(getCarried()); + + for (int index = 0; index < this.dataSlots.size(); ++index) { + this.remoteDataSlots.set(index, this.dataSlots.get(index).get()); + } + + if (this.synchronizer != null) { + this.synchronizer.sendInitialData(this, contentsCopy, this.getCarried().copy(), this.remoteDataSlots.toIntArray()); + } + } + + @Override + public void broadcastCarriedItem() { + ItemStack carried = this.getCarried(); + this.remoteCarried.force(carried); + if (this.synchronizer != null) { + this.synchronizer.sendCarriedChange(this, carried.copy()); + } + } + + @Override + public void removeSlotListener(@NotNull ContainerListener containerListener) { + this.containerListeners.remove(containerListener); + } + + @Override + public void broadcastChanges() { + for (int index = 0; index < this.slots.size(); ++index) { + Slot slot = this.slots.get(index); + ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); + Supplier supplier = Suppliers.memoize(itemstack::copy); + this.triggerSlotListeners(index, itemstack, supplier); + this.synchronizeSlotToRemote(index, itemstack, supplier); + } + + this.synchronizeCarriedToRemote(); + + for (int index = 0; index < this.dataSlots.size(); ++index) { + DataSlot dataSlot = this.dataSlots.get(index); + int j = dataSlot.get(); + if (dataSlot.checkAndClearUpdateFlag()) { + this.updateDataSlotListeners(index, j); + } + + this.synchronizeDataSlotToRemote(index, j); + } + } + + @Override + public void broadcastFullState() { + for (int index = 0; index < this.slots.size(); ++index) { + ItemStack itemstack = this.slots.get(index).getItem(); + this.triggerSlotListeners(index, itemstack, itemstack::copy); + } + + for (int index = 0; index < this.dataSlots.size(); ++index) { + DataSlot containerproperty = this.dataSlots.get(index); + if (containerproperty.checkAndClearUpdateFlag()) { + this.updateDataSlotListeners(index, containerproperty.get()); + } + } + + this.sendAllDataToRemote(); + } + + private void updateDataSlotListeners(int i, int j) { + for (ContainerListener containerListener : this.containerListeners) { + containerListener.dataChanged(this, i, j); + } + } + + private void triggerSlotListeners(int index, @NotNull ItemStack itemStack, @NotNull Supplier supplier) { + ItemStack itemStack1 = this.lastSlots.get(index); + if (!ItemStack.matches(itemStack1, itemStack)) { + ItemStack itemStack2 = supplier.get(); + this.lastSlots.set(index, itemStack2); + + for (ContainerListener containerListener : this.containerListeners) { + containerListener.slotChanged(this, index, itemStack2); + } + } + } + + private void synchronizeSlotToRemote(int i, @NotNull ItemStack itemStack, @NotNull Supplier supplier) { + if (!this.suppressRemoteUpdates) { + RemoteSlot slot = this.remoteSlots.get(i); + if (!slot.matches(itemStack)) { + slot.force(itemStack); + if (this.synchronizer != null) { + this.synchronizer.sendSlotChange(this, i, supplier.get()); + } + } + } + } + + private void synchronizeDataSlotToRemote(int index, int value) { + if (!this.suppressRemoteUpdates) { + int existing = this.remoteDataSlots.getInt(index); + if (existing != value) { + this.remoteDataSlots.set(index, value); + if (this.synchronizer != null) { + this.synchronizer.sendDataChange(this, index, value); + } + } + } + } + + private void synchronizeCarriedToRemote() { + if (!this.suppressRemoteUpdates) { + ItemStack carried = this.getCarried(); + if (!this.remoteCarried.matches(carried)) { + this.remoteCarried.force(carried); + if (this.synchronizer != null) { + this.synchronizer.sendCarriedChange(this, carried.copy()); + } + } + } + } + + @Override + public void setRemoteCarried(@NotNull HashedStack stack) { + this.remoteCarried.receive(stack); + } + + @Override + public void suppressRemoteUpdates() { + this.suppressRemoteUpdates = true; + } + + @Override + public void resumeRemoteUpdates() { + this.suppressRemoteUpdates = false; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/Content.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/Content.java new file mode 100644 index 00000000..6be9ca5d --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/Content.java @@ -0,0 +1,69 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * An interface defining behaviors for entries in a {@link Container}. Used to reduce duplicate content reordering. + */ +public interface Content { + + /** + * Update internal holder. + * + * @param holder the new holder + */ + void setHolder(@NotNull ServerPlayer holder); + + /** + * Get the current item. + * + * @return the current item + */ + ItemStack get(); + + /** + * Remove the current item. + * + * @return the current item + */ + ItemStack remove(); + + /** + * Remove some of the current item. + * + * @return the current item + */ + ItemStack removePartial(int amount); + + /** + * Set the current item. If slot is currently not usable, will drop item instead. + * + * @param itemStack the item to set + */ + void set(ItemStack itemStack); + + /** + * Get a {@link Slot} for use in a {@link net.minecraft.world.inventory.AbstractContainerMenu ContainerMenu}. Will + * impose any specific restrictions to insertion or removal. + * + * @param container the backing container + * @param slot the slot of the backing container represented + * @param x clientside x dimension from top left of inventory, not used + * @param y clientside y dimension from top left of inventory, not used + * @return a menu slot + */ + Slot asSlot(Container container, int slot, int x, int y); + + /** + * Get a loose Bukkit translation of what this slot stores. For example, any slot that drops items at the owner rather + * than insert them will report itself as being {@link org.bukkit.event.inventory.InventoryType.SlotType#OUTSIDE}. + * + * @return the closes Bukkit slot type + */ + org.bukkit.event.inventory.InventoryType.SlotType getSlotType(); + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCrafting.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCrafting.java new file mode 100644 index 00000000..a2c76f27 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCrafting.java @@ -0,0 +1,132 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import com.github.jikoo.openinv.internal.spigot26_1.player.OpenPlayer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * A slot in a survival crafting inventory. Unavailable when not online in a survival mode. + */ +public class ContentCrafting implements Content { + + private final int index; + private ServerPlayer holder; + private List items; + + public ContentCrafting(@NotNull ServerPlayer holder, int index) { + setHolder(holder); + this.index = index; + } + + private boolean isAvailable() { + return isAvailable(holder); + } + + public static boolean isAvailable(@NotNull ServerPlayer holder) { + // Player must be online and not in creative - since the creative client is (semi-)authoritative, + // it ignores changes without extra help, and will delete the item as a result. + // Spectator mode is technically possible but may cause the item to be dropped if the client opens an inventory. + return OpenPlayer.isConnected(holder.connection) && holder.gameMode.isSurvival(); + } + + @Override + public void setHolder(@NotNull ServerPlayer holder) { + this.holder = holder; + // Note: CraftingContainer#getItems is immutable! Be careful with updates. + this.items = holder.inventoryMenu.getCraftSlots().getContents(); + } + + @Override + public ItemStack get() { + return isAvailable() ? items.get(index) : ItemStack.EMPTY; + } + + @Override + public ItemStack remove() { + if (!this.isAvailable()) { + return ItemStack.EMPTY; + } + ItemStack removed = items.remove(index); + if (removed.isEmpty()) { + return ItemStack.EMPTY; + } + holder.inventoryMenu.slotsChanged(holder.inventoryMenu.getCraftSlots()); + return removed; + } + + @Override + public ItemStack removePartial(int amount) { + if (!this.isAvailable()) { + return ItemStack.EMPTY; + } + ItemStack removed = ContainerHelper.removeItem(items, index, amount); + if (removed.isEmpty()) { + return ItemStack.EMPTY; + } + holder.inventoryMenu.slotsChanged(holder.inventoryMenu.getCraftSlots()); + return removed; + } + + @Override + public void set(ItemStack itemStack) { + if (isAvailable()) { + items.set(index, itemStack); + holder.inventoryMenu.slotsChanged(holder.inventoryMenu.getCraftSlots()); + } else { + holder.drop(itemStack, false); + } + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotCrafting(container, slot, x, y); + } + + @Override + public InventoryType.SlotType getSlotType() { + return isAvailable() ? InventoryType.SlotType.CRAFTING : InventoryType.SlotType.OUTSIDE; + } + + public class SlotCrafting extends SlotPlaceholder { + + private SlotCrafting(Container container, int index, int x, int y) { + super(container, index, x, y); + } + + @Override + public ItemStack getOrDefault() { + return isAvailable() ? items.get(ContentCrafting.this.index) : Placeholders.survivalOnly(holder); + } + + @Override + public boolean mayPickup(@NotNull Player player) { + return isAvailable(); + } + + @Override + public boolean mayPlace(@NotNull ItemStack itemStack) { + return isAvailable(); + } + + @Override + public boolean hasItem() { + return isAvailable() && super.hasItem(); + } + + @Override + public boolean isFake() { + return !isAvailable(); + } + + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCraftingResult.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCraftingResult.java new file mode 100644 index 00000000..886a8d1d --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCraftingResult.java @@ -0,0 +1,48 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +/** + * A slot allowing viewing of the crafting result. + * + *

Unmodifiable because I said so. Use your own crafting grid.

+ */ +public class ContentCraftingResult extends ContentViewOnly { + + public ContentCraftingResult(@NotNull ServerPlayer holder) { + super(holder); + } + + @Override + public ItemStack get() { + InventoryMenu inventoryMenu = holder.inventoryMenu; + return inventoryMenu.getResultSlot().getItem(); + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y) { + @Override + public ItemStack getOrDefault() { + if (!ContentCrafting.isAvailable(holder)) { + return Placeholders.survivalOnly(holder); + } + InventoryMenu inventoryMenu = holder.inventoryMenu; + return inventoryMenu.getResultSlot().getItem(); + } + }; + } + + @Override + public InventoryType.SlotType getSlotType() { + return InventoryType.SlotType.RESULT; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCursor.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCursor.java new file mode 100644 index 00000000..0a35c588 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentCursor.java @@ -0,0 +1,118 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import com.github.jikoo.openinv.internal.spigot26_1.player.OpenPlayer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +/** + * A slot wrapping the active menu's cursor. Unavailable when not online in a survival mode. + */ +public class ContentCursor implements Content { + + private @NotNull ServerPlayer holder; + + public ContentCursor(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public void setHolder(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public ItemStack get() { + return isAvailable() ? holder.containerMenu.getCarried() : ItemStack.EMPTY; + } + + @Override + public ItemStack remove() { + ItemStack carried = holder.containerMenu.getCarried(); + holder.containerMenu.setCarried(ItemStack.EMPTY); + return carried; + } + + @Override + public ItemStack removePartial(int amount) { + ItemStack carried = holder.containerMenu.getCarried(); + if (!carried.isEmpty() && carried.getCount() >= amount) { + ItemStack value = carried.split(amount); + if (carried.isEmpty()) { + holder.containerMenu.setCarried(ItemStack.EMPTY); + } + return value; + } + return ItemStack.EMPTY; + } + + @Override + public void set(ItemStack itemStack) { + if (isAvailable()) { + holder.containerMenu.setCarried(itemStack); + } else { + holder.drop(itemStack, false); + } + } + + private boolean isAvailable() { + // Player must be online and not in creative - since the creative client is (semi-)authoritative, + // it ignores changes without extra help, and will delete the item as a result. + // Spectator mode is technically possible but may cause the item to be dropped if the client opens an inventory. + return OpenPlayer.isConnected(holder.connection) && holder.gameMode.isSurvival(); + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotCursor(container, slot, x, y); + } + + @Override + public InventoryType.SlotType getSlotType() { + // As close as possible to "not real" + return InventoryType.SlotType.OUTSIDE; + } + + public class SlotCursor extends SlotPlaceholder { + + private SlotCursor(Container container, int index, int x, int y) { + super(container, index, x, y); + } + + @Override + public ItemStack getOrDefault() { + if (!isAvailable()) { + return Placeholders.survivalOnly(holder); + } + ItemStack carried = holder.containerMenu.getCarried(); + return carried.isEmpty() ? Placeholders.cursor : carried; + } + + @Override + public boolean mayPickup(@NotNull Player player) { + return isAvailable(); + } + + @Override + public boolean mayPlace(@NotNull ItemStack itemStack) { + return isAvailable(); + } + + @Override + public boolean hasItem() { + return isAvailable() && super.hasItem(); + } + + @Override + public boolean isFake() { + return true; + } + + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentDrop.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentDrop.java new file mode 100644 index 00000000..06c102bd --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentDrop.java @@ -0,0 +1,89 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import com.github.jikoo.openinv.internal.spigot26_1.player.OpenPlayer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +/** + * A fake slot used to drop items. Unavailable offline. + */ +public class ContentDrop implements Content { + + private ServerPlayer holder; + + public ContentDrop(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public void setHolder(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public ItemStack get() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack remove() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack removePartial(int amount) { + return ItemStack.EMPTY; + } + + @Override + public void set(ItemStack itemStack) { + holder.drop(itemStack, true); + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotDrop(container, slot, x, y); + } + + @Override + public InventoryType.SlotType getSlotType() { + // Behaves like dropping an item outside the screen, just by the target player. + return InventoryType.SlotType.OUTSIDE; + } + + public class SlotDrop extends SlotPlaceholder { + + private SlotDrop(Container container, int index, int x, int y) { + super(container, index, x, y); + } + + @Override + public ItemStack getOrDefault() { + return OpenPlayer.isConnected(holder.connection) + ? Placeholders.drop + : Placeholders.blockedOffline; + } + + @Override + public boolean mayPlace(@NotNull ItemStack itemStack) { + return OpenPlayer.isConnected(holder.connection); + } + + @Override + public boolean hasItem() { + return false; + } + + @Override + public boolean isFake() { + return true; + } + + } + +} diff --git a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/slot/ContentEquipment.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentEquipment.java similarity index 91% rename from internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/slot/ContentEquipment.java rename to internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentEquipment.java index bfec218e..f55c9ce7 100644 --- a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/slot/ContentEquipment.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentEquipment.java @@ -1,13 +1,13 @@ -package com.lishid.openinv.internal.reobf.container.slot; +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; -import com.lishid.openinv.internal.reobf.container.slot.placeholder.Placeholders; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import org.bukkit.craftbukkit.v1_21_R7.CraftEquipmentSlot; -import org.bukkit.craftbukkit.v1_21_R7.inventory.CraftItemStack; +import org.bukkit.craftbukkit.CraftEquipmentSlot; +import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.PlayerInventory; import org.jetbrains.annotations.NotNull; diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentList.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentList.java new file mode 100644 index 00000000..97e1422a --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentList.java @@ -0,0 +1,58 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; + +import java.util.List; + +/** + * A normal slot backed by an item list. + */ +public abstract class ContentList implements Content { + + private final int index; + private final InventoryType.SlotType slotType; + protected List items; + + public ContentList(ServerPlayer holder, int index, InventoryType.SlotType slotType) { + this.index = index; + this.slotType = slotType; + setHolder(holder); + } + + @Override + public ItemStack get() { + return items.get(index); + } + + @Override + public ItemStack remove() { + ItemStack removed = items.remove(index); + return removed == null || removed.isEmpty() ? ItemStack.EMPTY : removed; + } + + @Override + public ItemStack removePartial(int amount) { + return ContainerHelper.removeItem(items, index, amount); + } + + @Override + public void set(ItemStack itemStack) { + items.set(index, itemStack); + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new Slot(container, slot, x, y); + } + + @Override + public InventoryType.SlotType getSlotType() { + return slotType; + } + +} diff --git a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/slot/ContentOffHand.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentOffHand.java similarity index 91% rename from internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/slot/ContentOffHand.java rename to internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentOffHand.java index 5052987a..9aebadd3 100644 --- a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/container/slot/ContentOffHand.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentOffHand.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.reobf.container.slot; +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; -import com.lishid.openinv.internal.reobf.player.OpenPlayer; +import com.github.jikoo.openinv.internal.spigot26_1.player.OpenPlayer; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentViewOnly.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentViewOnly.java new file mode 100644 index 00000000..bbce19d5 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/ContentViewOnly.java @@ -0,0 +1,56 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +/** + * A view-only slot that can't be interacted with. + */ +public class ContentViewOnly implements Content { + + protected @NotNull ServerPlayer holder; + + public ContentViewOnly(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public void setHolder(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public ItemStack get() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack remove() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack removePartial(int amount) { + return ItemStack.EMPTY; + } + + @Override + public void set(ItemStack itemStack) { + this.holder.drop(itemStack, false); + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y); + } + + @Override + public InventoryType.SlotType getSlotType() { + return InventoryType.SlotType.OUTSIDE; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotPlaceholder.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotPlaceholder.java new file mode 100644 index 00000000..d1e793c7 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotPlaceholder.java @@ -0,0 +1,20 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +/** + * An implementation of a slot as used by a menu that may have fake placeholder items. + * + *

Used to prevent plugins (particularly sorting plugins) from adding placeholders to inventories.

+ */ +public abstract class SlotPlaceholder extends Slot { + + public SlotPlaceholder(Container container, int index, int x, int y) { + super(container, index, x, y); + } + + public abstract ItemStack getOrDefault(); + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotViewOnly.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotViewOnly.java new file mode 100644 index 00000000..6c24d6ce --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/SlotViewOnly.java @@ -0,0 +1,151 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot; + +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +/** + * A view-only {@link Slot}. "Blank" by default, but can wrap another slot to display its content. + */ +public class SlotViewOnly extends SlotPlaceholder { + + public static @NotNull SlotViewOnly wrap(@NotNull Slot wrapped) { + SlotViewOnly wrapper; + if (wrapped instanceof SlotPlaceholder placeholder) { + wrapper = new SlotViewOnly(wrapped.container, wrapped.slot, wrapped.x, wrapped.y) { + @Override + public ItemStack getOrDefault() { + return placeholder.getOrDefault(); + } + }; + } else { + wrapper = new SlotViewOnly(wrapped.container, wrapped.slot, wrapped.x, wrapped.y) { + @Override + public ItemStack getOrDefault() { + return wrapped.getItem(); + } + }; + } + wrapper.index = wrapped.index; + return wrapper; + } + + public SlotViewOnly(Container container, int index, int x, int y) { + super(container, index, x, y); + } + + @Override + public ItemStack getOrDefault() { + return Placeholders.notSlot; + } + + @Override + public void onQuickCraft(@NotNull ItemStack itemStack1, @NotNull ItemStack itemStack2) { + } + + @Override + public void onTake(@NotNull Player player, @NotNull ItemStack itemStack) { + } + + @Override + public boolean mayPlace(@NotNull ItemStack itemStack) { + return false; + } + + @Override + public @NotNull ItemStack getItem() { + return ItemStack.EMPTY; + } + + @Override + public boolean hasItem() { + return false; + } + + @Override + public void setByPlayer(@NotNull ItemStack newStack) { + } + + @Override + public void setByPlayer(@NotNull ItemStack newStack, @NotNull ItemStack oldStack) { + } + + @Override + public void set(@NotNull ItemStack itemStack) { + } + + @Override + public void setChanged() { + } + + @Override + public int getMaxStackSize() { + return 0; + } + + @Override + public int getMaxStackSize(@NotNull ItemStack itemStack) { + return 0; + } + + @Override + public @NotNull ItemStack remove(int amount) { + return ItemStack.EMPTY; + } + + @Override + public boolean mayPickup(@NotNull Player player) { + return false; + } + + @Override + public boolean isActive() { + return false; + } + + @Override + public @NotNull Optional tryRemove(int var0, int var1, @NotNull Player player) { + return Optional.empty(); + } + + @Override + public @NotNull ItemStack safeTake(int var0, int var1, @NotNull Player player) { + return ItemStack.EMPTY; + } + + @Override + public @NotNull ItemStack safeInsert(@NotNull ItemStack itemStack) { + return itemStack; + } + + @Override + public @NotNull ItemStack safeInsert(@NotNull ItemStack itemStack, int amount) { + return itemStack; + } + + @Override + public boolean allowModification(@NotNull Player player) { + return false; + } + + @Override + public int getContainerSlot() { + return this.slot; + } + + @Override + public boolean isHighlightable() { + return false; + } + + @Override + public boolean isFake() { + return true; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoader.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoader.java new file mode 100644 index 00000000..c1925d78 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoader.java @@ -0,0 +1,40 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.TagParser; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomModelData; +import net.minecraft.world.item.component.DyedItemColor; +import net.minecraft.world.item.component.TooltipDisplay; +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashSet; +import java.util.List; + +public class PlaceholderLoader extends PlaceholderLoaderBase { + + private static final CustomModelData DEFAULT_CUSTOM_MODEL_DATA = new CustomModelData(List.of(), List.of(), List.of("openinv:custom"), List.of()); + private static final TooltipDisplay HIDE_TOOLTIP = new TooltipDisplay(true, new LinkedHashSet<>()); + + @Override + protected @NotNull CompoundTag parseTag(@NotNull String itemText) throws Exception { + return TagParser.parseCompoundFully(itemText); + } + + @Override + protected void addModelData(@NotNull ItemStack itemStack) { + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + } + + @Override + protected void hideTooltip(@NotNull ItemStack itemStack) { + itemStack.set(DataComponents.TOOLTIP_DISPLAY, HIDE_TOOLTIP); + } + + @Override + protected DyedItemColor getDye(int rgb) { + return new DyedItemColor(rgb); + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoaderBase.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoaderBase.java new file mode 100644 index 00000000..b16ec996 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/PlaceholderLoaderBase.java @@ -0,0 +1,180 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder; + +import com.mojang.serialization.DataResult; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.DyedItemColor; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.entity.BannerPattern; +import net.minecraft.world.level.block.entity.BannerPatternLayers; +import net.minecraft.world.level.block.entity.BannerPatterns; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.craftbukkit.CraftRegistry; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public abstract class PlaceholderLoaderBase { + + public void load(@Nullable ConfigurationSection section) throws Exception { + Placeholders.craftingOutput = parse(section, "crafting-output", defaultCraftingOutput()); + Placeholders.cursor = parse(section, "cursor", defaultCursor()); + Placeholders.drop = parse(section, "drop", defaultDrop()); + Placeholders.emptyHelmet = parse(section, "empty-helmet", getEmptyArmor(Items.LEATHER_HELMET)); + Placeholders.emptyChestplate = parse(section, "empty-chestplate", getEmptyArmor(Items.LEATHER_CHESTPLATE)); + Placeholders.emptyLeggings = parse(section, "empty-leggings", getEmptyArmor(Items.LEATHER_LEGGINGS)); + Placeholders.emptyBoots = parse(section, "empty-boots", getEmptyArmor(Items.LEATHER_BOOTS)); + Placeholders.emptyOffHand = parse(section, "empty-off-hand", defaultShield()); + Placeholders.notSlot = parse(section, "not-a-slot", defaultNotSlot()); + Placeholders.blockedOffline = parse(section, "blocked.offline", defaultBlockedOffline()); + + for (GameType type : GameType.values()) { + // Barrier: "Not available - Creative" etc. + ItemStack typeItem = new ItemStack(Items.BARRIER); + typeItem.set( + DataComponents.ITEM_NAME, + Component.translatable("options.narrator.notavailable").append(" - ").append(type.getShortDisplayName()) + ); + Placeholders.BLOCKED_GAME_TYPE.put(type, typeItem); + } + + Placeholders.BLOCKED_GAME_TYPE.put(GameType.CREATIVE, parse(section, "blocked.creative", Placeholders.BLOCKED_GAME_TYPE.get(GameType.CREATIVE))); + Placeholders.BLOCKED_GAME_TYPE.put(GameType.SPECTATOR, parse(section, "blocked.spectator", Placeholders.BLOCKED_GAME_TYPE.get(GameType.SPECTATOR))); + } + + protected @NotNull ItemStack parse( + @Nullable ConfigurationSection section, + @NotNull String path, + @NotNull ItemStack defaultStack + ) throws Exception { + if (section == null) { + return defaultStack; + } + + String itemText = section.getString(path); + + if (itemText == null) { + return defaultStack; + } + + CompoundTag compoundTag = parseTag(itemText); + DataResult parsed = ItemStack.CODEC.parse(CraftRegistry.getMinecraftRegistry().createSerializationContext(NbtOps.INSTANCE), compoundTag); + ItemStack itemStack; + try { + itemStack = parsed.getOrThrow(); + } catch (Exception e) { + itemStack = null; + } + return itemStack == null ? defaultStack : itemStack; + } + + protected abstract @NotNull CompoundTag parseTag(@NotNull String itemText) throws Exception; + + protected abstract void addModelData(@NotNull ItemStack itemStack); + + protected abstract void hideTooltip(@NotNull ItemStack itemStack); + + protected abstract DyedItemColor getDye(int rgb); + + protected @NotNull ItemStack defaultCraftingOutput() { + // Crafting table: "Crafting" + ItemStack itemStack = new ItemStack(Items.CRAFTING_TABLE); + itemStack.set(DataComponents.ITEM_NAME, Component.translatable("container.crafting")); + addModelData(itemStack); + return itemStack; + } + + protected @NotNull ItemStack defaultCursor() { + // Cursor-like banner with no tooltip + ItemStack itemStack = new ItemStack(Items.WHITE_BANNER); + RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); + Registry bannerPatterns = minecraftRegistry.lookupOrThrow(Registries.BANNER_PATTERN); + BannerPattern halfDiagBottomRight = bannerPatterns.getOrThrow(BannerPatterns.DIAGONAL_RIGHT).value(); + BannerPattern downRight = bannerPatterns.getOrThrow(BannerPatterns.STRIPE_DOWNRIGHT).value(); + BannerPattern border = bannerPatterns.getOrThrow(BannerPatterns.BORDER).value(); + itemStack.set(DataComponents.BANNER_PATTERNS, + new BannerPatternLayers(List.of( + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfDiagBottomRight), DyeColor.GRAY), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(downRight), DyeColor.WHITE), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(border), DyeColor.GRAY) + )) + ); + addModelData(itemStack); + hideTooltip(itemStack); + return itemStack; + } + + protected @NotNull ItemStack defaultDrop() { + // Dropper: "Drop Selected Item" + ItemStack itemStack = new ItemStack(Items.DROPPER); + // Note: translatable component, not keybind component! We want the text identifying the keybind, not the key. + itemStack.set(DataComponents.ITEM_NAME, Component.translatable("key.drop")); + addModelData(itemStack); + return itemStack; + } + + protected @NotNull ItemStack getEmptyArmor(@NotNull ItemLike item) { + // Inventory-background-grey-ish leather armor with no tooltip + ItemStack itemStack = new ItemStack(item); + DyedItemColor color = getDye(0xC8C8C8); + itemStack.set(DataComponents.DYED_COLOR, color); + hideTooltip(itemStack); + addModelData(itemStack); + return itemStack; + } + + protected @NotNull ItemStack defaultShield() { + // Shield with "missing texture" pattern, magenta and black squares. + ItemStack itemStack = new ItemStack(Items.SHIELD); + itemStack.set(DataComponents.BASE_COLOR, DyeColor.MAGENTA); + RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); + Registry bannerPatterns = minecraftRegistry.lookupOrThrow(Registries.BANNER_PATTERN); + BannerPattern halfLeft = bannerPatterns.getOrThrow(BannerPatterns.HALF_VERTICAL).value(); + BannerPattern topLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_LEFT).value(); + BannerPattern topRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_RIGHT).value(); + BannerPattern bottomLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_LEFT).value(); + BannerPattern bottomRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_RIGHT).value(); + itemStack.set(DataComponents.BANNER_PATTERNS, + new BannerPatternLayers(List.of( + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfLeft), DyeColor.BLACK), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topLeft), DyeColor.MAGENTA), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomLeft), DyeColor.MAGENTA), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topRight), DyeColor.BLACK), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomRight), DyeColor.BLACK) + )) + ); + hideTooltip(itemStack); + addModelData(itemStack); + return itemStack; + } + + protected @NotNull ItemStack defaultNotSlot() { + // White pane with no tooltip + ItemStack itemStack = new ItemStack(Items.WHITE_STAINED_GLASS_PANE); + hideTooltip(itemStack); + addModelData(itemStack); + return itemStack; + } + + protected @NotNull ItemStack defaultBlockedOffline() { + // Barrier: "Not available - Offline" + ItemStack itemStack = new ItemStack(Items.BARRIER); + itemStack.set(DataComponents.ITEM_NAME, + Component.translatable("options.narrator.notavailable") + .append(Component.literal(" - ")) + .append(Component.translatable("gui.socialInteractions.status_offline")) + ); + return itemStack; + } + +} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/Placeholders.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/Placeholders.java new file mode 100644 index 00000000..30308d92 --- /dev/null +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/slot/placeholder/Placeholders.java @@ -0,0 +1,37 @@ +package com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder; + +import com.github.jikoo.openinv.internal.spigot26_1.player.OpenPlayer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; + +public final class Placeholders { + + static final @NotNull EnumMap BLOCKED_GAME_TYPE = new EnumMap<>(GameType.class); + public static @NotNull ItemStack craftingOutput = ItemStack.EMPTY; + public static @NotNull ItemStack cursor = ItemStack.EMPTY; + public static @NotNull ItemStack drop = ItemStack.EMPTY; + public static @NotNull ItemStack emptyHelmet = ItemStack.EMPTY; + public static @NotNull ItemStack emptyChestplate = ItemStack.EMPTY; + public static @NotNull ItemStack emptyLeggings = ItemStack.EMPTY; + public static @NotNull ItemStack emptyBoots = ItemStack.EMPTY; + public static @NotNull ItemStack emptyOffHand = ItemStack.EMPTY; + public static @NotNull ItemStack notSlot = ItemStack.EMPTY; + public static @NotNull ItemStack blockedOffline = ItemStack.EMPTY; + + public static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) { + if (!OpenPlayer.isConnected(serverPlayer.connection)) { + return blockedOffline; + } + + return BLOCKED_GAME_TYPE.getOrDefault(serverPlayer.gameMode.getGameModeForPlayer(), ItemStack.EMPTY); + } + + private Placeholders() { + throw new IllegalStateException("Cannot create instance of utility class."); + } + +} diff --git a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/player/OpenPlayer.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/OpenPlayer.java similarity index 97% rename from internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/player/OpenPlayer.java rename to internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/OpenPlayer.java index 33c630ac..cae26f4a 100644 --- a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/player/OpenPlayer.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/OpenPlayer.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.reobf.player; +package com.github.jikoo.openinv.internal.spigot26_1.player; import com.lishid.openinv.event.OpenEvents; import com.mojang.logging.LogUtils; @@ -13,8 +13,8 @@ import net.minecraft.world.level.storage.PlayerDataStorage; import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.level.storage.ValueOutput; -import org.bukkit.craftbukkit.v1_21_R7.CraftServer; -import org.bukkit.craftbukkit.v1_21_R7.entity.CraftPlayer; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftPlayer; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/player/PlayerManager.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java similarity index 94% rename from internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/player/PlayerManager.java rename to internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java index d619f847..916ec14a 100644 --- a/internal/spigot/src/main/java/com/lishid/openinv/internal/reobf/player/PlayerManager.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java @@ -1,9 +1,9 @@ -package com.lishid.openinv.internal.reobf.player; +package com.github.jikoo.openinv.internal.spigot26_1.player; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.reobf.container.OpenEnderChest; -import com.lishid.openinv.internal.reobf.container.OpenInventory; -import com.lishid.openinv.internal.reobf.container.menu.OpenChestMenu; import com.lishid.openinv.util.JulLoggerAdapter; import com.mojang.authlib.GameProfile; import net.minecraft.nbt.CompoundTag; @@ -24,9 +24,9 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.Server; -import org.bukkit.craftbukkit.v1_21_R7.CraftServer; -import org.bukkit.craftbukkit.v1_21_R7.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_21_R7.event.CraftEventFactory; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.entity.Player; import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; diff --git a/jitpack.yml b/jitpack.yml index 4130c60e..db0815ca 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,6 +1,6 @@ before_install: - sdk update - - sdk install java 21-tem - - sdk use java 21-tem + - sdk install java 25-tem + - sdk use java 25-tem install: - ./gradlew -Djitpack=true :openinvapi:publishJitpackPublicationToMavenLocal diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 12c3faac..128f5abd 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -1,5 +1,3 @@ -import com.github.jikoo.openinv.SpigotReobf - plugins { `openinv-base` alias(libs.plugins.shadow) @@ -19,7 +17,9 @@ dependencies { implementation(project(":openinvadapterpaper1_21_4")) implementation(project(":openinvadapterpaper1_21_3")) implementation(project(":openinvadapterpaper1_21_1")) - implementation(project(":openinvadapterspigot", configuration = SpigotReobf.ARTIFACT_CONFIG)) + implementation(project(":openinvadapterspigot")) { + isTransitive = false + } implementation(libs.planarwrappers) implementation(libs.folia.scheduler.wrapper) compileOnly(libs.sqlite.jdbc) diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index f5d77139..b0828f3e 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -64,6 +64,15 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { } private @Nullable Accessor getAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { + // TODO reorganize internals, version handling + if (!PAPER) { + if (BukkitVersions.MINECRAFT.equals(Version.of(26, 1))) { + // Load Spigot accessor. + return new com.github.jikoo.openinv.internal.spigot26_1.InternalAccessor(logger, lang); + } + return null; + } + Version maxSupported = Version.of(1, 21, 11); Version minSupported = Version.of(1, 21, 1); @@ -72,17 +81,6 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { return null; } - // Load Spigot accessor. - if (!PAPER) { - if (BukkitVersions.MINECRAFT.equals(maxSupported)) { - // Current Spigot, remapped internals are available. - return new com.lishid.openinv.internal.reobf.InternalAccessor(logger, lang); - } else { - // Older Spigot; unsupported. - return null; - } - } - // Paper or a Paper fork, can use Mojang-mapped internals. if (BukkitVersions.MINECRAFT.equals(maxSupported)) { // 1.21.11 return new com.lishid.openinv.internal.common.InternalAccessor(logger, lang); @@ -212,6 +210,9 @@ private String getSpigotReleaseLink() { if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 10))) { return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.15"; } + if (BukkitVersions.MINECRAFT.lessThan(Version.of(26, 1))) { + return "https://github.com/Jikoo/OpenInv/releases/tag/5.3.0"; + } return "https://github.com/Jikoo/OpenInv/releases"; } From 68765ac606f4adae781720ed6d9ba5e6c4213a3a Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 27 Mar 2026 10:34:43 -0400 Subject: [PATCH 02/18] Move Spigot install location --- .github/workflows/ci.yml | 11 ----------- .../kotlin/com/github/jikoo/openinv/SpigotSetup.kt | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3014bdd..140aa052 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,17 +22,6 @@ jobs: distribution: 'temurin' java-version: '25' - # We can't use 'maven' prebuilt cache setup because it requires that the project have a pom file. - # BuildTools installs to Maven local if available, so it's easier to just rely on that. - - name: Cache Spigot dependency - uses: actions/cache@v5 - with: - path: | - ~/.m2/repository/org/spigotmc/ - key: ${{ runner.os }}-buildtools-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-buildtools- - - uses: gradle/actions/setup-gradle@v5 - name: Build with Gradle diff --git a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt index 37698726..1f41c3c8 100644 --- a/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt +++ b/buildSrc/src/main/kotlin/com/github/jikoo/openinv/SpigotSetup.kt @@ -31,7 +31,7 @@ abstract class SpigotSetup : Plugin { // Install Spigot with BuildTools. val spigot: File = target.providers.of(BuildToolsValueSource::class.java) { parameters { - installDir.set(target.layout.buildDirectory.dir("tmp/spigot")) + installDir.set(target.gradle.gradleUserHomeDir.resolve("caches/spigot")) workingDir.set(target.layout.buildDirectory.dir("tmp/buildtools")) spigotVersion.set(spigotExt.version) spigotRevision.set(spigotExt.revision) From 2160df1fb79090a30c1fe6d8c9f00c3c3a21176f Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 27 Mar 2026 17:00:39 -0400 Subject: [PATCH 03/18] Drop unnecessary intermediary class --- .../internal/spigot26_1/InternalAccessor.java | 2 +- .../container/BaseOpenInventory.java | 335 ------------------ .../spigot26_1/container/OpenInventory.java | 326 ++++++++++++++++- .../container/bukkit/OpenPlayerInventory.java | 8 +- .../bukkit/OpenPlayerInventorySelf.java | 4 +- .../container/menu/OpenInventoryMenu.java | 10 +- .../spigot26_1/player/PlayerManager.java | 2 +- 7 files changed, 334 insertions(+), 353 deletions(-) delete mode 100644 internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java index 7ac4bd1f..3a657c3e 100644 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/InternalAccessor.java @@ -1,8 +1,8 @@ package com.github.jikoo.openinv.internal.spigot26_1; import com.github.jikoo.openinv.internal.spigot26_1.container.AnySilentContainer; -import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.PlaceholderLoader; import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; import com.lishid.openinv.internal.Accessor; diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java deleted file mode 100644 index f513bdb5..00000000 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/BaseOpenInventory.java +++ /dev/null @@ -1,335 +0,0 @@ -package com.github.jikoo.openinv.internal.spigot26_1.container; - -import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenPlayerInventory; -import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; -import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenInventoryMenu; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.Content; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCrafting; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCraftingResult; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCursor; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentDrop; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentEquipment; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentList; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentOffHand; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentViewOnly; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.SlotViewOnly; -import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; -import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; -import com.lishid.openinv.internal.ISpecialPlayerInventory; -import com.lishid.openinv.internal.InternalOwned; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.core.NonNullList; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.Location; -import org.bukkit.craftbukkit.entity.CraftHumanEntity; -import org.bukkit.craftbukkit.inventory.CraftInventory; -import org.bukkit.entity.HumanEntity; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -public abstract class BaseOpenInventory implements Container, InternalOwned, ISpecialPlayerInventory { - - protected final List slots; - private final int size; - protected ServerPlayer owner; - private int maxStackSize = 99; - protected CraftInventory bukkitEntity; - public List transaction = new ArrayList<>(); - - public BaseOpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) { - owner = PlayerManager.getHandle(bukkitPlayer); - - // Get total size, rounding up to nearest 9 for client compatibility. - int rawSize = owner.getInventory().getContainerSize() + owner.inventoryMenu.getCraftSlots().getContainerSize() + 1; - size = ((int) Math.ceil(rawSize / 9.0)) * 9; - - slots = NonNullList.withSize(size, new ContentViewOnly(owner)); - setupSlots(); - } - - protected void setupSlots() { - // Top of inventory: Regular contents. - int nextIndex = addMainInventory(); - - // If inventory is expected size, we can arrange slots to be pretty. - Inventory ownerInv = owner.getInventory(); - if (ownerInv.getNonEquipmentItems().size() == 36 - && owner.inventoryMenu.getCraftSlots().getContainerSize() == 4 - && (Inventory.EQUIPMENT_SLOT_MAPPING.size() == 5 || Inventory.EQUIPMENT_SLOT_MAPPING.size() == 7)) { - // Armor slots: Bottom left. - addArmor(36); - // Off-hand: Below chestplate. - addOffHand(46); - // Drop slot: Bottom right. - slots.set(53, new ContentDrop(owner)); - // Cursor slot: Above drop. - slots.set(44, new ContentCursor(owner)); - - // Crafting is displayed in the bottom right corner. - // As we're using the pretty view, this is a 3x2. - addCrafting(41, true); - return; - } - - // Otherwise we'll just add elements linearly. - nextIndex = addArmor(nextIndex); - nextIndex = addOffHand(nextIndex); - nextIndex = addCrafting(nextIndex, false); - slots.set(nextIndex, new ContentCursor(owner)); - // Drop slot last. - slots.set(slots.size() - 1, new ContentDrop(owner)); - } - - private int addMainInventory() { - int listSize = owner.getInventory().getNonEquipmentItems().size(); - // Hotbar slots are 0-8. We want those to appear on the bottom of the inventory like a normal player inventory, - // so everything else needs to move up a row. - int hotbarDiff = listSize - 9; - for (int localIndex = 0; localIndex < listSize; ++localIndex) { - InventoryType.SlotType type; - int invIndex; - if (localIndex < hotbarDiff) { - invIndex = localIndex + 9; - type = InventoryType.SlotType.CONTAINER; - } else { - type = InventoryType.SlotType.QUICKBAR; - invIndex = localIndex - hotbarDiff; - } - - slots.set( - localIndex, - new ContentList(owner, invIndex, type) { - @Override - public void setHolder(@NotNull ServerPlayer holder) { - items = holder.getInventory().getNonEquipmentItems(); - } - } - ); - } - return listSize; - } - - private int addArmor(int startIndex) { - // Armor slots go bottom to top; boots are first and helmet is last. - // Since we have to display horizontally due to space restrictions, - // making the left side the "top" is more user-friendly. - EquipmentSlot[] sorted = Inventory.EQUIPMENT_SLOT_MAPPING.int2ObjectEntrySet() - .stream() - .sorted(Comparator.comparingInt(Int2ObjectMap.Entry::getIntKey)) - .map(Map.Entry::getValue) - .toArray(EquipmentSlot[]::new); - int localIndex = 0; - for (int i = sorted.length - 1; i >= 0; --i) { - // Skip off-hand, handled separately. Also skip non-player slots. - if (sorted[i].getType() != EquipmentSlot.Type.HUMANOID_ARMOR) { - continue; - } - - slots.set(startIndex + localIndex, new ContentEquipment(owner, sorted[i])); - ++localIndex; - } - - return startIndex + localIndex; - } - - private int addOffHand(int startIndex) { - // No off-hand? - if (!Inventory.EQUIPMENT_SLOT_MAPPING.containsValue(EquipmentSlot.OFFHAND)) { - return startIndex; - } - - slots.set(startIndex, new ContentOffHand(owner)); - return startIndex + 1; - } - - private int addCrafting(int startIndex, boolean pretty) { - int listSize = owner.inventoryMenu.getCraftSlots().getContents().size(); - pretty &= listSize == 4; - - for (int localIndex = 0; localIndex < listSize; ++localIndex) { - // Pretty display is a 2x2 rather than linear. - // If index is in top row, grid is not 2x2, or pretty is disabled, just use current index. - // Otherwise, subtract 2 and add 9 to start in the same position on the next row. - int modIndex = startIndex + (localIndex < 2 || !pretty ? localIndex : localIndex + 7); - - slots.set(modIndex, new ContentCrafting(owner, localIndex)); - } - - if (pretty) { - slots.set(startIndex + 2, new ContentViewOnly(owner) { - @Override - public Slot asSlot(Container container, int slot, int x, int y) { - return new SlotViewOnly(container, slot, x, y) { - @Override - public ItemStack getOrDefault() { - return Placeholders.craftingOutput; - } - }; - } - } - ); - slots.set(startIndex + 11, getCraftingResult(owner)); - } - - return startIndex + listSize; - } - - protected Content getCraftingResult(@NotNull ServerPlayer serverPlayer) { - return new ContentCraftingResult(serverPlayer); - } - - public Slot getMenuSlot(int index, int x, int y) { - return slots.get(index).asSlot(this, index, x, y); - } - - public InventoryType.SlotType getSlotType(int index) { - return slots.get(index).getSlotType(); - } - - public abstract Component getTitle(ServerPlayer player, @Nullable OpenChestMenu menu); - - @Override - public ServerPlayer getOwnerHandle() { - return owner; - } - - @Override - public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { - if (bukkitEntity == null) { - bukkitEntity = new OpenPlayerInventory(this); - } - return bukkitEntity; - } - - @Override - public void setPlayerOnline(@NotNull org.bukkit.entity.Player player) { - ServerPlayer newOwner = PlayerManager.getHandle(player); - // Only transfer regular inventory - crafting and cursor slots are transient. - newOwner.getInventory().replaceWith(owner.getInventory()); - owner = newOwner; - // Update slots to point to new inventory. - slots.forEach(slot -> slot.setHolder(newOwner)); - } - - @Override - public boolean isInUse() { - return !transaction.isEmpty(); - } - - @Override - public @NotNull org.bukkit.entity.Player getPlayer() { - return getOwner(); - } - - @Override - public int getContainerSize() { - return size; - } - - @Override - public boolean isEmpty() { - return slots.stream().map(Content::get).allMatch(ItemStack::isEmpty); - } - - @Override - public @NotNull ItemStack getItem(int index) { - return slots.get(index).get(); - } - - @Override - public @NotNull ItemStack removeItem(int index, int amount) { - return slots.get(index).removePartial(amount); - } - - @Override - public @NotNull ItemStack removeItemNoUpdate(int index) { - return slots.get(index).remove(); - } - - @Override - public void setItem(int index, @NotNull ItemStack itemStack) { - slots.get(index).set(itemStack); - } - - @Override - public int getMaxStackSize() { - return maxStackSize; - } - - @Override - public void setMaxStackSize(int maxStackSize) { - this.maxStackSize = maxStackSize; - } - - @Override - public void setChanged() { - } - - @Override - public boolean stillValid(@NotNull Player player) { - return true; - } - - @Override - public @NotNull List getContents() { - NonNullList contents = NonNullList.withSize(getContainerSize(), ItemStack.EMPTY); - for (int i = 0; i < getContainerSize(); ++i) { - contents.set(i, getItem(i)); - } - return contents; - } - - @Override - public void onOpen(@NotNull CraftHumanEntity viewer) { - transaction.add(viewer); - } - - @Override - public void onClose(@NotNull CraftHumanEntity viewer) { - transaction.remove(viewer); - } - - @Override - public @NotNull List getViewers() { - return transaction; - } - - @Override - public @NotNull org.bukkit.entity.Player getOwner() { - return owner.getBukkitEntity(); - } - - @Override - public @NotNull Location getLocation() { - return owner.getBukkitEntity().getLocation(); - } - - @Override - public void clearContent() { - owner.getInventory().clearContent(); - owner.inventoryMenu.getCraftSlots().clearContent(); - owner.inventoryMenu.slotsChanged(owner.inventoryMenu.getCraftSlots()); - owner.containerMenu.setCarried(ItemStack.EMPTY); - } - - public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { - if (player instanceof ServerPlayer serverPlayer) { - return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); - } - return null; - } - -} diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java index 3ff8dec9..8ffc5982 100644 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/OpenInventory.java @@ -1,23 +1,208 @@ package com.github.jikoo.openinv.internal.spigot26_1.container; +import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenPlayerInventory; import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; +import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenInventoryMenu; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.Content; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCrafting; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCraftingResult; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentCursor; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentDrop; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentEquipment; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentList; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentOffHand; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentViewOnly; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.SlotViewOnly; +import com.github.jikoo.openinv.internal.spigot26_1.container.slot.placeholder.Placeholders; +import com.github.jikoo.openinv.internal.spigot26_1.player.PlayerManager; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalOwned; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.minecraft.ChatFormatting; +import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FontDescription; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; -import org.bukkit.entity.Player; +import net.minecraft.world.Container; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.inventory.CraftInventory; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class OpenInventory extends BaseOpenInventory { +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; - public OpenInventory(@NotNull Player bukkitPlayer) { - super(bukkitPlayer); +public class OpenInventory implements Container, InternalOwned, ISpecialPlayerInventory { + + protected final List slots; + private final int size; + protected ServerPlayer owner; + private int maxStackSize = 99; + protected CraftInventory bukkitEntity; + public List transaction = new ArrayList<>(); + + public OpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) { + owner = PlayerManager.getHandle(bukkitPlayer); + + // Get total size, rounding up to nearest 9 for client compatibility. + int rawSize = owner.getInventory().getContainerSize() + owner.inventoryMenu.getCraftSlots().getContainerSize() + 1; + size = ((int) Math.ceil(rawSize / 9.0)) * 9; + + slots = NonNullList.withSize(size, new ContentViewOnly(owner)); + setupSlots(); + } + + protected void setupSlots() { + // Top of inventory: Regular contents. + int nextIndex = addMainInventory(); + + // If inventory is expected size, we can arrange slots to be pretty. + Inventory ownerInv = owner.getInventory(); + if (ownerInv.getNonEquipmentItems().size() == 36 + && owner.inventoryMenu.getCraftSlots().getContainerSize() == 4 + && (Inventory.EQUIPMENT_SLOT_MAPPING.size() == 5 || Inventory.EQUIPMENT_SLOT_MAPPING.size() == 7)) { + // Armor slots: Bottom left. + addArmor(36); + // Off-hand: Below chestplate. + addOffHand(46); + // Drop slot: Bottom right. + slots.set(53, new ContentDrop(owner)); + // Cursor slot: Above drop. + slots.set(44, new ContentCursor(owner)); + + // Crafting is displayed in the bottom right corner. + // As we're using the pretty view, this is a 3x2. + addCrafting(41, true); + return; + } + + // Otherwise we'll just add elements linearly. + nextIndex = addArmor(nextIndex); + nextIndex = addOffHand(nextIndex); + nextIndex = addCrafting(nextIndex, false); + slots.set(nextIndex, new ContentCursor(owner)); + // Drop slot last. + slots.set(slots.size() - 1, new ContentDrop(owner)); + } + + private int addMainInventory() { + int listSize = owner.getInventory().getNonEquipmentItems().size(); + // Hotbar slots are 0-8. We want those to appear on the bottom of the inventory like a normal player inventory, + // so everything else needs to move up a row. + int hotbarDiff = listSize - 9; + for (int localIndex = 0; localIndex < listSize; ++localIndex) { + InventoryType.SlotType type; + int invIndex; + if (localIndex < hotbarDiff) { + invIndex = localIndex + 9; + type = InventoryType.SlotType.CONTAINER; + } else { + type = InventoryType.SlotType.QUICKBAR; + invIndex = localIndex - hotbarDiff; + } + + slots.set( + localIndex, + new ContentList(owner, invIndex, type) { + @Override + public void setHolder(@NotNull ServerPlayer holder) { + items = holder.getInventory().getNonEquipmentItems(); + } + } + ); + } + return listSize; + } + + private int addArmor(int startIndex) { + // Armor slots go bottom to top; boots are first and helmet is last. + // Since we have to display horizontally due to space restrictions, + // making the left side the "top" is more user-friendly. + EquipmentSlot[] sorted = Inventory.EQUIPMENT_SLOT_MAPPING.int2ObjectEntrySet() + .stream() + .sorted(Comparator.comparingInt(Int2ObjectMap.Entry::getIntKey)) + .map(Map.Entry::getValue) + .toArray(EquipmentSlot[]::new); + int localIndex = 0; + for (int i = sorted.length - 1; i >= 0; --i) { + // Skip off-hand, handled separately. Also skip non-player slots. + if (sorted[i].getType() != EquipmentSlot.Type.HUMANOID_ARMOR) { + continue; + } + + slots.set(startIndex + localIndex, new ContentEquipment(owner, sorted[i])); + ++localIndex; + } + + return startIndex + localIndex; + } + + private int addOffHand(int startIndex) { + // No off-hand? + if (!Inventory.EQUIPMENT_SLOT_MAPPING.containsValue(EquipmentSlot.OFFHAND)) { + return startIndex; + } + + slots.set(startIndex, new ContentOffHand(owner)); + return startIndex + 1; + } + + private int addCrafting(int startIndex, boolean pretty) { + int listSize = owner.inventoryMenu.getCraftSlots().getContents().size(); + pretty &= listSize == 4; + + for (int localIndex = 0; localIndex < listSize; ++localIndex) { + // Pretty display is a 2x2 rather than linear. + // If index is in top row, grid is not 2x2, or pretty is disabled, just use current index. + // Otherwise, subtract 2 and add 9 to start in the same position on the next row. + int modIndex = startIndex + (localIndex < 2 || !pretty ? localIndex : localIndex + 7); + + slots.set(modIndex, new ContentCrafting(owner, localIndex)); + } + + if (pretty) { + slots.set(startIndex + 2, new ContentViewOnly(owner) { + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y) { + @Override + public ItemStack getOrDefault() { + return Placeholders.craftingOutput; + } + }; + } + } + ); + slots.set(startIndex + 11, getCraftingResult(owner)); + } + + return startIndex + listSize; + } + + protected Content getCraftingResult(@NotNull ServerPlayer serverPlayer) { + return new ContentCraftingResult(serverPlayer); + } + + public Slot getMenuSlot(int index, int x, int y) { + return slots.get(index).asSlot(this, index, x, y); + } + + public InventoryType.SlotType getSlotType(int index) { + return slots.get(index).getSlotType(); } - @Override public @NotNull Component getTitle(@Nullable ServerPlayer viewer, @Nullable OpenChestMenu menu) { MutableComponent component = Component.empty(); // Prefix for use with custom bitmap image fonts. @@ -46,4 +231,135 @@ public OpenInventory(@NotNull Player bukkitPlayer) { return component; } + @Override + public ServerPlayer getOwnerHandle() { + return owner; + } + + @Override + public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { + if (bukkitEntity == null) { + bukkitEntity = new OpenPlayerInventory(this); + } + return bukkitEntity; + } + + @Override + public void setPlayerOnline(@NotNull org.bukkit.entity.Player player) { + ServerPlayer newOwner = PlayerManager.getHandle(player); + // Only transfer regular inventory - crafting and cursor slots are transient. + newOwner.getInventory().replaceWith(owner.getInventory()); + owner = newOwner; + // Update slots to point to new inventory. + slots.forEach(slot -> slot.setHolder(newOwner)); + } + + @Override + public boolean isInUse() { + return !transaction.isEmpty(); + } + + @Override + public @NotNull org.bukkit.entity.Player getPlayer() { + return getOwner(); + } + + @Override + public int getContainerSize() { + return size; + } + + @Override + public boolean isEmpty() { + return slots.stream().map(Content::get).allMatch(ItemStack::isEmpty); + } + + @Override + public @NotNull ItemStack getItem(int index) { + return slots.get(index).get(); + } + + @Override + public @NotNull ItemStack removeItem(int index, int amount) { + return slots.get(index).removePartial(amount); + } + + @Override + public @NotNull ItemStack removeItemNoUpdate(int index) { + return slots.get(index).remove(); + } + + @Override + public void setItem(int index, @NotNull ItemStack itemStack) { + slots.get(index).set(itemStack); + } + + @Override + public int getMaxStackSize() { + return maxStackSize; + } + + @Override + public void setMaxStackSize(int maxStackSize) { + this.maxStackSize = maxStackSize; + } + + @Override + public void setChanged() { + } + + @Override + public boolean stillValid(@NotNull Player player) { + return true; + } + + @Override + public @NotNull List getContents() { + NonNullList contents = NonNullList.withSize(getContainerSize(), ItemStack.EMPTY); + for (int i = 0; i < getContainerSize(); ++i) { + contents.set(i, getItem(i)); + } + return contents; + } + + @Override + public void onOpen(@NotNull CraftHumanEntity viewer) { + transaction.add(viewer); + } + + @Override + public void onClose(@NotNull CraftHumanEntity viewer) { + transaction.remove(viewer); + } + + @Override + public @NotNull List getViewers() { + return transaction; + } + + @Override + public @NotNull org.bukkit.entity.Player getOwner() { + return owner.getBukkitEntity(); + } + + @Override + public @NotNull Location getLocation() { + return owner.getBukkitEntity().getLocation(); + } + + @Override + public void clearContent() { + owner.getInventory().clearContent(); + owner.inventoryMenu.getCraftSlots().clearContent(); + owner.inventoryMenu.slotsChanged(owner.inventoryMenu.getCraftSlots()); + owner.containerMenu.setCarried(ItemStack.EMPTY); + } + + public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + } diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java index 512f5258..30ebb74f 100644 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventory.java @@ -1,7 +1,7 @@ package com.github.jikoo.openinv.internal.spigot26_1.container.bukkit; import com.google.common.base.Preconditions; -import com.github.jikoo.openinv.internal.spigot26_1.container.BaseOpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; import net.minecraft.core.NonNullList; import net.minecraft.world.entity.player.Inventory; import org.bukkit.craftbukkit.inventory.CraftInventory; @@ -15,13 +15,13 @@ public class OpenPlayerInventory extends CraftInventory implements PlayerInventory { - public OpenPlayerInventory(@NotNull BaseOpenInventory inventory) { + public OpenPlayerInventory(@NotNull OpenInventory inventory) { super(inventory); } @Override - public @NotNull BaseOpenInventory getInventory() { - return (BaseOpenInventory) super.getInventory(); + public @NotNull OpenInventory getInventory() { + return (OpenInventory) super.getInventory(); } @Override diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java index 7d57a8a6..3057020f 100644 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/bukkit/OpenPlayerInventorySelf.java @@ -1,6 +1,6 @@ package com.github.jikoo.openinv.internal.spigot26_1.container.bukkit; -import com.github.jikoo.openinv.internal.spigot26_1.container.BaseOpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -8,7 +8,7 @@ public class OpenPlayerInventorySelf extends OpenPlayerInventory { private final int offset; - public OpenPlayerInventorySelf(@NotNull BaseOpenInventory inventory, int offset) { + public OpenPlayerInventorySelf(@NotNull OpenInventory inventory, int offset) { super(inventory); this.offset = offset; } diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java index b8e69195..735d4e3d 100644 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/container/menu/OpenInventoryMenu.java @@ -2,7 +2,7 @@ import com.google.common.base.Preconditions; import com.lishid.openinv.util.Permissions; -import com.github.jikoo.openinv.internal.spigot26_1.container.BaseOpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenDummyPlayerInventory; import com.github.jikoo.openinv.internal.spigot26_1.container.bukkit.OpenPlayerInventorySelf; import com.github.jikoo.openinv.internal.spigot26_1.container.slot.ContentDrop; @@ -23,15 +23,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class OpenInventoryMenu extends OpenSyncMenu { +public class OpenInventoryMenu extends OpenSyncMenu { private int offset; - public OpenInventoryMenu(BaseOpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { + public OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { super(getMenuType(inventory, viewer), i, inventory, viewer, viewOnly); } - private static MenuType getMenuType(BaseOpenInventory inventory, ServerPlayer viewer) { + private static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { int size = inventory.getContainerSize(); // Disallow duplicate access to own main inventory contents. if (inventory.getOwnerHandle().equals(viewer)) { @@ -99,7 +99,7 @@ protected void preSlotSetup() { } @Override - protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { + protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { Inventory bukkitInventory; if (viewOnly) { bukkitInventory = new OpenDummyPlayerInventory(container); diff --git a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java index 916ec14a..79196390 100644 --- a/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java +++ b/internal/spigot/src/main/java/com/github/jikoo/openinv/internal/spigot26_1/player/PlayerManager.java @@ -1,7 +1,7 @@ package com.github.jikoo.openinv.internal.spigot26_1.player; -import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; import com.github.jikoo.openinv.internal.spigot26_1.container.OpenInventory; +import com.github.jikoo.openinv.internal.spigot26_1.container.OpenEnderChest; import com.github.jikoo.openinv.internal.spigot26_1.container.menu.OpenChestMenu; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.util.JulLoggerAdapter; From 89f3d2f9766c1a590773438198df15fa97c95991 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Sat, 4 Apr 2026 15:37:21 -0400 Subject: [PATCH 04/18] Force Paper 26.1.1 to (try to) compile --- addon/togglepersist/build.gradle.kts | 14 +++- api/build.gradle.kts | 18 ++++- build.gradle.kts | 31 ++++++-- buildSrc/build.gradle.kts | 5 -- buildSrc/settings.gradle.kts | 7 -- .../src/main/kotlin/openinv-base.gradle.kts | 31 -------- common/build.gradle.kts | 16 +++- gradle/libs.versions.toml | 5 +- internal/common/build.gradle.kts | 78 +++++++++++++------ internal/paper1_21_1/build.gradle.kts | 27 +++---- internal/paper1_21_10/build.gradle.kts | 27 +++---- internal/paper1_21_3/build.gradle.kts | 27 +++---- internal/paper1_21_4/build.gradle.kts | 27 +++---- internal/paper1_21_5/build.gradle.kts | 27 +++---- internal/paper1_21_8/build.gradle.kts | 27 +++---- internal/spigot/build.gradle.kts | 25 +++--- plugin/build.gradle.kts | 15 +++- 17 files changed, 218 insertions(+), 189 deletions(-) delete mode 100644 buildSrc/src/main/kotlin/openinv-base.gradle.kts diff --git a/addon/togglepersist/build.gradle.kts b/addon/togglepersist/build.gradle.kts index 78cb9095..2a0e693d 100644 --- a/addon/togglepersist/build.gradle.kts +++ b/addon/togglepersist/build.gradle.kts @@ -1,11 +1,21 @@ -plugins { - `openinv-base` +repositories { + mavenCentral() + maven("https://hub.spigotmc.org/nexus/content/groups/public/") } dependencies { + compileOnly(libs.spigotapi) implementation(project(":openinvapi")) } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 +} + tasks.processResources { expand("version" to version) } diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 9b2665ad..1952885b 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -1,8 +1,24 @@ plugins { - `openinv-base` `maven-publish` } +repositories { + mavenCentral() + maven("https://hub.spigotmc.org/nexus/content/groups/public/") +} + +dependencies { + compileOnly(libs.spigotapi) +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 +} + publishing { publications { create("jitpack") { diff --git a/build.gradle.kts b/build.gradle.kts index 2aa1d9f4..3bc4ac7b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,21 +2,40 @@ plugins { `java-library` alias(libs.plugins.paperweight) apply false alias(libs.plugins.shadow) apply false - id(libs.plugins.errorprone.gradle.get().pluginId) apply false + alias(libs.plugins.errorprone.gradle) } -// Set by Spigot module, used by Paper module to convert to Spigot's version of Mojang mappings. -project.ext.set("craftbukkitPackage", "UNKNOWN") - repositories { maven("https://repo.papermc.io/repository/maven-public/") } // Allow submodules to target higher Java release versions. -// Not currently necessary (as lowest supported version is in the 1.21 range) -// but may become relevant in the future. java.disableAutoTargetJvm() +subprojects { + apply(plugin = "java-library") + apply(plugin = rootProject.libs.plugins.errorprone.gradle.get().pluginId) + + repositories { + mavenCentral() + } + + dependencies { + compileOnly(rootProject.libs.jspecify) + compileOnly(rootProject.libs.annotations) + errorprone(rootProject.libs.errorprone.core) + } + + tasks { + withType().configureEach { + options.encoding = Charsets.UTF_8.name() + } + withType().configureEach { + options.encoding = Charsets.UTF_8.name() + } + } +} + // Task to delete ./dist where final files are output. tasks.register("cleanDist") { delete("dist") diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 08bf5248..b98aa01c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -6,8 +6,3 @@ repositories { gradlePluginPortal() mavenCentral() } - -dependencies { - val libs = project.extensions.getByType(VersionCatalogsExtension::class.java).named("libs") - implementation(libs.findLibrary("errorprone-gradle").orElseThrow()) -} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 215a5d58..e69de29b 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -1,7 +0,0 @@ -dependencyResolutionManagement { - versionCatalogs { - create("libs") { - from(files("../gradle/libs.versions.toml")) - } - } -} diff --git a/buildSrc/src/main/kotlin/openinv-base.gradle.kts b/buildSrc/src/main/kotlin/openinv-base.gradle.kts deleted file mode 100644 index be1979a3..00000000 --- a/buildSrc/src/main/kotlin/openinv-base.gradle.kts +++ /dev/null @@ -1,31 +0,0 @@ -plugins { - `java-library` - id("net.ltgt.errorprone") -} - -java { - toolchain.languageVersion = JavaLanguageVersion.of(21) -} - -repositories { - mavenCentral() - maven("https://repo.papermc.io/repository/maven-public/") - maven("https://hub.spigotmc.org/nexus/content/groups/public/") -} - -dependencies { - val libs = versionCatalogs.named("libs") - compileOnly(libs.findLibrary("annotations").orElseThrow()) - compileOnly(libs.findLibrary("spigotapi").orElseThrow()) - errorprone(libs.findLibrary("errorprone-core").orElseThrow()) -} - -tasks { - withType().configureEach { - options.release = 21 - options.encoding = Charsets.UTF_8.name() - } - withType().configureEach { - options.encoding = Charsets.UTF_8.name() - } -} diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 3321bb0e..945d7a8e 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,5 +1,17 @@ -plugins { - `openinv-base` +repositories { + maven("https://hub.spigotmc.org/nexus/content/groups/public/") +} + +dependencies { + compileOnly(libs.spigotapi) +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 572b1fc6..2748373f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,9 @@ [versions] spigotapi = "1.21.5-R0.1-SNAPSHOT" planarwrappers = "3.3.0" +jspecify = "1.0.0" annotations = "26.1.0" -paperweight = "2.0.0-beta.17" +paperweight = "2.0.0-beta.21" shadow = "9.3.2" folia-scheduler-wrapper = "v0.0.3" errorprone-core = "2.48.0" @@ -13,10 +14,10 @@ sqlite-jdbc = "3.49.1.0" [libraries] spigotapi = { module = "org.spigotmc:spigot-api", version.ref = "spigotapi" } planarwrappers = { module = "com.github.jikoo:planarwrappers", version.ref = "planarwrappers" } +jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" } annotations = { module = "org.jetbrains:annotations", version.ref = "annotations" } folia-scheduler-wrapper = { module = "com.github.NahuLD.folia-scheduler-wrapper:folia-scheduler-wrapper", version.ref = "folia-scheduler-wrapper" } errorprone-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorprone-core" } -errorprone-gradle = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorprone-gradle" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite-jdbc" } diff --git a/internal/common/build.gradle.kts b/internal/common/build.gradle.kts index e94b4ea3..85399da2 100644 --- a/internal/common/build.gradle.kts +++ b/internal/common/build.gradle.kts @@ -1,35 +1,67 @@ +import org.gradle.api.internal.attributes.DefaultCompatibilityRuleChain + plugins { - `openinv-base` alias(libs.plugins.paperweight) } -//tasks { -// withType { -// // OpenPlayer unchecked warning is due to superclass' messy inheritance and legacy methods. -// options.compilerArgs.add("-Xlint:unchecked") -// // PlayerManager uses "deprecated" method matching vanilla to support legacy save data. -// // While vanilla still feels that it is appropriate to use in the load process, we will too. -// options.compilerArgs.add("-Xlint:deprecation") -// } -//} - -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } +repositories { + maven("https://repo.papermc.io/repository/maven-public/") +} + +java { + toolchain.languageVersion.set(JavaLanguageVersion.of(25)) +} + +tasks.withType().configureEach { + options.release = 21 +} + +class ToolchainJvmVersion: AttributeCompatibilityRule { + override fun execute(details: CompatibilityCheckDetails) { + if (details.consumerValue == details.producerValue) { + return } - if (paper != null) { - select(paper) + if (details.consumerValue == null) { + details.incompatible() + return + } + if (25 >= details.producerValue!!) { + details.compatible() + } else { + details.incompatible() } - because("module is written for Paper servers") } } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + attributesSchema { + attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE) { + // Gradle thinks that depending on a library with a certain language level requires + // any project that depends on it to also require that language level no matter what. + // This is a bit obnoxious when we're specifically adding compatiblity patches to shared common code. + // Realistically Gradle is correct and the chain should be reversed - the oldest, least common + // denominator should be targeted and patches should be slapped on top as necessary. + // However, I don't want to spend a week restructuring the project to cut a release. + // Hack out Gradle's rules and replace them with our own less-restrictive version. + val rules = compatibilityRules as DefaultCompatibilityRuleChain + rules.rules.clear() - paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") + compatibilityRules.add(ToolchainJvmVersion::class.java) + } + } + + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + + paperweight.paperDevBundle("26.1.1.build.15-alpha") +} + +tasks.reobfJar { + enabled = false } + +configurations.reobf.get().outgoing.artifacts.clear() diff --git a/internal/paper1_21_1/build.gradle.kts b/internal/paper1_21_1/build.gradle.kts index 84ba9a0d..483c5268 100644 --- a/internal/paper1_21_1/build.gradle.kts +++ b/internal/paper1_21_1/build.gradle.kts @@ -1,25 +1,22 @@ plugins { - `openinv-base` alias(libs.plugins.paperweight) } -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } - } - if (paper != null) { - select(paper) - } - because("module is written for Paper servers") - } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } implementation(project(":openinvadaptercommon")) implementation(project(":openinvadapterpaper1_21_8")) implementation(project(":openinvadapterpaper1_21_5")) diff --git a/internal/paper1_21_10/build.gradle.kts b/internal/paper1_21_10/build.gradle.kts index d727317a..38949bd9 100644 --- a/internal/paper1_21_10/build.gradle.kts +++ b/internal/paper1_21_10/build.gradle.kts @@ -1,25 +1,22 @@ plugins { - `openinv-base` alias(libs.plugins.paperweight) } -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } - } - if (paper != null) { - select(paper) - } - because("module is written for Paper servers") - } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } implementation(project(":openinvadaptercommon")) paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") diff --git a/internal/paper1_21_3/build.gradle.kts b/internal/paper1_21_3/build.gradle.kts index 86fa2f13..42e1bfdb 100644 --- a/internal/paper1_21_3/build.gradle.kts +++ b/internal/paper1_21_3/build.gradle.kts @@ -1,25 +1,22 @@ plugins { - `openinv-base` alias(libs.plugins.paperweight) } -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } - } - if (paper != null) { - select(paper) - } - because("module is written for Paper servers") - } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } implementation(project(":openinvadaptercommon")) implementation(project(":openinvadapterpaper1_21_8")) implementation(project(":openinvadapterpaper1_21_5")) diff --git a/internal/paper1_21_4/build.gradle.kts b/internal/paper1_21_4/build.gradle.kts index 761ada30..3c941c3c 100644 --- a/internal/paper1_21_4/build.gradle.kts +++ b/internal/paper1_21_4/build.gradle.kts @@ -1,25 +1,22 @@ plugins { - `openinv-base` alias(libs.plugins.paperweight) } -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } - } - if (paper != null) { - select(paper) - } - because("module is written for Paper servers") - } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } implementation(project(":openinvadaptercommon")) implementation(project(":openinvadapterpaper1_21_8")) implementation(project(":openinvadapterpaper1_21_5")) diff --git a/internal/paper1_21_5/build.gradle.kts b/internal/paper1_21_5/build.gradle.kts index 2b1471c1..4c198112 100644 --- a/internal/paper1_21_5/build.gradle.kts +++ b/internal/paper1_21_5/build.gradle.kts @@ -1,25 +1,22 @@ plugins { - `openinv-base` alias(libs.plugins.paperweight) } -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } - } - if (paper != null) { - select(paper) - } - because("module is written for Paper servers") - } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } implementation(project(":openinvadaptercommon")) implementation(project(":openinvadapterpaper1_21_8")) diff --git a/internal/paper1_21_8/build.gradle.kts b/internal/paper1_21_8/build.gradle.kts index 306db103..deeebd8c 100644 --- a/internal/paper1_21_8/build.gradle.kts +++ b/internal/paper1_21_8/build.gradle.kts @@ -1,25 +1,22 @@ plugins { - `openinv-base` alias(libs.plugins.paperweight) } -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val paper = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "paper-api" - } - } - if (paper != null) { - select(paper) - } - because("module is written for Paper servers") - } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 } dependencies { - implementation(project(":openinvapi")) - implementation(project(":openinvcommon")) + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } implementation(project(":openinvadaptercommon")) paperweight.paperDevBundle("1.21.8-R0.1-SNAPSHOT") diff --git a/internal/spigot/build.gradle.kts b/internal/spigot/build.gradle.kts index ee8f8d6c..1b3cb4df 100644 --- a/internal/spigot/build.gradle.kts +++ b/internal/spigot/build.gradle.kts @@ -2,33 +2,26 @@ import com.github.jikoo.openinv.SpigotDependencyExtension import com.github.jikoo.openinv.SpigotSetup plugins { - `openinv-base` alias(libs.plugins.shadow) } +repositories { + maven("https://repo.papermc.io/repository/maven-public/") +} + java { toolchain.languageVersion = JavaLanguageVersion.of(25) } -apply() - -configurations.all { - resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") { - val spigot = candidates.firstOrNull { - it.id.let { id -> - id is ModuleComponentIdentifier && id.module == "spigot-api" - } - } - if (spigot != null) { - select(spigot) - } - because("module is written for Spigot servers") - } +tasks.withType().configureEach { + options.release = 21 } +apply() + dependencies { compileOnly(libs.spigotapi) - extensions.getByType(SpigotDependencyExtension::class.java).version = "26.1-R0.1-SNAPSHOT" + extensions.getByType(SpigotDependencyExtension::class.java).version = "26.1.1-R0.1-SNAPSHOT" compileOnly("com.mojang:logging:1.6.11") compileOnly("com.mojang:brigadier:1.3.10") compileOnly("com.mojang:datafixerupper:9.0.19") diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 128f5abd..b503ff38 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -1,13 +1,14 @@ plugins { - `openinv-base` alias(libs.plugins.shadow) } repositories { + maven("https://hub.spigotmc.org/nexus/content/groups/public/") maven("https://jitpack.io") } dependencies { + compileOnly(libs.spigotapi) implementation(project(":openinvapi")) implementation(project(":openinvcommon")) implementation(project(":openinvadaptercommon")) @@ -17,14 +18,20 @@ dependencies { implementation(project(":openinvadapterpaper1_21_4")) implementation(project(":openinvadapterpaper1_21_3")) implementation(project(":openinvadapterpaper1_21_1")) - implementation(project(":openinvadapterspigot")) { - isTransitive = false - } + implementation(project(":openinvadapterspigot")) implementation(libs.planarwrappers) implementation(libs.folia.scheduler.wrapper) compileOnly(libs.sqlite.jdbc) } +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 +} + tasks.processResources { expand( mutableMapOf( From ca2e3221820f4652c52c5d2207730d8d86857da1 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Sat, 4 Apr 2026 15:39:57 -0400 Subject: [PATCH 05/18] Initial Paper 26.1.1 support --- .../common/container/menu/OpenChestMenu.java | 35 +++++++++---------- .../lishid/openinv/util/InternalAccessor.java | 7 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java b/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java index 939ecd1b..d5f79b31 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java +++ b/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java @@ -9,7 +9,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -17,12 +17,13 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * An extension of {@link AbstractContainerMenu} storing and managing data common to all special inventories. */ +@NullMarked public abstract class OpenChestMenu> extends AbstractContainerMenu { @@ -33,13 +34,13 @@ public abstract class OpenChestMenu, Inventory> bukkitEntity; + private @Nullable CraftInventoryView, Inventory> bukkitEntity; protected OpenChestMenu( - @NotNull MenuType type, + MenuType type, int containerCounter, - @NotNull T container, - @NotNull ServerPlayer viewer, + T container, + ServerPlayer viewer, boolean viewOnly ) { super(type, containerCounter); @@ -90,7 +91,7 @@ protected OpenChestMenu( } } - public static @NotNull MenuType getChestMenuType(int inventorySize) { + public static MenuType getChestMenuType(int inventorySize) { inventorySize = ((int) Math.ceil(inventorySize / 9.0)) * 9; return switch (inventorySize) { case 9 -> MenuType.GENERIC_9x1; @@ -103,11 +104,10 @@ protected OpenChestMenu( }; } - protected void preSlotSetup() { } - protected @NotNull Slot getUpperSlot(int index, int x, int y) { + protected Slot getUpperSlot(int index, int x, int y) { Slot slot = new Slot(container, index, x, y); if (viewOnly) { return SlotViewOnly.wrap(slot); @@ -120,7 +120,7 @@ public boolean isViewOnly() { } @Override - public final @NotNull CraftInventoryView, Inventory> getBukkitView() { + public final CraftInventoryView, Inventory> getBukkitView() { if (bukkitEntity == null) { bukkitEntity = createBukkitEntity(); } @@ -128,7 +128,7 @@ public boolean isViewOnly() { return bukkitEntity; } - protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { + protected CraftInventoryView, Inventory> createBukkitEntity() { Inventory top; if (viewOnly) { top = new OpenDummyInventory(container, container.getBukkitType()); @@ -153,7 +153,7 @@ public int convertSlot(int rawSlot) { } @Override - public @NotNull InventoryType.SlotType getSlotType(int slot) { + public InventoryType.SlotType getSlotType(int slot) { if (viewOnly) { return InventoryType.SlotType.OUTSIDE; } @@ -270,18 +270,17 @@ private static boolean addToExistingStack(ItemStack itemStack, Slot slot) { } @Override - public void clicked(int i, int j, @NotNull ClickType clickType, @NotNull Player player) { + public void clicked(int slotIndex, int buttonNum, ContainerInput containerInput, Player player) { if (viewOnly) { - if (clickType == ClickType.QUICK_CRAFT) { + if (containerInput == ContainerInput.QUICK_CRAFT) { sendAllDataToRemote(); } - return; } - super.clicked(i, j, clickType, player); + super.clicked(slotIndex, buttonNum, containerInput, player); } @Override - public boolean stillValid(@NotNull Player player) { + public boolean stillValid(Player player) { return true; } diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index b0828f3e..e89c32e4 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -66,15 +66,16 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { private @Nullable Accessor getAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { // TODO reorganize internals, version handling if (!PAPER) { - if (BukkitVersions.MINECRAFT.equals(Version.of(26, 1))) { + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(26, 1)) + && BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(26, 1, 1))) { // Load Spigot accessor. return new com.github.jikoo.openinv.internal.spigot26_1.InternalAccessor(logger, lang); } return null; } - Version maxSupported = Version.of(1, 21, 11); - Version minSupported = Version.of(1, 21, 1); + Version maxSupported = Version.of(21, 1, 1); + Version minSupported = maxSupported;//Version.of(1, 21, 1); // Ensure version is in supported range. if (BukkitVersions.MINECRAFT.greaterThan(maxSupported) || BukkitVersions.MINECRAFT.lessThan(minSupported)) { From 14c9cfef15c930712224028737c1b9ff318c2281 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Wed, 8 Apr 2026 12:58:44 -0400 Subject: [PATCH 06/18] Drop versions > 1 year old Also reorganize modern-ish releases --- internal/common/build.gradle.kts | 3 +- internal/paper1_21_1/build.gradle.kts | 27 -- .../paper1_21_1/InternalAccessor.java | 80 ------ .../paper1_21_1/container/OpenInventory.java | 20 -- .../container/slot/ContentCraftingResult.java | 46 --- .../slot/placeholder/PlaceholderLoader.java | 74 ----- .../paper1_21_1/player/PlayerManager.java | 58 ---- internal/paper1_21_3/build.gradle.kts | 26 -- .../paper1_21_3/InternalAccessor.java | 28 -- .../NumericDataPlaceholderLoader.java | 12 - internal/paper1_21_4/build.gradle.kts | 25 -- .../paper1_21_4/InternalAccessor.java | 80 ------ .../paper1_21_4/container/OpenEnderChest.java | 28 -- .../paper1_21_4/container/OpenInventory.java | 191 ------------- .../container/bukkit/OpenPlayerInventory.java | 225 --------------- .../bukkit/OpenPlayerInventorySelf.java | 26 -- .../container/menu/OpenEnderChestMenu.java | 61 ---- .../container/menu/OpenInventoryMenu.java | 266 ------------------ .../container/menu/OpenSyncMenu.java | 229 --------------- .../container/slot/ContentEquipment.java | 80 ------ .../container/slot/ContentOffHand.java | 53 ---- .../slot/placeholder/CustomModelBase.java | 41 --- .../CustomModelPlaceholderLoader.java | 13 - .../paper1_21_4/player/OpenPlayer.java | 36 --- .../paper1_21_4/player/PlayerManager.java | 73 ----- internal/paper1_21_5/build.gradle.kts | 24 -- .../paper1_21_5/InternalAccessor.java | 37 --- .../PlaceholderLoaderLegacyParse.java | 36 --- .../paper1_21_5/player/OpenPlayer.java | 46 --- .../paper1_21_5/player/PlayerManager.java | 106 ------- plugin/build.gradle.kts | 4 - .../lishid/openinv/util/InternalAccessor.java | 111 ++++---- settings.gradle.kts | 4 - 33 files changed, 57 insertions(+), 2112 deletions(-) delete mode 100644 internal/paper1_21_1/build.gradle.kts delete mode 100644 internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/InternalAccessor.java delete mode 100644 internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/OpenInventory.java delete mode 100644 internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/ContentCraftingResult.java delete mode 100644 internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/placeholder/PlaceholderLoader.java delete mode 100644 internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/player/PlayerManager.java delete mode 100644 internal/paper1_21_3/build.gradle.kts delete mode 100644 internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/InternalAccessor.java delete mode 100644 internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/container/slot/placeholder/NumericDataPlaceholderLoader.java delete mode 100644 internal/paper1_21_4/build.gradle.kts delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/InternalAccessor.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenEnderChest.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenInventory.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventory.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventorySelf.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenEnderChestMenu.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenInventoryMenu.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenSyncMenu.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentEquipment.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentOffHand.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelBase.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelPlaceholderLoader.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/OpenPlayer.java delete mode 100644 internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/PlayerManager.java delete mode 100644 internal/paper1_21_5/build.gradle.kts delete mode 100644 internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/InternalAccessor.java delete mode 100644 internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/container/slot/placeholder/PlaceholderLoaderLegacyParse.java delete mode 100644 internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/OpenPlayer.java delete mode 100644 internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/PlayerManager.java diff --git a/internal/common/build.gradle.kts b/internal/common/build.gradle.kts index 85399da2..02a0cfed 100644 --- a/internal/common/build.gradle.kts +++ b/internal/common/build.gradle.kts @@ -19,9 +19,10 @@ tasks.withType().configureEach { class ToolchainJvmVersion: AttributeCompatibilityRule { override fun execute(details: CompatibilityCheckDetails) { if (details.consumerValue == details.producerValue) { + details.compatible() return } - if (details.consumerValue == null) { + if (details.producerValue == null) { details.incompatible() return } diff --git a/internal/paper1_21_1/build.gradle.kts b/internal/paper1_21_1/build.gradle.kts deleted file mode 100644 index 483c5268..00000000 --- a/internal/paper1_21_1/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - alias(libs.plugins.paperweight) -} - -java { - toolchain.languageVersion = JavaLanguageVersion.of(21) -} - -tasks.withType().configureEach { - options.release = 21 -} - -dependencies { - implementation(project(":openinvapi")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvcommon")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvadaptercommon")) - implementation(project(":openinvadapterpaper1_21_8")) - implementation(project(":openinvadapterpaper1_21_5")) - implementation(project(":openinvadapterpaper1_21_4")) - implementation(project(":openinvadapterpaper1_21_3")) - - paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") -} diff --git a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/InternalAccessor.java b/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/InternalAccessor.java deleted file mode 100644 index 100bf31f..00000000 --- a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/InternalAccessor.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_1; - -import com.lishid.openinv.internal.Accessor; -import com.lishid.openinv.internal.IAnySilentContainer; -import com.lishid.openinv.internal.ISpecialEnderChest; -import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.ISpecialPlayerInventory; -import com.lishid.openinv.internal.common.container.AnySilentContainer; -import com.lishid.openinv.internal.paper1_21_1.container.OpenInventory; -import com.lishid.openinv.internal.paper1_21_1.container.slot.placeholder.PlaceholderLoader; -import com.lishid.openinv.internal.paper1_21_1.player.PlayerManager; -import com.lishid.openinv.internal.paper1_21_4.container.OpenEnderChest; -import com.lishid.openinv.util.lang.LanguageManager; -import net.minecraft.world.Container; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.craftbukkit.inventory.CraftInventory; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.logging.Level; -import java.util.logging.Logger; - -public class InternalAccessor implements Accessor { - - private final @NotNull Logger logger; - private final @NotNull PlayerManager manager; - private final @NotNull AnySilentContainer anySilentContainer; - - public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { - this.logger = logger; - this.manager = new PlayerManager(logger); - this.anySilentContainer = new AnySilentContainer(logger, lang); - } - - @Override - public @NotNull PlayerManager getPlayerManager() { - return manager; - } - - @Override - public @NotNull IAnySilentContainer getAnySilentContainer() { - return anySilentContainer; - } - - @Override - public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) { - return new OpenInventory(player); - } - - @Override - public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) { - return new OpenEnderChest(player); - } - - @Override - public @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class clazz) { - if (!(bukkitInventory instanceof CraftInventory craftInventory)) { - return null; - } - Container container = craftInventory.getInventory(); - if (clazz.isInstance(container)) { - return clazz.cast(container); - } - return null; - } - - @Override - public void reload(@NotNull ConfigurationSection config) { - ConfigurationSection placeholders = config.getConfigurationSection("placeholders"); - try { - // Reset placeholders to defaults and try to load configuration. - new PlaceholderLoader().load(placeholders); - } catch (Exception e) { - logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e); - } - } - -} diff --git a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/OpenInventory.java b/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/OpenInventory.java deleted file mode 100644 index 1368d89a..00000000 --- a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/OpenInventory.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_1.container; - -import com.lishid.openinv.internal.common.container.slot.Content; -import com.lishid.openinv.internal.paper1_21_1.container.slot.ContentCraftingResult; -import net.minecraft.server.level.ServerPlayer; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public class OpenInventory extends com.lishid.openinv.internal.paper1_21_4.container.OpenInventory { - - public OpenInventory(@NotNull Player bukkitPlayer) { - super(bukkitPlayer); - } - - @Override - protected Content getCraftingResult(@NotNull ServerPlayer serverPlayer) { - return new ContentCraftingResult(serverPlayer); - } - -} diff --git a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/ContentCraftingResult.java b/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/ContentCraftingResult.java deleted file mode 100644 index d0d74f74..00000000 --- a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/ContentCraftingResult.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_1.container.slot; - -import com.lishid.openinv.internal.common.container.slot.ContentCrafting; -import com.lishid.openinv.internal.common.container.slot.ContentViewOnly; -import com.lishid.openinv.internal.common.container.slot.SlotViewOnly; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.NotNull; - -public class ContentCraftingResult extends ContentViewOnly { - - public ContentCraftingResult(@NotNull ServerPlayer holder) { - super(holder); - } - - @Override - public ItemStack get() { - InventoryMenu inventoryMenu = holder.inventoryMenu; - return inventoryMenu.getSlot(inventoryMenu.getResultSlotIndex()).getItem(); - } - - @Override - public Slot asSlot(Container container, int slot, int x, int y) { - return new SlotViewOnly(container, slot, x, y) { - @Override - public ItemStack getOrDefault() { - if (!ContentCrafting.isAvailable(holder)) { - return Placeholders.survivalOnly(holder); - } - InventoryMenu inventoryMenu = holder.inventoryMenu; - return inventoryMenu.getSlot(inventoryMenu.getResultSlotIndex()).getItem(); - } - }; - } - - @Override - public InventoryType.SlotType getSlotType() { - return InventoryType.SlotType.RESULT; - } - -} diff --git a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/placeholder/PlaceholderLoader.java b/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/placeholder/PlaceholderLoader.java deleted file mode 100644 index 0ac03f26..00000000 --- a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/container/slot/placeholder/PlaceholderLoader.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_1.container.slot.placeholder; - -import com.lishid.openinv.internal.paper1_21_3.container.slot.placeholder.NumericDataPlaceholderLoader; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.registries.Registries; -import net.minecraft.util.Unit; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.entity.BannerPattern; -import net.minecraft.world.level.block.entity.BannerPatternLayers; -import net.minecraft.world.level.block.entity.BannerPatterns; -import org.bukkit.craftbukkit.CraftRegistry; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public class PlaceholderLoader extends NumericDataPlaceholderLoader { - - @Override - protected @NotNull ItemStack defaultCursor() { - // Cursor-like banner with no tooltip - ItemStack itemStack = new ItemStack(Items.WHITE_BANNER); - RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); - Registry bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN); - BannerPattern halfDiagBottomRight = bannerPatterns.getOrThrow(BannerPatterns.DIAGONAL_RIGHT); - BannerPattern downRight = bannerPatterns.getOrThrow(BannerPatterns.STRIPE_DOWNRIGHT); - BannerPattern border = bannerPatterns.getOrThrow(BannerPatterns.BORDER); - itemStack.set( - DataComponents.BANNER_PATTERNS, - new BannerPatternLayers( - List.of( - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfDiagBottomRight), DyeColor.GRAY), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(downRight), DyeColor.WHITE), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(border), DyeColor.GRAY) - ) - ) - ); - addModelData(itemStack); - itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - return itemStack; - } - - @Override - protected @NotNull ItemStack defaultShield() { - // Shield with "missing texture" pattern, magenta and black squares. - ItemStack itemStack = new ItemStack(Items.SHIELD); - itemStack.set(DataComponents.BASE_COLOR, DyeColor.MAGENTA); - RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); - Registry bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN); - BannerPattern halfLeft = bannerPatterns.getOrThrow(BannerPatterns.HALF_VERTICAL); - BannerPattern topLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_LEFT); - BannerPattern topRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_RIGHT); - BannerPattern bottomLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_LEFT); - BannerPattern bottomRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_RIGHT); - itemStack.set(DataComponents.BANNER_PATTERNS, - new BannerPatternLayers( - List.of( - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfLeft), DyeColor.BLACK), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topLeft), DyeColor.MAGENTA), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomLeft), DyeColor.MAGENTA), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topRight), DyeColor.BLACK), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomRight), DyeColor.BLACK) - ) - ) - ); - itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - addModelData(itemStack); - return itemStack; - } - -} diff --git a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/player/PlayerManager.java b/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/player/PlayerManager.java deleted file mode 100644 index 61d78002..00000000 --- a/internal/paper1_21_1/src/main/java/com/lishid/openinv/internal/paper1_21_1/player/PlayerManager.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_1.player; - -import com.mojang.authlib.GameProfile; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ClientInformation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.ChatVisiblity; -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.NotNull; - -import java.util.logging.Logger; - -public class PlayerManager extends com.lishid.openinv.internal.paper1_21_4.player.PlayerManager { - - public PlayerManager(@NotNull Logger logger) { - super(logger); - } - - @Override - protected @NotNull ServerPlayer createNewPlayer( - @NotNull MinecraftServer server, - @NotNull ServerLevel worldServer, - @NotNull final OfflinePlayer offline - ) { - // See net.minecraft.server.players.PlayerList#canPlayerLogin(ServerLoginPacketListenerImpl, GameProfile) - // See net.minecraft.server.network.ServerLoginPacketListenerImpl#handleHello(ServerboundHelloPacket) - GameProfile profile = new GameProfile(offline.getUniqueId(), - offline.getName() != null ? offline.getName() : offline.getUniqueId().toString() - ); - - ClientInformation dummyInfo = new ClientInformation( - "en_us", - 1, // Reduce distance just in case. - ChatVisiblity.HIDDEN, // Don't accept chat. - false, - ServerPlayer.DEFAULT_MODEL_CUSTOMIZATION, - ServerPlayer.DEFAULT_MAIN_HAND, - true, - false // Don't list in player list (not that this player is in the list anyway). - ); - - ServerPlayer entity = new ServerPlayer(server, worldServer, profile, dummyInfo); - - try { - injectPlayer(server, entity); - } catch (IllegalAccessException e) { - logger.log( - java.util.logging.Level.WARNING, - e, - () -> "Unable to inject ServerPlayer, certain player data may be lost when saving!" - ); - } - - return entity; - } - -} diff --git a/internal/paper1_21_3/build.gradle.kts b/internal/paper1_21_3/build.gradle.kts deleted file mode 100644 index 42e1bfdb..00000000 --- a/internal/paper1_21_3/build.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -plugins { - alias(libs.plugins.paperweight) -} - -java { - toolchain.languageVersion = JavaLanguageVersion.of(21) -} - -tasks.withType().configureEach { - options.release = 21 -} - -dependencies { - implementation(project(":openinvapi")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvcommon")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvadaptercommon")) - implementation(project(":openinvadapterpaper1_21_8")) - implementation(project(":openinvadapterpaper1_21_5")) - implementation(project(":openinvadapterpaper1_21_4")) - - paperweight.paperDevBundle("1.21.3-R0.1-SNAPSHOT") -} diff --git a/internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/InternalAccessor.java b/internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/InternalAccessor.java deleted file mode 100644 index e72aeb0a..00000000 --- a/internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/InternalAccessor.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_3; - -import com.lishid.openinv.internal.paper1_21_3.container.slot.placeholder.NumericDataPlaceholderLoader; -import com.lishid.openinv.util.lang.LanguageManager; -import org.bukkit.configuration.ConfigurationSection; -import org.jetbrains.annotations.NotNull; - -import java.util.logging.Level; -import java.util.logging.Logger; - -public class InternalAccessor extends com.lishid.openinv.internal.paper1_21_4.InternalAccessor { - - public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { - super(logger, lang); - } - - @Override - public void reload(@NotNull ConfigurationSection config) { - ConfigurationSection placeholders = config.getConfigurationSection("placeholders"); - try { - // Reset placeholders to defaults and try to load configuration. - new NumericDataPlaceholderLoader().load(placeholders); - } catch (Exception e) { - logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e); - } - } - -} diff --git a/internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/container/slot/placeholder/NumericDataPlaceholderLoader.java b/internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/container/slot/placeholder/NumericDataPlaceholderLoader.java deleted file mode 100644 index d19552a4..00000000 --- a/internal/paper1_21_3/src/main/java/com/lishid/openinv/internal/paper1_21_3/container/slot/placeholder/NumericDataPlaceholderLoader.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_3.container.slot.placeholder; - -import com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder.CustomModelBase; -import net.minecraft.world.item.component.CustomModelData; - -public class NumericDataPlaceholderLoader extends CustomModelBase { - - public NumericDataPlaceholderLoader() { - super(new CustomModelData(9999)); - } - -} diff --git a/internal/paper1_21_4/build.gradle.kts b/internal/paper1_21_4/build.gradle.kts deleted file mode 100644 index 3c941c3c..00000000 --- a/internal/paper1_21_4/build.gradle.kts +++ /dev/null @@ -1,25 +0,0 @@ -plugins { - alias(libs.plugins.paperweight) -} - -java { - toolchain.languageVersion = JavaLanguageVersion.of(21) -} - -tasks.withType().configureEach { - options.release = 21 -} - -dependencies { - implementation(project(":openinvapi")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvcommon")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvadaptercommon")) - implementation(project(":openinvadapterpaper1_21_8")) - implementation(project(":openinvadapterpaper1_21_5")) - - paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/InternalAccessor.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/InternalAccessor.java deleted file mode 100644 index 98b09873..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/InternalAccessor.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4; - -import com.lishid.openinv.internal.Accessor; -import com.lishid.openinv.internal.IAnySilentContainer; -import com.lishid.openinv.internal.ISpecialEnderChest; -import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.ISpecialPlayerInventory; -import com.lishid.openinv.internal.common.container.AnySilentContainer; -import com.lishid.openinv.internal.paper1_21_4.container.OpenEnderChest; -import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory; -import com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder.CustomModelPlaceholderLoader; -import com.lishid.openinv.internal.paper1_21_4.player.PlayerManager; -import com.lishid.openinv.util.lang.LanguageManager; -import net.minecraft.world.Container; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.craftbukkit.inventory.CraftInventory; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.logging.Level; -import java.util.logging.Logger; - -public class InternalAccessor implements Accessor { - - protected final @NotNull Logger logger; - private final @NotNull PlayerManager manager; - private final @NotNull AnySilentContainer anySilentContainer; - - public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { - this.logger = logger; - manager = new PlayerManager(logger); - anySilentContainer = new AnySilentContainer(logger, lang); - } - - @Override - public @NotNull PlayerManager getPlayerManager() { - return manager; - } - - @Override - public @NotNull IAnySilentContainer getAnySilentContainer() { - return anySilentContainer; - } - - @Override - public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) { - return new OpenInventory(player); - } - - @Override - public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) { - return new OpenEnderChest(player); - } - - @Override - public @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class clazz) { - if (!(bukkitInventory instanceof CraftInventory craftInventory)) { - return null; - } - Container container = craftInventory.getInventory(); - if (clazz.isInstance(container)) { - return clazz.cast(container); - } - return null; - } - - @Override - public void reload(@NotNull ConfigurationSection config) { - ConfigurationSection placeholders = config.getConfigurationSection("placeholders"); - try { - // Reset placeholders to defaults and try to load configuration. - new CustomModelPlaceholderLoader().load(placeholders); - } catch (Exception e) { - logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e); - } - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenEnderChest.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenEnderChest.java deleted file mode 100644 index 5ffd2665..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenEnderChest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container; - -import com.lishid.openinv.internal.paper1_21_4.container.menu.OpenEnderChestMenu; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.inventory.AbstractContainerMenu; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class OpenEnderChest extends com.lishid.openinv.internal.common.container.OpenEnderChest { - - public OpenEnderChest(@NotNull Player player) { - super(player); - } - - @Override - public @Nullable OpenEnderChestMenu createMenu( - net.minecraft.world.entity.player.Player player, - int i, - boolean viewOnly - ) { - if (player instanceof ServerPlayer serverPlayer) { - return new OpenEnderChestMenu(this, serverPlayer, i, viewOnly); - } - return null; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenInventory.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenInventory.java deleted file mode 100644 index 4eea3374..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/OpenInventory.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container; - -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.common.container.slot.ContentCrafting; -import com.lishid.openinv.internal.common.container.slot.ContentCursor; -import com.lishid.openinv.internal.common.container.slot.ContentDrop; -import com.lishid.openinv.internal.common.container.slot.ContentList; -import com.lishid.openinv.internal.common.container.slot.ContentViewOnly; -import com.lishid.openinv.internal.common.container.slot.SlotViewOnly; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.paper1_21_4.container.bukkit.OpenPlayerInventory; -import com.lishid.openinv.internal.paper1_21_4.container.menu.OpenInventoryMenu; -import com.lishid.openinv.internal.paper1_21_4.container.slot.ContentEquipment; -import com.lishid.openinv.internal.paper1_21_4.container.slot.ContentOffHand; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class OpenInventory extends com.lishid.openinv.internal.paper1_21_8.container.OpenInventory { - - public OpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) { - super(bukkitPlayer); - } - - @Override - protected void setupSlots() { - // Top of inventory: Regular contents. - int nextIndex = addMainInventory(); - - // If inventory is expected size, we can arrange slots to be pretty. - Inventory ownerInv = owner.getInventory(); - if (ownerInv.items.size() == 36 - && ownerInv.armor.size() == 4 - && ownerInv.offhand.size() == 1 - && owner.inventoryMenu.getCraftSlots().getContainerSize() == 4) { - // Armor slots: Bottom left. - addArmor(36); - // Off-hand: Below chestplate. - addOffHand(46); - // Drop slot: Bottom right. - slots.set(53, new ContentDrop(owner)); - // Cursor slot: Above drop. - slots.set(44, new ContentCursor(owner)); - - // Crafting is displayed in the bottom right corner. - // As we're using the pretty view, this is a 3x2. - addCrafting(41, true); - return; - } - - // Otherwise we'll just add elements linearly. - nextIndex = addArmor(nextIndex); - nextIndex = addOffHand(nextIndex); - nextIndex = addCrafting(nextIndex, false); - slots.set(nextIndex, new ContentCursor(owner)); - // Drop slot last. - slots.set(slots.size() - 1, new ContentDrop(owner)); - } - - private int addMainInventory() { - int listSize = owner.getInventory().items.size(); - // Hotbar slots are 0-8. We want those to appear on the bottom of the inventory like a normal player inventory, - // so everything else needs to move up a row. - int hotbarDiff = listSize - 9; - for (int localIndex = 0; localIndex < listSize; ++localIndex) { - InventoryType.SlotType type; - int invIndex; - if (localIndex < hotbarDiff) { - invIndex = localIndex + 9; - type = InventoryType.SlotType.CONTAINER; - } else { - type = InventoryType.SlotType.QUICKBAR; - invIndex = localIndex - hotbarDiff; - } - - slots.set( - localIndex, - new ContentList(owner, invIndex, type) { - @Override - public void setHolder(@NotNull ServerPlayer holder) { - items = holder.getInventory().items; - } - } - ); - } - return listSize; - } - - private int addArmor(int startIndex) { - int listSize = owner.getInventory().armor.size(); - - for (int i = 0; i < listSize; ++i) { - // Armor slots go bottom to top; boots are slot 0, helmet is slot 3. - // Since we have to display horizontally due to space restrictions, - // making the left side the "top" is more user-friendly. - int armorIndex; - EquipmentSlot slot; - switch (i) { - case 3 -> { - armorIndex = 0; - slot = EquipmentSlot.FEET; - } - case 2 -> { - armorIndex = 1; - slot = EquipmentSlot.LEGS; - } - case 1 -> { - armorIndex = 2; - slot = EquipmentSlot.CHEST; - } - case 0 -> { - armorIndex = 3; - slot = EquipmentSlot.HEAD; - } - default -> { - // In the event that new armor slots are added, they can be placed at the end. - armorIndex = i; - slot = EquipmentSlot.MAINHAND; - } - } - - slots.set(startIndex + i, new ContentEquipment(owner, armorIndex, slot)); - } - - return startIndex + listSize; - } - - private int addOffHand(int startIndex) { - int listSize = owner.getInventory().offhand.size(); - for (int localIndex = 0; localIndex < listSize; ++localIndex) { - slots.set(startIndex + localIndex, new ContentOffHand(owner, localIndex)); - } - return startIndex + listSize; - } - - private int addCrafting(int startIndex, boolean pretty) { - int listSize = owner.inventoryMenu.getCraftSlots().getContents().size(); - pretty &= listSize == 4; - - for (int localIndex = 0; localIndex < listSize; ++localIndex) { - // Pretty display is a 2x2 rather than linear. - // If index is in top row, grid is not 2x2, or pretty is disabled, just use current index. - // Otherwise, subtract 2 and add 9 to start in the same position on the next row. - int modIndex = startIndex + (localIndex < 2 || !pretty ? localIndex : localIndex + 7); - - slots.set(modIndex, new ContentCrafting(owner, localIndex)); - } - - if (pretty) { - slots.set(startIndex + 2, new ContentViewOnly(owner) { - @Override - public Slot asSlot(Container container, int slot, int x, int y) { - return new SlotViewOnly(container, slot, x, y) { - @Override - public ItemStack getOrDefault() { - return Placeholders.craftingOutput; - } - }; - } - } - ); - slots.set(startIndex + 11, getCraftingResult(owner)); - } - - return startIndex + listSize; - } - - @Override - public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { - if (bukkitEntity == null) { - bukkitEntity = new OpenPlayerInventory(this); - } - return bukkitEntity; - } - - @Override - public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { - if (player instanceof ServerPlayer serverPlayer) { - return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); - } - return null; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventory.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventory.java deleted file mode 100644 index 9cd8fbc0..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventory.java +++ /dev/null @@ -1,225 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.bukkit; - -import com.google.common.base.Preconditions; -import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory; -import net.minecraft.core.NonNullList; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Inventory; -import org.bukkit.craftbukkit.inventory.CraftInventory; -import org.bukkit.craftbukkit.inventory.CraftItemStack; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class OpenPlayerInventory extends CraftInventory implements PlayerInventory { - - public OpenPlayerInventory(@NotNull OpenInventory inventory) { - super(inventory); - } - - @Override - public @NotNull OpenInventory getInventory() { - return (OpenInventory) super.getInventory(); - } - - @Override - public ItemStack @NotNull [] getContents() { - return asCraftMirror(getInventory().getOwnerHandle().getInventory().getContents()); - } - - @Override - public void setContents(ItemStack[] items) { - Inventory internal = getInventory().getOwnerHandle().getInventory(); - int size = internal.getContainerSize(); - Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size); - - for (int index = 0; index < size; ++index) { - if (index < items.length) { - internal.setItem(index, CraftItemStack.asNMSCopy(items[index])); - } else { - internal.setItem(index, net.minecraft.world.item.ItemStack.EMPTY); - } - } - } - - @Override - public ItemStack @NotNull [] getStorageContents() { - return asCraftMirror(getInventory().getOwnerHandle().getInventory().items); - } - - @Override - public void setStorageContents(ItemStack[] items) throws IllegalArgumentException { - NonNullList list = getInventory().getOwnerHandle().getInventory().items; - int size = list.size(); - Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size); - for (int index = 0; index < items.length; ++index) { - list.set(index, CraftItemStack.asNMSCopy(items[index])); - } - } - - @Override - public @NotNull InventoryType getType() { - return InventoryType.PLAYER; - } - - @Override - public @NotNull Player getHolder() { - return getInventory().getOwner(); - } - - @Override - public @NotNull ItemStack @NotNull [] getArmorContents() { - return asCraftMirror(getInventory().getOwnerHandle().getInventory().armor); - } - - @Override - public void setArmorContents(ItemStack @NotNull [] items) { - NonNullList list = getInventory().getOwnerHandle().getInventory().armor; - int size = list.size(); - Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size); - for (int index = 0; index < items.length; ++index) { - list.set(index, CraftItemStack.asNMSCopy(items[index])); - } - } - - @Override - public @NotNull ItemStack @NotNull [] getExtraContents() { - return asCraftMirror(getInventory().getOwnerHandle().getInventory().offhand); - } - - @Override - public void setExtraContents(ItemStack @NotNull [] items) { - NonNullList list = getInventory().getOwnerHandle().getInventory().offhand; - int size = list.size(); - Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size); - for (int index = 0; index < items.length; ++index) { - list.set(index, CraftItemStack.asNMSCopy(items[index])); - } - } - - @Override - public @NotNull ItemStack getHelmet() { - return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory() - .getArmor(EquipmentSlot.HEAD.getIndex())); - } - - @Override - public void setHelmet(@Nullable ItemStack helmet) { - getInventory().getOwnerHandle().getInventory().armor - .set(EquipmentSlot.HEAD.getIndex(), CraftItemStack.asNMSCopy(helmet)); - } - - @Override - public @NotNull ItemStack getChestplate() { - return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory() - .getArmor(EquipmentSlot.CHEST.getIndex())); - } - - @Override - public void setChestplate(@Nullable ItemStack chestplate) { - getInventory().getOwnerHandle().getInventory().armor - .set(EquipmentSlot.CHEST.getIndex(), CraftItemStack.asNMSCopy(chestplate)); - } - - @Override - public @NotNull ItemStack getLeggings() { - return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory() - .getArmor(EquipmentSlot.LEGS.getIndex())); - } - - @Override - public void setLeggings(@Nullable ItemStack leggings) { - getInventory().getOwnerHandle().getInventory().armor - .set(EquipmentSlot.LEGS.getIndex(), CraftItemStack.asNMSCopy(leggings)); - } - - @Override - public @NotNull ItemStack getBoots() { - return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory() - .getArmor(EquipmentSlot.FEET.getIndex())); - } - - @Override - public void setBoots(@Nullable ItemStack boots) { - getInventory().getOwnerHandle().getInventory().armor - .set(EquipmentSlot.FEET.getIndex(), CraftItemStack.asNMSCopy(boots)); - } - - @Override - public @NotNull ItemStack getItemInMainHand() { - Inventory internal = getInventory().getOwnerHandle().getInventory(); - return CraftItemStack.asCraftMirror(internal.getItem(internal.selected)); - } - - @Override - public void setItemInMainHand(@Nullable ItemStack item) { - Inventory internal = getInventory().getOwnerHandle().getInventory(); - internal.setItem(internal.selected, CraftItemStack.asNMSCopy(item)); - } - - @Override - public @NotNull ItemStack getItemInOffHand() { - return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory().offhand.getFirst()); - } - - @Override - public void setItemInOffHand(@Nullable ItemStack item) { - getInventory().getOwnerHandle().getInventory().offhand.set(0, CraftItemStack.asNMSCopy(item)); - } - - @SuppressWarnings("InlineMeSuggester") - @Deprecated - @Override - public @NotNull ItemStack getItemInHand() { - return getItemInMainHand(); - } - - @SuppressWarnings("InlineMeSuggester") - @Deprecated - @Override - public void setItemInHand(@Nullable ItemStack stack) { - setItemInMainHand(stack); - } - - @Override - public int getHeldItemSlot() { - Inventory internal = getInventory().getOwnerHandle().getInventory(); - return internal.items.size() - 9 + internal.selected; - } - - @Override - public void setHeldItemSlot(int slot) { - slot %= 9; - getInventory().getOwnerHandle().getInventory().selected = slot; - } - - @Override - public @NotNull ItemStack getItem(@NotNull org.bukkit.inventory.EquipmentSlot slot) { - return switch (slot) { - case HAND -> getItemInMainHand(); - case OFF_HAND -> getItemInOffHand(); - case FEET -> getBoots(); - case LEGS -> getLeggings(); - case CHEST -> getChestplate(); - case HEAD -> getHelmet(); - default -> throw new IllegalArgumentException("Unsupported EquipmentSlot " + slot); - }; - } - - @Override - public void setItem(@NotNull org.bukkit.inventory.EquipmentSlot slot, @Nullable ItemStack item) { - switch (slot) { - case HAND -> setItemInMainHand(item); - case OFF_HAND -> setItemInOffHand(item); - case FEET -> setBoots(item); - case LEGS -> setLeggings(item); - case CHEST -> setChestplate(item); - case HEAD -> setHelmet(item); - default -> throw new IllegalArgumentException("Unsupported EquipmentSlot " + slot); - } - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventorySelf.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventorySelf.java deleted file mode 100644 index d6e0ce0b..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/bukkit/OpenPlayerInventorySelf.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.bukkit; - -import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; - -public class OpenPlayerInventorySelf extends OpenPlayerInventory { - - private final int offset; - - public OpenPlayerInventorySelf(@NotNull OpenInventory inventory, int offset) { - super(inventory); - this.offset = offset; - } - - @Override - public ItemStack getItem(int index) { - return super.getItem(offset + index); - } - - @Override - public void setItem(int index, ItemStack item) { - super.setItem(offset + index, item); - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenEnderChestMenu.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenEnderChestMenu.java deleted file mode 100644 index 6ba23c14..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenEnderChestMenu.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.menu; - -import com.lishid.openinv.internal.common.container.OpenEnderChest; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; - -public class OpenEnderChestMenu extends OpenSyncMenu { - - public OpenEnderChestMenu( - @NotNull OpenEnderChest enderChest, - @NotNull ServerPlayer viewer, - int containerId, - boolean viewOnly - ) { - super( - OpenChestMenu.getChestMenuType(enderChest.getContainerSize()), - containerId, - enderChest, - viewer, - viewOnly - ); - } - - @Override - public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { - if (viewOnly) { - return ItemStack.EMPTY; - } - - // See ChestMenu - Slot slot = this.slots.get(index); - - if (slot.isFake() || !slot.hasItem()) { - return ItemStack.EMPTY; - } - - ItemStack itemStack = slot.getItem(); - ItemStack original = itemStack.copy(); - - if (index < topSize) { - if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { - return ItemStack.EMPTY; - } - } else if (!this.moveItemStackTo(itemStack, 0, topSize, false)) { - return ItemStack.EMPTY; - } - - if (itemStack.isEmpty()) { - slot.setByPlayer(ItemStack.EMPTY); - } else { - slot.setChanged(); - } - - return original; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenInventoryMenu.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenInventoryMenu.java deleted file mode 100644 index 1bdbf469..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenInventoryMenu.java +++ /dev/null @@ -1,266 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.menu; - -import com.google.common.base.Preconditions; -import com.lishid.openinv.internal.common.container.bukkit.OpenDummyPlayerInventory; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.common.container.slot.ContentDrop; -import com.lishid.openinv.internal.common.container.slot.SlotViewOnly; -import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory; -import com.lishid.openinv.internal.paper1_21_4.container.bukkit.OpenPlayerInventorySelf; -import com.lishid.openinv.internal.paper1_21_4.container.slot.ContentEquipment; -import com.lishid.openinv.util.Permissions; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.craftbukkit.inventory.CraftInventoryView; -import org.bukkit.craftbukkit.inventory.CraftItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class OpenInventoryMenu extends OpenSyncMenu { - - private int offset; - - public OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { - super(getMenuType(inventory, viewer), i, inventory, viewer, viewOnly); - } - - private static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { - int size = inventory.getContainerSize(); - // Disallow duplicate access to own main inventory contents. - if (inventory.getOwnerHandle().equals(viewer)) { - size -= viewer.getInventory().items.size(); - size = ((int) Math.ceil(size / 9.0)) * 9; - } - - return OpenChestMenu.getChestMenuType(size); - } - - @Override - protected void preSlotSetup() { - offset = ownContainer ? viewer.getInventory().items.size() : 0; - } - - @Override - protected @NotNull Slot getUpperSlot(int index, int x, int y) { - index += offset; - Slot slot = container.getMenuSlot(index, x, y); - - // If the slot cannot be interacted with there's nothing to configure. - if (slot.getClass().equals(SlotViewOnly.class)) { - return slot; - } - - // Remove drop slot if viewer is not allowed to use it. - if (slot instanceof ContentDrop.SlotDrop - && (viewOnly || !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity()))) { - return new SlotViewOnly(container, index, x, y); - } - - if (slot instanceof ContentEquipment.SlotEquipment equipment) { - if (viewOnly) { - return SlotViewOnly.wrap(slot); - } - - Permissions perm = switch (equipment.getEquipmentSlot()) { - case HEAD -> Permissions.INVENTORY_SLOT_HEAD_ANY; - case CHEST -> Permissions.INVENTORY_SLOT_CHEST_ANY; - case LEGS -> Permissions.INVENTORY_SLOT_LEGS_ANY; - case FEET -> Permissions.INVENTORY_SLOT_FEET_ANY; - // Off-hand can hold anything, not just equipment. - default -> null; - }; - - // If the viewer doesn't have permission, only allow equipment the viewee can equip in the slot. - if (perm != null && !perm.hasPermission(viewer.getBukkitEntity())) { - equipment.onlyEquipmentFor(container.getOwnerHandle()); - } - - // Equipment slots are a core part of the inventory, so they will always be shown. - return slot; - } - - // When viewing own inventory, only allow access to equipment and drop slots (equipment allowed above). - if (ownContainer && !(slot instanceof ContentDrop.SlotDrop)) { - return new SlotViewOnly(container, index, x, y); - } - - if (viewOnly) { - return SlotViewOnly.wrap(slot); - } - - return slot; - } - - @Override - protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { - org.bukkit.inventory.Inventory bukkitInventory; - if (viewOnly) { - bukkitInventory = new OpenDummyPlayerInventory(container); - } else if (ownContainer) { - bukkitInventory = new OpenPlayerInventorySelf(container, offset); - } else { - bukkitInventory = container.getBukkitInventory(); - } - - return new CraftInventoryView<>(viewer.getBukkitEntity(), bukkitInventory, this) { - @Override - public org.bukkit.inventory.ItemStack getItem(int index) { - if (viewOnly || index < 0) { - return null; - } - - Slot slot = slots.get(index); - return CraftItemStack.asCraftMirror(slot.hasItem() ? slot.getItem() : ItemStack.EMPTY); - } - - @Override - public boolean isInTop(int rawSlot) { - return rawSlot < topSize; - } - - @Override - public @Nullable Inventory getInventory(int rawSlot) { - if (viewOnly) { - return null; - } - if (rawSlot == InventoryView.OUTSIDE || rawSlot == -1) { - return null; - } - Preconditions.checkArgument( - rawSlot >= 0 && rawSlot < topSize + offset + BOTTOM_INVENTORY_SIZE, - "Slot %s outside of inventory", - rawSlot - ); - if (rawSlot > topSize) { - return getBottomInventory(); - } - Slot slot = slots.get(rawSlot); - if (slot.isFake()) { - return null; - } - return getTopInventory(); - } - - @Override - public int convertSlot(int rawSlot) { - if (viewOnly) { - return InventoryView.OUTSIDE; - } - if (rawSlot < 0) { - return rawSlot; - } - if (rawSlot < topSize) { - Slot slot = slots.get(rawSlot); - if (slot.isFake()) { - return InventoryView.OUTSIDE; - } - return rawSlot; - } - - int slot = rawSlot - topSize; - - if (slot >= 27) { - slot -= 27; - } else { - slot += 9; - } - - return slot; - } - - @Override - public @NotNull InventoryType.SlotType getSlotType(int slot) { - if (viewOnly || slot < 0) { - return InventoryType.SlotType.OUTSIDE; - } - if (slot >= topSize) { - slot -= topSize; - if (slot >= 27) { - return InventoryType.SlotType.QUICKBAR; - } - return InventoryType.SlotType.CONTAINER; - } - return OpenInventoryMenu.this.container.getSlotType(offset + slot); - } - - @Override - public int countSlots() { - return topSize + BOTTOM_INVENTORY_SIZE; - } - }; - } - - @Override - public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { - if (viewOnly) { - return ItemStack.EMPTY; - } - - // See ChestMenu and InventoryMenu - Slot slot = this.slots.get(index); - - if (!slot.hasItem() || slot.isFake()) { - return ItemStack.EMPTY; - } - - ItemStack itemStack = slot.getItem(); - ItemStack originalStack = itemStack.copy(); - - if (index < topSize) { - // If we're moving top to bottom, do a normal transfer. - if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { - return ItemStack.EMPTY; - } - } else { - EquipmentSlot equipmentSlot = player.getEquipmentSlotForItem(itemStack); - boolean movedGear = switch (equipmentSlot) { - // If this is gear, try to move it to the correct slot first. - case OFFHAND, FEET, LEGS, CHEST, HEAD -> { - // Locate the correct slot in the contents following the main inventory. - for (int extra = container.getOwnerHandle().getInventory().items.size() - offset; extra < topSize; ++extra) { - Slot extraSlot = getSlot(extra); - if (extraSlot instanceof ContentEquipment.SlotEquipment equipSlot - && equipSlot.getEquipmentSlot() == equipmentSlot) { - // If we've found a matching slot, try to move to it. - // If this succeeds, even partially, we will not attempt to move to other slots. - // Otherwise, armor is already occupied, so we'll fall through to main inventory. - yield this.moveItemStackTo(itemStack, extra, extra + 1, false); - } - } - yield false; - } - // Non-gear gets no special treatment. - default -> false; - }; - - // If main inventory is not available, there's nowhere else to move. - if (offset != 0) { - if (!movedGear) { - return ItemStack.EMPTY; - } - } else { - // If we didn't move to a gear slot, try to move to a main inventory slot. - if (!movedGear && !this.moveItemStackTo(itemStack, 0, container.getOwnerHandle().getInventory().items.size(), true)) { - return ItemStack.EMPTY; - } - } - } - - if (itemStack.isEmpty()) { - slot.setByPlayer(ItemStack.EMPTY); - } else { - slot.setChanged(); - } - - return originalStack; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenSyncMenu.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenSyncMenu.java deleted file mode 100644 index 5a2d6162..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/menu/OpenSyncMenu.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.menu; - -import com.google.common.base.Suppliers; -import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.InternalOwned; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.common.container.slot.SlotPlaceholder; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.ContainerListener; -import net.minecraft.world.inventory.ContainerSynchronizer; -import net.minecraft.world.inventory.DataSlot; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -/** - * An extension of {@link AbstractContainerMenu} that supports {@link SlotPlaceholder placeholders}. - */ -@SuppressWarnings("HidingField") -public abstract class OpenSyncMenu> - extends OpenChestMenu { - - // Syncher fields - private @Nullable ContainerSynchronizer synchronizer; - private final List dataSlots = new ArrayList<>(); - private final IntList remoteDataSlots = new IntArrayList(); - private final List containerListeners = new ArrayList<>(); - private ItemStack remoteCarried = ItemStack.EMPTY; - private boolean suppressRemoteUpdates; - - protected OpenSyncMenu( - @NotNull MenuType type, - int containerCounter, - @NotNull T container, - @NotNull ServerPlayer viewer, - boolean viewOnly - ) { - super(type, containerCounter, container, viewer, viewOnly); - } - - // Overrides from here on are purely to modify the sync process to send placeholder items. - @Override - protected @NotNull Slot addSlot(@NotNull Slot slot) { - slot.index = this.slots.size(); - this.slots.add(slot); - this.lastSlots.add(ItemStack.EMPTY); - this.remoteSlots.add(ItemStack.EMPTY); - return slot; - } - - @Override - protected @NotNull DataSlot addDataSlot(@NotNull DataSlot dataSlot) { - this.dataSlots.add(dataSlot); - this.remoteDataSlots.add(0); - return dataSlot; - } - - @Override - protected void addDataSlots(ContainerData containerData) { - for (int i = 0; i < containerData.getCount(); i++) { - this.addDataSlot(DataSlot.forContainer(containerData, i)); - } - } - - @Override - public void addSlotListener(@NotNull ContainerListener containerListener) { - if (!this.containerListeners.contains(containerListener)) { - this.containerListeners.add(containerListener); - this.broadcastChanges(); - } - } - - @Override - public void setSynchronizer(@NotNull ContainerSynchronizer containerSynchronizer) { - this.synchronizer = containerSynchronizer; - this.sendAllDataToRemote(); - } - - @Override - public void sendAllDataToRemote() { - for (int index = 0; index < slots.size(); ++index) { - Slot slot = slots.get(index); - this.remoteSlots.set(index, (slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem()).copy()); - } - - remoteCarried = getCarried().copy(); - - for (int index = 0; index < this.dataSlots.size(); ++index) { - this.remoteDataSlots.set(index, this.dataSlots.get(index).get()); - } - - if (this.synchronizer != null) { - this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); - } - } - - @Override - public void broadcastCarriedItem() { - this.remoteCarried = this.getCarried().copy(); - if (this.synchronizer != null) { - this.synchronizer.sendCarriedChange(this, this.remoteCarried); - } - } - - @Override - public void removeSlotListener(@NotNull ContainerListener containerListener) { - this.containerListeners.remove(containerListener); - } - - @Override - public void broadcastChanges() { - for (int index = 0; index < this.slots.size(); ++index) { - Slot slot = this.slots.get(index); - ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); - Supplier supplier = Suppliers.memoize(itemstack::copy); - this.triggerSlotListeners(index, itemstack, supplier); - this.synchronizeSlotToRemote(index, itemstack, supplier); - } - - this.synchronizeCarriedToRemote(); - - for (int index = 0; index < this.dataSlots.size(); ++index) { - DataSlot dataSlot = this.dataSlots.get(index); - int j = dataSlot.get(); - if (dataSlot.checkAndClearUpdateFlag()) { - this.updateDataSlotListeners(index, j); - } - - this.synchronizeDataSlotToRemote(index, j); - } - } - - @Override - public void broadcastFullState() { - for (int index = 0; index < this.slots.size(); ++index) { - ItemStack itemstack = this.slots.get(index).getItem(); - this.triggerSlotListeners(index, itemstack, itemstack::copy); - } - - for (int index = 0; index < this.dataSlots.size(); ++index) { - DataSlot containerproperty = this.dataSlots.get(index); - if (containerproperty.checkAndClearUpdateFlag()) { - this.updateDataSlotListeners(index, containerproperty.get()); - } - } - - this.sendAllDataToRemote(); - } - - private void updateDataSlotListeners(int i, int j) { - for (ContainerListener containerListener : this.containerListeners) { - containerListener.dataChanged(this, i, j); - } - } - - private void triggerSlotListeners(int index, ItemStack itemStack, Supplier supplier) { - ItemStack itemStack1 = this.lastSlots.get(index); - if (!ItemStack.matches(itemStack1, itemStack)) { - ItemStack itemStack2 = supplier.get(); - this.lastSlots.set(index, itemStack2); - - for (ContainerListener containerListener : this.containerListeners) { - containerListener.slotChanged(this, index, itemStack2); - } - } - } - - private void synchronizeSlotToRemote(int i, ItemStack itemStack, Supplier supplier) { - if (!this.suppressRemoteUpdates) { - ItemStack itemStack1 = this.remoteSlots.get(i); - if (!ItemStack.matches(itemStack1, itemStack)) { - ItemStack itemstack2 = supplier.get(); - this.remoteSlots.set(i, itemstack2); - if (this.synchronizer != null) { - this.synchronizer.sendSlotChange(this, i, itemstack2); - } - } - } - } - - private void synchronizeDataSlotToRemote(int index, int value) { - if (!this.suppressRemoteUpdates) { - int existing = this.remoteDataSlots.getInt(index); - if (existing != value) { - this.remoteDataSlots.set(index, value); - if (this.synchronizer != null) { - this.synchronizer.sendDataChange(this, index, value); - } - } - } - } - - private void synchronizeCarriedToRemote() { - if (!this.suppressRemoteUpdates && !ItemStack.matches(this.getCarried(), this.remoteCarried)) { - this.remoteCarried = this.getCarried().copy(); - if (this.synchronizer != null) { - this.synchronizer.sendCarriedChange(this, this.remoteCarried); - } - } - } - - @Override - public void setRemoteCarried(ItemStack itemstack) { - this.remoteCarried = itemstack.copy(); - } - - @Override - public void suppressRemoteUpdates() { - this.suppressRemoteUpdates = true; - } - - @Override - public void resumeRemoteUpdates() { - this.suppressRemoteUpdates = false; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentEquipment.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentEquipment.java deleted file mode 100644 index b5513499..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentEquipment.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.slot; - -import com.lishid.openinv.internal.common.container.slot.ContentList; -import com.lishid.openinv.internal.common.container.slot.SlotPlaceholder; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.NotNull; - -/** - * A slot for equipment that displays placeholders if empty. - */ -public class ContentEquipment extends ContentList { - - private final ItemStack placeholder; - private final EquipmentSlot equipmentSlot; - - public ContentEquipment(ServerPlayer holder, int index, EquipmentSlot equipmentSlot) { - super(holder, index, InventoryType.SlotType.ARMOR); - placeholder = switch (equipmentSlot) { - case HEAD -> Placeholders.emptyHelmet; - case CHEST -> Placeholders.emptyChestplate; - case LEGS -> Placeholders.emptyLeggings; - case FEET -> Placeholders.emptyBoots; - default -> Placeholders.emptyOffHand; - }; - this.equipmentSlot = equipmentSlot; - } - - @Override - public void setHolder(@NotNull ServerPlayer holder) { - this.items = holder.getInventory().armor; - } - - @Override - public Slot asSlot(Container container, int slot, int x, int y) { - return new SlotEquipment(container, slot, x, y); - } - - public class SlotEquipment extends SlotPlaceholder { - - private ServerPlayer viewer; - - SlotEquipment(Container container, int index, int x, int y) { - super(container, index, x, y); - } - - @Override - public ItemStack getOrDefault() { - ItemStack itemStack = getItem(); - if (!itemStack.isEmpty()) { - return itemStack; - } - return placeholder; - } - - public EquipmentSlot getEquipmentSlot() { - return equipmentSlot; - } - - public void onlyEquipmentFor(ServerPlayer viewer) { - this.viewer = viewer; - } - - @Override - public boolean mayPlace(@NotNull ItemStack itemStack) { - if (viewer == null) { - return true; - } - - return equipmentSlot == EquipmentSlot.OFFHAND || viewer.getEquipmentSlotForItem(itemStack) == equipmentSlot; - } - - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentOffHand.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentOffHand.java deleted file mode 100644 index 31da3618..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/ContentOffHand.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.slot; - -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; -import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.inventory.InventoryMenu; -import net.minecraft.world.inventory.Slot; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.NotNull; - -/** - * A slot for equipment that updates held items if necessary. - */ -public class ContentOffHand extends ContentEquipment { - - private ServerPlayer holder; - - public ContentOffHand(ServerPlayer holder, int localIndex) { - super(holder, localIndex, EquipmentSlot.OFFHAND); - } - - @Override - public void setHolder(@NotNull ServerPlayer holder) { - this.items = holder.getInventory().offhand; - this.holder = holder; - } - - @Override - public InventoryType.SlotType getSlotType() { - return InventoryType.SlotType.QUICKBAR; - } - - @Override - public Slot asSlot(Container container, int slot, int x, int y) { - return new SlotEquipment(container, slot, x, y) { - @Override - public void setChanged() { - if (BaseOpenPlayer.isConnected(holder.connection) && holder.containerMenu != holder.inventoryMenu) { - holder.connection.send( - new ClientboundContainerSetSlotPacket( - holder.inventoryMenu.containerId, - holder.inventoryMenu.incrementStateId(), - InventoryMenu.SHIELD_SLOT, - holder.getOffhandItem() - )); - } - } - }; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelBase.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelBase.java deleted file mode 100644 index 33dd3a21..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelBase.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder; - -import com.lishid.openinv.internal.common.container.slot.placeholder.PlaceholderLoaderBase; -import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.TagParser; -import net.minecraft.util.Unit; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.CustomModelData; -import net.minecraft.world.item.component.DyedItemColor; -import org.jetbrains.annotations.NotNull; - -public class CustomModelBase extends PlaceholderLoaderBase { - - private final @NotNull CustomModelData defaultCustomModelData; - - public CustomModelBase(@NotNull CustomModelData defaultCustomModelData) { - this.defaultCustomModelData = defaultCustomModelData; - } - - @Override - protected @NotNull CompoundTag parseTag(@NotNull String itemText) throws Exception { - return TagParser.parseTag(itemText); - } - - @Override - protected void addModelData(@NotNull ItemStack itemStack) { - itemStack.set(DataComponents.CUSTOM_MODEL_DATA, defaultCustomModelData); - } - - @Override - protected void hideTooltip(@NotNull ItemStack itemStack) { - itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - } - - @Override - protected DyedItemColor getDye(int rgb) { - return new DyedItemColor(rgb, false); - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelPlaceholderLoader.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelPlaceholderLoader.java deleted file mode 100644 index d6c2c0b5..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/container/slot/placeholder/CustomModelPlaceholderLoader.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder; - -import net.minecraft.world.item.component.CustomModelData; - -import java.util.List; - -public class CustomModelPlaceholderLoader extends CustomModelBase { - - public CustomModelPlaceholderLoader() { - super(new CustomModelData(List.of(), List.of(), List.of("openinv:custom"), List.of())); - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/OpenPlayer.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/OpenPlayer.java deleted file mode 100644 index 3f1fe082..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/OpenPlayer.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.player; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; -import org.bukkit.craftbukkit.CraftServer; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class OpenPlayer extends com.lishid.openinv.internal.paper1_21_5.player.OpenPlayer { - - protected OpenPlayer( - CraftServer server, ServerPlayer entity, - PlayerManager manager - ) { - super(server, entity, manager); - } - - @Contract("null -> new") - @Override - protected @NotNull CompoundTag getWritableTag(@Nullable CompoundTag oldData) { - if (oldData == null) { - return new CompoundTag(); - } - - // Copy old data. This is a deep clone, so operating on it should be safe. - oldData = oldData.copy(); - - // Remove vanilla/server data that is not written every time. - oldData.getAllKeys() - .removeIf(key -> RESET_TAGS.contains(key) || key.startsWith("Bukkit")); - - return oldData; - } - -} diff --git a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/PlayerManager.java b/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/PlayerManager.java deleted file mode 100644 index 4172afd7..00000000 --- a/internal/paper1_21_4/src/main/java/com/lishid/openinv/internal/paper1_21_4/player/PlayerManager.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_4.player; - -import com.mojang.serialization.Dynamic; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.DimensionType; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.jetbrains.annotations.NotNull; - -import java.util.UUID; -import java.util.logging.Logger; - -public class PlayerManager extends com.lishid.openinv.internal.paper1_21_5.player.PlayerManager { - - public PlayerManager(@NotNull Logger logger) { - super(logger); - } - - @Override - protected void parseWorld(@NotNull ServerPlayer player, @NotNull CompoundTag loadedData) { - // See PlayerList#placeNewPlayer - World bukkitWorld; - if (loadedData.contains("WorldUUIDMost") && loadedData.contains("WorldUUIDLeast")) { - // Modern Bukkit world. - bukkitWorld = Bukkit.getServer().getWorld(new UUID(loadedData.getLong("WorldUUIDMost"), loadedData.getLong("WorldUUIDLeast"))); - } else if (loadedData.contains("world", net.minecraft.nbt.Tag.TAG_STRING)) { - // Legacy Bukkit world. - bukkitWorld = Bukkit.getServer().getWorld(loadedData.getString("world")); - } else { - // Vanilla player data. - DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, loadedData.get("Dimension"))) - .resultOrPartial(logger::warning) - .map(player.server::getLevel) - // If ServerLevel exists, set, otherwise move to spawn. - .ifPresentOrElse(player::setServerLevel, () -> spawnInDefaultWorld(player.server, player)); - return; - } - if (bukkitWorld == null) { - spawnInDefaultWorld(player.server, player); - return; - } - player.setServerLevel(((CraftWorld) bukkitWorld).getHandle()); - } - - @Override - protected void spawnInDefaultWorld(@NotNull MinecraftServer server, @NotNull ServerPlayer player) { - ServerLevel level = server.getLevel(Level.OVERWORLD); - if (level != null) { - // Adjust player to default spawn (in keeping with Paper handling) when world not found. - player.moveTo(player.adjustSpawnLocation(level, level.getSharedSpawnPos()).getBottomCenter(), level.getSharedSpawnAngle(), 0.0F); - player.spawnIn(level); - } else { - logger.warning("Tried to load player with invalid world when no fallback was available!"); - } - } - - @Override - protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlayer player) throws IllegalAccessException { - if (bukkitEntity == null) { - return; - } - - bukkitEntity.setAccessible(true); - bukkitEntity.set(player, new OpenPlayer(player.server.server, player, this)); - } - -} diff --git a/internal/paper1_21_5/build.gradle.kts b/internal/paper1_21_5/build.gradle.kts deleted file mode 100644 index 4c198112..00000000 --- a/internal/paper1_21_5/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -plugins { - alias(libs.plugins.paperweight) -} - -java { - toolchain.languageVersion = JavaLanguageVersion.of(21) -} - -tasks.withType().configureEach { - options.release = 21 -} - -dependencies { - implementation(project(":openinvapi")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvcommon")) { - exclude(group = "org.spigotmc", module = "spigot-api") - } - implementation(project(":openinvadaptercommon")) - implementation(project(":openinvadapterpaper1_21_8")) - - paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT") -} diff --git a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/InternalAccessor.java b/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/InternalAccessor.java deleted file mode 100644 index e0552bd2..00000000 --- a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/InternalAccessor.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_5; - -import com.lishid.openinv.internal.paper1_21_5.container.slot.placeholder.PlaceholderLoaderLegacyParse; -import com.lishid.openinv.internal.paper1_21_5.player.PlayerManager; -import com.lishid.openinv.util.lang.LanguageManager; -import org.bukkit.configuration.ConfigurationSection; -import org.jetbrains.annotations.NotNull; - -import java.util.logging.Level; -import java.util.logging.Logger; - -public class InternalAccessor extends com.lishid.openinv.internal.paper1_21_8.InternalAccessor { - - private final @NotNull PlayerManager manager; - - public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { - super(logger, lang); - manager = new PlayerManager(logger); - } - - @Override - public @NotNull PlayerManager getPlayerManager() { - return manager; - } - - @Override - public void reload(@NotNull ConfigurationSection config) { - ConfigurationSection placeholders = config.getConfigurationSection("placeholders"); - try { - // Reset placeholders to defaults and try to load configuration. - new PlaceholderLoaderLegacyParse().load(placeholders); - } catch (Exception e) { - logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e); - } - } - -} diff --git a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/container/slot/placeholder/PlaceholderLoaderLegacyParse.java b/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/container/slot/placeholder/PlaceholderLoaderLegacyParse.java deleted file mode 100644 index 3b11c697..00000000 --- a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/container/slot/placeholder/PlaceholderLoaderLegacyParse.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_5.container.slot.placeholder; - -import com.lishid.openinv.internal.common.container.slot.placeholder.PlaceholderLoader; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.craftbukkit.CraftRegistry; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; - -public class PlaceholderLoaderLegacyParse extends PlaceholderLoader { - - @Override - protected @NotNull ItemStack parse( - @Nullable ConfigurationSection section, - @NotNull String path, - @NotNull ItemStack defaultStack - ) throws Exception { - if (section == null) { - return defaultStack; - } - - String itemText = section.getString(path); - - if (itemText == null) { - return defaultStack; - } - - CompoundTag compoundTag = parseTag(itemText); - Optional parsed = ItemStack.parse(CraftRegistry.getMinecraftRegistry(), compoundTag); - return parsed.filter(itemStack -> !itemStack.isEmpty()).orElse(defaultStack); - } - -} diff --git a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/OpenPlayer.java b/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/OpenPlayer.java deleted file mode 100644 index 46b4aa87..00000000 --- a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/OpenPlayer.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_5.player; - -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; -import com.mojang.logging.LogUtils; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.storage.PlayerDataStorage; -import org.bukkit.craftbukkit.CraftServer; -import org.jetbrains.annotations.NotNull; - -import java.nio.file.Path; - -public class OpenPlayer extends BaseOpenPlayer { - - protected OpenPlayer(CraftServer server, ServerPlayer entity, PlayerManager manager) { - super(server, entity, manager); - } - - @Override - protected void trySave(ServerPlayer player) { - // See net.minecraft.world.level.storage.PlayerDataStorage#save(EntityHuman) - try { - PlayerDataStorage worldNBTStorage = player.server.getPlayerList().playerIo; - - CompoundTag oldData = isOnline() ? null : worldNBTStorage.load(player.getName().getString(), player.getStringUUID()).orElse(null); - CompoundTag playerData = getWritableTag(oldData); - - playerData = player.saveWithoutId(playerData); - - saveSafe(player, oldData, playerData, worldNBTStorage); - } catch (Exception e) { - LogUtils.getLogger().warn("Failed to save player data for {}: {}", player.getScoreboardName(), e); - } - } - - @Override - protected void safeReplaceFile(@NotNull Path dataFile, @NotNull Path tempFile, @NotNull Path backupFile) { - net.minecraft.Util.safeReplaceFile(dataFile, tempFile, backupFile); - } - - @Override - protected void remove(@NotNull CompoundTag tag, @NotNull String key) { - tag.remove(key); - } - -} diff --git a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/PlayerManager.java b/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/PlayerManager.java deleted file mode 100644 index 9637b062..00000000 --- a/internal/paper1_21_5/src/main/java/com/lishid/openinv/internal/paper1_21_5/player/PlayerManager.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.lishid.openinv.internal.paper1_21_5.player; - -import com.mojang.serialization.Dynamic; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.dimension.DimensionType; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Optional; -import java.util.UUID; -import java.util.logging.Logger; - -public class PlayerManager extends com.lishid.openinv.internal.paper1_21_8.player.PlayerManager { - - public PlayerManager(@NotNull Logger logger) { - super(logger); - } - - @Override - protected boolean loadData(@NotNull MinecraftServer server, @NotNull ServerPlayer player) { - // See CraftPlayer#loadData - CompoundTag loadedData = server.getPlayerList().playerIo.load(player).orElse(null); - - if (loadedData == null) { - // Exceptions with loading are logged. - return false; - } - - // Read basic data into the player. - player.load(loadedData); - // Game type settings are also loaded separately. - player.loadGameTypes(loadedData); - - // World is not loaded by ServerPlayer#load(CompoundTag) on Paper. - parseWorld(player, loadedData); - - return true; - } - - protected void parseWorld(@NotNull ServerPlayer player, @NotNull CompoundTag loadedData) { - // See PlayerList#placeNewPlayer - World bukkitWorld; - Optional msbs = loadedData.getLong("WorldUUIDMost"); - Optional lsbs = loadedData.getLong("WorldUUIDLeast"); - if (msbs.isPresent() && lsbs.isPresent()) { - // Modern Bukkit world. - bukkitWorld = Bukkit.getServer().getWorld(new UUID(msbs.get(), lsbs.get())); - } else { - Optional worldName = loadedData.getString("world"); - if (worldName.isPresent()) { - // Legacy Bukkit world. - bukkitWorld = Bukkit.getServer().getWorld(worldName.get()); - } else { - // Vanilla player data. - DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, loadedData.get("Dimension"))) - .resultOrPartial(logger::warning) - .map(player.server::getLevel) - // If ServerLevel exists, set, otherwise move to spawn. - .ifPresentOrElse(player::setServerLevel, () -> spawnInDefaultWorld(player.server, player)); - return; - } - } - if (bukkitWorld == null) { - spawnInDefaultWorld(player.server, player); - return; - } - player.setServerLevel(((CraftWorld) bukkitWorld).getHandle()); - } - - @Override - public @NotNull Player inject(@NotNull Player player) { - try { - ServerPlayer nmsPlayer = getHandle(player); - if (nmsPlayer.getBukkitEntity() instanceof OpenPlayer openPlayer) { - return openPlayer; - } - injectPlayer(nmsPlayer.server, nmsPlayer); - return nmsPlayer.getBukkitEntity(); - } catch (IllegalAccessException e) { - logger.log( - java.util.logging.Level.WARNING, - e, - () -> "Unable to inject ServerPlayer, certain player data may be lost when saving!" - ); - return player; - } - } - - @Override - protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlayer player) throws IllegalAccessException { - if (bukkitEntity == null) { - return; - } - - bukkitEntity.setAccessible(true); - - bukkitEntity.set(player, new OpenPlayer(player.server.server, player, this)); - } - -} diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index b503ff38..7c231437 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -14,10 +14,6 @@ dependencies { implementation(project(":openinvadaptercommon")) implementation(project(":openinvadapterpaper1_21_10")) implementation(project(":openinvadapterpaper1_21_8")) - implementation(project(":openinvadapterpaper1_21_5")) - implementation(project(":openinvadapterpaper1_21_4")) - implementation(project(":openinvadapterpaper1_21_3")) - implementation(project(":openinvadapterpaper1_21_1")) implementation(project(":openinvadapterspigot")) implementation(libs.planarwrappers) implementation(libs.folia.scheduler.wrapper) diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index e89c32e4..ef73573a 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -64,7 +64,6 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { } private @Nullable Accessor getAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { - // TODO reorganize internals, version handling if (!PAPER) { if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(26, 1)) && BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(26, 1, 1))) { @@ -75,7 +74,7 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { } Version maxSupported = Version.of(21, 1, 1); - Version minSupported = maxSupported;//Version.of(1, 21, 1); + Version minSupported = maxSupported;//Version.of(1, 21, 6); // Ensure version is in supported range. if (BukkitVersions.MINECRAFT.greaterThan(maxSupported) || BukkitVersions.MINECRAFT.lessThan(minSupported)) { @@ -90,26 +89,64 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { && BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 9))) { // 1.21.9, 1.21.10 return new com.lishid.openinv.internal.paper1_21_10.InternalAccessor(logger, lang); } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 8)) - && BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 6))) { // 1.21.6, 1.21.7, 1.21.8 - return new com.lishid.openinv.internal.paper1_21_8.InternalAccessor(logger, lang); - } - if (BukkitVersions.MINECRAFT.equals(Version.of(1, 21, 5))) { // 1.21.5 - return new com.lishid.openinv.internal.paper1_21_5.InternalAccessor(logger, lang); + return new com.lishid.openinv.internal.paper1_21_8.InternalAccessor(logger, lang); + } + + public String getReleasesLink() { + if (PAPER) { + // Paper 1.21.1+ + return getPaperReleaseLink(); } - if (BukkitVersions.MINECRAFT.equals(Version.of(1, 21, 4))) { // 1.21.4 - return new com.lishid.openinv.internal.paper1_21_4.InternalAccessor(logger, lang); + // Spigot 1.21.1+ + return getSpigotReleaseLink(); + } + + private String getPaperReleaseLink() { + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 6))) { + return "https://github.com/Jikoo/OpenInv/releases"; } - if (BukkitVersions.MINECRAFT.lessThan(Version.of(1, 21, 2))) { - // 1.21.1-1.21.2 placeholder format - return new com.lishid.openinv.internal.paper1_21_1.InternalAccessor(logger, lang); + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 1))) { + return "https://github.com/Jikoo/OpenInv/releases/tag/5.3.0"; } + return getLegacyReleaseLink(); + } - // 1.21.2, 1.21.3 - return new com.lishid.openinv.internal.paper1_21_3.InternalAccessor(logger, lang); + private String getSpigotReleaseLink() { + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(26, 1))) { + return "https://github.com/Jikoo/OpenInv/releases"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 11))) { // 1.21.11 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.3.0"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 10))) { // 1.21.10 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.15"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 9))) { // 1.21.9 + return "Unsupported; upgrade to 1.21.10: https://github.com/Jikoo/OpenInv/releases/tag/5.1.15"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 8))) { // 1.21.8, 1.21.7 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.13"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 6))) { // 1.21.6 + return "Unsupported; upgrade to 1.21.7: https://github.com/Jikoo/OpenInv/releases/tag/5.1.13"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 5))) { // 1.21.5 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.11"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 4))) { // 1.21.4 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.9"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 3))) { // 1.21.3 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.6"; + } + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 1))) { // 1.21.1, 1.21.2 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.3"; + } + // 1.21.0 and lower + return getLegacyReleaseLink(); } - public String getReleasesLink() { + private String getLegacyReleaseLink() { if (BukkitVersions.MINECRAFT.lessThan(Version.of(1, 4, 4))) { // Good luck. return "https://dev.bukkit.org/projects/openinv/files?&sort=datecreated"; } @@ -176,46 +213,8 @@ public String getReleasesLink() { if (BukkitVersions.MINECRAFT.equals(Version.of(1, 20, 5))) { // 1.20.5 return "Unsupported; upgrade to 1.20.6: https://github.com/Jikoo/OpenInv/releases/tag/5.1.2"; } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21))) { // 1.20.4, 1.20.6, 1.21 - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.2"; - } - if (!PAPER) { - return getSpigotReleaseLink(); - } - // Paper 1.21.1+ - return "https://github.com/Jikoo/OpenInv/releases"; - } - - private String getSpigotReleaseLink() { - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 2))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.3"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 3))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.6"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 4))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.9"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 5))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.11"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 6))) { - return "Unsupported; upgrade to 1.21.7: https://github.com/Jikoo/OpenInv/releases"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 8))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.13"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 9))) { - return "Unsupported; upgrade to 1.21.10: https://github.com/Jikoo/OpenInv/releases/tag/5.1.15"; - } - if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 10))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.15"; - } - if (BukkitVersions.MINECRAFT.lessThan(Version.of(26, 1))) { - return "https://github.com/Jikoo/OpenInv/releases/tag/5.3.0"; - } - - return "https://github.com/Jikoo/OpenInv/releases"; + // 1.20.4, 1.20.6, 1.21 + return "https://github.com/Jikoo/OpenInv/releases/tag/5.1.2"; } /** diff --git a/settings.gradle.kts b/settings.gradle.kts index efbf5eb0..06502b16 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,10 +21,6 @@ if (!java.lang.Boolean.getBoolean("jitpack")) { "common", "paper1_21_10", "paper1_21_8", - "paper1_21_5", - "paper1_21_4", - "paper1_21_3", - "paper1_21_1", "spigot" ) for (internal in internals) { From 1608d2b64433e43aeeab70c266c34352ecb5a472 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Wed, 8 Apr 2026 13:26:17 -0400 Subject: [PATCH 07/18] Bump resource pack version to current should probably consider dropping the legacy overlay too --- resource-pack/openinv-legibility-pack/pack.mcmeta | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resource-pack/openinv-legibility-pack/pack.mcmeta b/resource-pack/openinv-legibility-pack/pack.mcmeta index a8a915fc..f9b92606 100644 --- a/resource-pack/openinv-legibility-pack/pack.mcmeta +++ b/resource-pack/openinv-legibility-pack/pack.mcmeta @@ -2,16 +2,16 @@ "pack": { "description": "Improve OpenInv's legibility", "min_format": 34, - "max_format": [75, 0], + "max_format": [85, 0], "pack_format": 64, - "supported_formats": [ 34, 75 ] + "supported_formats": [ 34, 85 ] }, "overlays": { "entries": [ { "min_format": 44, - "max_format": [75, 0], - "formats": [ 44, 75 ], + "max_format": [85, 0], + "formats": [ 44, 85 ], "directory": "openinv_44" }, { From de881f7416cd6668994547e6bf8e8ee49cf59f22 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Thu, 9 Apr 2026 16:52:48 -0400 Subject: [PATCH 08/18] Rename common module, clean up syncher Removed a lot of shadowing that caused unnecessary desync risk with originals --- .../common/container/menu/OpenSyncMenu.java | 251 ------------------ internal/paper1_21_10/build.gradle.kts | 2 +- .../paper1_21_10/InternalAccessor.java | 2 +- .../paper1_21_10/container/OpenInventory.java | 4 +- .../paper1_21_10/player/OpenPlayer.java | 4 +- .../paper1_21_10/player/PlayerManager.java | 2 +- internal/paper1_21_8/build.gradle.kts | 2 +- .../paper1_21_8/InternalAccessor.java | 2 +- .../paper1_21_8/container/OpenInventory.java | 4 +- .../paper1_21_8/player/OpenPlayer.java | 2 +- .../paper1_21_8/player/PlayerManager.java | 4 +- .../{common => paper26_1}/build.gradle.kts | 0 .../internal/paper26_1}/InternalAccessor.java | 12 +- .../container/AnySilentContainer.java | 6 +- .../container/BaseOpenInventory.java | 32 +-- .../paper26_1}/container/OpenEnderChest.java | 8 +- .../paper26_1}/container/OpenInventory.java | 4 +- .../container/bukkit/OpenDummyInventory.java | 2 +- .../bukkit/OpenDummyPlayerInventory.java | 2 +- .../container/bukkit/OpenPlayerInventory.java | 4 +- .../bukkit/OpenPlayerInventorySelf.java | 4 +- .../container/menu/OpenChestMenu.java | 6 +- .../container/menu/OpenEnderChestMenu.java | 4 +- .../container/menu/OpenInventoryMenu.java | 14 +- .../container/menu/OpenSyncMenu.java | 166 ++++++++++++ .../paper26_1}/container/slot/Content.java | 2 +- .../container/slot/ContentCrafting.java | 6 +- .../container/slot/ContentCraftingResult.java | 4 +- .../container/slot/ContentCursor.java | 6 +- .../container/slot/ContentDrop.java | 6 +- .../container/slot/ContentEquipment.java | 4 +- .../container/slot/ContentList.java | 2 +- .../container/slot/ContentOffHand.java | 4 +- .../container/slot/ContentViewOnly.java | 2 +- .../container/slot/SlotPlaceholder.java | 2 +- .../container/slot/SlotViewOnly.java | 4 +- .../slot/placeholder/PlaceholderLoader.java | 2 +- .../placeholder/PlaceholderLoaderBase.java | 2 +- .../slot/placeholder/Placeholders.java | 4 +- .../paper26_1}/player/BaseOpenPlayer.java | 2 +- .../paper26_1}/player/OpenPlayer.java | 2 +- .../paper26_1}/player/PlayerManager.java | 8 +- plugin/build.gradle.kts | 2 +- .../lishid/openinv/util/InternalAccessor.java | 8 +- settings.gradle.kts | 2 +- 45 files changed, 268 insertions(+), 349 deletions(-) delete mode 100644 internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenSyncMenu.java rename internal/{common => paper26_1}/build.gradle.kts (100%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/InternalAccessor.java (85%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/AnySilentContainer.java (97%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/BaseOpenInventory.java (89%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/OpenEnderChest.java (95%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/OpenInventory.java (93%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/bukkit/OpenDummyInventory.java (98%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/bukkit/OpenDummyPlayerInventory.java (97%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/bukkit/OpenPlayerInventory.java (98%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/bukkit/OpenPlayerInventorySelf.java (79%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/menu/OpenChestMenu.java (97%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/menu/OpenEnderChestMenu.java (90%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/menu/OpenInventoryMenu.java (94%) create mode 100644 internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenSyncMenu.java rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/Content.java (96%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentCrafting.java (94%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentCraftingResult.java (89%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentCursor.java (93%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentDrop.java (89%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentEquipment.java (94%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentList.java (95%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentOffHand.java (92%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/ContentViewOnly.java (95%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/SlotPlaceholder.java (89%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/SlotViewOnly.java (95%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/placeholder/PlaceholderLoader.java (94%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/placeholder/PlaceholderLoaderBase.java (99%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/container/slot/placeholder/Placeholders.java (90%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/player/BaseOpenPlayer.java (99%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/player/OpenPlayer.java (96%) rename internal/{common/src/main/java/com/lishid/openinv/internal/common => paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1}/player/PlayerManager.java (97%) diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenSyncMenu.java b/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenSyncMenu.java deleted file mode 100644 index 612b2ec9..00000000 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenSyncMenu.java +++ /dev/null @@ -1,251 +0,0 @@ -package com.lishid.openinv.internal.common.container.menu; - -import com.google.common.base.Suppliers; -import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.InternalOwned; -import com.lishid.openinv.internal.common.container.slot.SlotPlaceholder; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import net.minecraft.network.HashedStack; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.ContainerListener; -import net.minecraft.world.inventory.ContainerSynchronizer; -import net.minecraft.world.inventory.DataSlot; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.RemoteSlot; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -/** - * An extension of {@link OpenChestMenu} that supports {@link SlotPlaceholder placeholders}. - */ -@SuppressWarnings("HidingField") // Revisit when removing 1.21.4 support -public abstract class OpenSyncMenu> - extends OpenChestMenu { - - // Syncher fields - protected @Nullable ContainerSynchronizer synchronizer; - protected final List dataSlots = new ArrayList<>(); - protected final IntList remoteDataSlots = new IntArrayList(); - protected final List containerListeners = new ArrayList<>(); - private RemoteSlot remoteCarried = RemoteSlot.PLACEHOLDER; - protected boolean suppressRemoteUpdates; - - protected OpenSyncMenu( - @NotNull MenuType type, - int containerCounter, - @NotNull T container, - @NotNull ServerPlayer viewer, - boolean viewOnly - ) { - super(type, containerCounter, container, viewer, viewOnly); - } - - // Overrides from here on are purely to modify the sync process to send placeholder items. - @Override - protected @NotNull Slot addSlot(@NotNull Slot slot) { - slot.index = this.slots.size(); - this.slots.add(slot); - this.lastSlots.add(ItemStack.EMPTY); - this.remoteSlots.add(this.synchronizer != null ? this.synchronizer.createSlot() : RemoteSlot.PLACEHOLDER); - return slot; - } - - @Override - protected @NotNull DataSlot addDataSlot(@NotNull DataSlot dataSlot) { - this.dataSlots.add(dataSlot); - this.remoteDataSlots.add(0); - return dataSlot; - } - - @Override - protected void addDataSlots(ContainerData containerData) { - for (int i = 0; i < containerData.getCount(); i++) { - this.addDataSlot(DataSlot.forContainer(containerData, i)); - } - } - - @Override - public void addSlotListener(@NotNull ContainerListener containerListener) { - if (!this.containerListeners.contains(containerListener)) { - this.containerListeners.add(containerListener); - this.broadcastChanges(); - } - } - - @Override - public void setSynchronizer(@NotNull ContainerSynchronizer containerSynchronizer) { - this.synchronizer = containerSynchronizer; - this.remoteCarried = synchronizer.createSlot(); - this.remoteSlots.replaceAll(slot -> synchronizer.createSlot()); - this.sendAllDataToRemote(); - } - - @Override - public void sendAllDataToRemote() { - List contentsCopy = new ArrayList<>(); - for (int index = 0; index < slots.size(); ++index) { - Slot slot = slots.get(index); - ItemStack itemStack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); - contentsCopy.add(itemStack); - this.remoteSlots.get(index).force(itemStack); - } - - remoteCarried.force(getCarried()); - - for (int index = 0; index < this.dataSlots.size(); ++index) { - this.remoteDataSlots.set(index, this.dataSlots.get(index).get()); - } - - if (this.synchronizer != null) { - this.synchronizer.sendInitialData(this, contentsCopy, this.getCarried().copy(), this.remoteDataSlots.toIntArray()); - } - } - - @Override - public void forceSlot(@NotNull Container container, int slot) { - int slotsIndex = this.findSlot(container, slot).orElse(-1); - if (slotsIndex != -1) { - ItemStack item = this.slots.get(slotsIndex).getItem(); - this.remoteSlots.get(slotsIndex).force(item); - if (this.synchronizer != null) { - this.synchronizer.sendSlotChange(this, slotsIndex, item.copy()); - } - } - } - - @Override - public void broadcastCarriedItem() { - ItemStack carried = this.getCarried(); - this.remoteCarried.force(carried); - if (this.synchronizer != null) { - this.synchronizer.sendCarriedChange(this, carried.copy()); - } - } - - @Override - public void removeSlotListener(@NotNull ContainerListener containerListener) { - this.containerListeners.remove(containerListener); - } - - @Override - public void broadcastChanges() { - for (int index = 0; index < this.slots.size(); ++index) { - Slot slot = this.slots.get(index); - ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); - Supplier supplier = Suppliers.memoize(itemstack::copy); - this.triggerSlotListeners(index, itemstack, supplier); - this.synchronizeSlotToRemote(index, itemstack, supplier); - } - - this.synchronizeCarriedToRemote(); - - for (int index = 0; index < this.dataSlots.size(); ++index) { - DataSlot dataSlot = this.dataSlots.get(index); - int j = dataSlot.get(); - if (dataSlot.checkAndClearUpdateFlag()) { - this.updateDataSlotListeners(index, j); - } - - this.synchronizeDataSlotToRemote(index, j); - } - } - - @Override - public void broadcastFullState() { - for (int index = 0; index < this.slots.size(); ++index) { - ItemStack itemstack = this.slots.get(index).getItem(); - this.triggerSlotListeners(index, itemstack, itemstack::copy); - } - - for (int index = 0; index < this.dataSlots.size(); ++index) { - DataSlot containerproperty = this.dataSlots.get(index); - if (containerproperty.checkAndClearUpdateFlag()) { - this.updateDataSlotListeners(index, containerproperty.get()); - } - } - - this.sendAllDataToRemote(); - } - - private void updateDataSlotListeners(int i, int j) { - for (ContainerListener containerListener : this.containerListeners) { - containerListener.dataChanged(this, i, j); - } - } - - @Override - public void triggerSlotListeners(int index, @NotNull ItemStack itemStack, @NotNull Supplier supplier) { - ItemStack itemStack1 = this.lastSlots.get(index); - if (!ItemStack.matches(itemStack1, itemStack)) { - ItemStack itemStack2 = supplier.get(); - this.lastSlots.set(index, itemStack2); - - for (ContainerListener containerListener : this.containerListeners) { - containerListener.slotChanged(this, index, itemStack2); - } - } - } - - @Override - public void synchronizeSlotToRemote(int i, @NotNull ItemStack itemStack, @NotNull Supplier supplier) { - if (!this.suppressRemoteUpdates) { - RemoteSlot slot = this.remoteSlots.get(i); - if (!slot.matches(itemStack)) { - slot.force(itemStack); - if (this.synchronizer != null) { - this.synchronizer.sendSlotChange(this, i, supplier.get()); - } - } - } - } - - private void synchronizeDataSlotToRemote(int index, int value) { - if (!this.suppressRemoteUpdates) { - int existing = this.remoteDataSlots.getInt(index); - if (existing != value) { - this.remoteDataSlots.set(index, value); - if (this.synchronizer != null) { - this.synchronizer.sendDataChange(this, index, value); - } - } - } - } - - private void synchronizeCarriedToRemote() { - if (!this.suppressRemoteUpdates) { - ItemStack carried = this.getCarried(); - if (!this.remoteCarried.matches(carried)) { - this.remoteCarried.force(carried); - if (this.synchronizer != null) { - this.synchronizer.sendCarriedChange(this, carried.copy()); - } - } - } - } - - @Override - public void setRemoteCarried(@NotNull HashedStack stack) { - this.remoteCarried.receive(stack); - } - - @Override - public void suppressRemoteUpdates() { - this.suppressRemoteUpdates = true; - } - - @Override - public void resumeRemoteUpdates() { - this.suppressRemoteUpdates = false; - } - -} diff --git a/internal/paper1_21_10/build.gradle.kts b/internal/paper1_21_10/build.gradle.kts index 38949bd9..b143a17e 100644 --- a/internal/paper1_21_10/build.gradle.kts +++ b/internal/paper1_21_10/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { implementation(project(":openinvcommon")) { exclude(group = "org.spigotmc", module = "spigot-api") } - implementation(project(":openinvadaptercommon")) + implementation(project(":openinvadapterpaper26_1")) paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") } diff --git a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java index b6333bf0..c49856da 100644 --- a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java +++ b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java @@ -9,7 +9,7 @@ import java.util.logging.Logger; -public class InternalAccessor extends com.lishid.openinv.internal.common.InternalAccessor { +public class InternalAccessor extends com.lishid.openinv.internal.paper26_1.InternalAccessor { private final @NotNull PlayerManager manager; diff --git a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java index 3210726c..488baca9 100644 --- a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java +++ b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java @@ -1,7 +1,7 @@ package com.lishid.openinv.internal.paper1_21_10.container; -import com.lishid.openinv.internal.common.container.BaseOpenInventory; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FontDescription; diff --git a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/OpenPlayer.java b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/OpenPlayer.java index 0595e9b0..3a4041be 100644 --- a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/OpenPlayer.java +++ b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/OpenPlayer.java @@ -1,6 +1,6 @@ package com.lishid.openinv.internal.paper1_21_10.player; -import com.lishid.openinv.internal.common.player.PlayerManager; +import com.lishid.openinv.internal.paper26_1.player.PlayerManager; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; import org.bukkit.craftbukkit.CraftServer; @@ -8,7 +8,7 @@ import java.nio.file.Path; -public class OpenPlayer extends com.lishid.openinv.internal.common.player.OpenPlayer { +public class OpenPlayer extends com.lishid.openinv.internal.paper26_1.player.OpenPlayer { protected OpenPlayer( CraftServer server, diff --git a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/PlayerManager.java b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/PlayerManager.java index 3382bfaf..507d80fc 100644 --- a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/PlayerManager.java +++ b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/player/PlayerManager.java @@ -6,7 +6,7 @@ import java.util.logging.Logger; -public class PlayerManager extends com.lishid.openinv.internal.common.player.PlayerManager { +public class PlayerManager extends com.lishid.openinv.internal.paper26_1.player.PlayerManager { public PlayerManager(@NotNull Logger logger) { super(logger); diff --git a/internal/paper1_21_8/build.gradle.kts b/internal/paper1_21_8/build.gradle.kts index deeebd8c..d30bb1d1 100644 --- a/internal/paper1_21_8/build.gradle.kts +++ b/internal/paper1_21_8/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { implementation(project(":openinvcommon")) { exclude(group = "org.spigotmc", module = "spigot-api") } - implementation(project(":openinvadaptercommon")) + implementation(project(":openinvadapterpaper26_1")) paperweight.paperDevBundle("1.21.8-R0.1-SNAPSHOT") } diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java index 0c68893d..ab3db0ed 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java @@ -9,7 +9,7 @@ import java.util.logging.Logger; -public class InternalAccessor extends com.lishid.openinv.internal.common.InternalAccessor { +public class InternalAccessor extends com.lishid.openinv.internal.paper26_1.InternalAccessor { private final @NotNull PlayerManager manager; diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java index 076d69a8..0b6ff43b 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java @@ -1,7 +1,7 @@ package com.lishid.openinv.internal.paper1_21_8.container; -import com.lishid.openinv.internal.common.container.BaseOpenInventory; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java index 0cad37a7..4e045292 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java @@ -1,6 +1,6 @@ package com.lishid.openinv.internal.paper1_21_8.player; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import com.mojang.logging.LogUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java index dc3ad219..b997c21e 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java @@ -1,6 +1,6 @@ package com.lishid.openinv.internal.paper1_21_8.player; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import com.lishid.openinv.util.JulLoggerAdapter; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -15,7 +15,7 @@ import java.util.logging.Logger; -public class PlayerManager extends com.lishid.openinv.internal.common.player.PlayerManager { +public class PlayerManager extends com.lishid.openinv.internal.paper26_1.player.PlayerManager { public PlayerManager(@NotNull Logger logger) { super(logger); diff --git a/internal/common/build.gradle.kts b/internal/paper26_1/build.gradle.kts similarity index 100% rename from internal/common/build.gradle.kts rename to internal/paper26_1/build.gradle.kts diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/InternalAccessor.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/InternalAccessor.java similarity index 85% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/InternalAccessor.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/InternalAccessor.java index 16218663..e31407a7 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/InternalAccessor.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/InternalAccessor.java @@ -1,15 +1,15 @@ -package com.lishid.openinv.internal.common; +package com.lishid.openinv.internal.paper26_1; import com.lishid.openinv.internal.Accessor; import com.lishid.openinv.internal.IAnySilentContainer; import com.lishid.openinv.internal.ISpecialEnderChest; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.internal.ISpecialPlayerInventory; -import com.lishid.openinv.internal.common.container.AnySilentContainer; -import com.lishid.openinv.internal.common.container.OpenEnderChest; -import com.lishid.openinv.internal.common.container.OpenInventory; -import com.lishid.openinv.internal.common.container.slot.placeholder.PlaceholderLoader; -import com.lishid.openinv.internal.common.player.PlayerManager; +import com.lishid.openinv.internal.paper26_1.container.AnySilentContainer; +import com.lishid.openinv.internal.paper26_1.container.OpenEnderChest; +import com.lishid.openinv.internal.paper26_1.container.OpenInventory; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.PlaceholderLoader; +import com.lishid.openinv.internal.paper26_1.player.PlayerManager; import com.lishid.openinv.util.lang.LanguageManager; import net.minecraft.world.Container; import org.bukkit.configuration.ConfigurationSection; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/AnySilentContainer.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/AnySilentContainer.java similarity index 97% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/AnySilentContainer.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/AnySilentContainer.java index 2a12bcef..26f8d75f 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/AnySilentContainer.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/AnySilentContainer.java @@ -14,11 +14,11 @@ * along with this program. If not, see . */ -package com.lishid.openinv.internal.common.container; +package com.lishid.openinv.internal.paper26_1.container; import com.lishid.openinv.internal.AnySilentContainerBase; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.common.player.PlayerManager; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.player.PlayerManager; import com.lishid.openinv.util.ReflectionHelper; import com.lishid.openinv.util.lang.LanguageManager; import net.minecraft.core.BlockPos; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/BaseOpenInventory.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/BaseOpenInventory.java similarity index 89% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/BaseOpenInventory.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/BaseOpenInventory.java index 4987afd3..52096805 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/BaseOpenInventory.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/BaseOpenInventory.java @@ -1,22 +1,22 @@ -package com.lishid.openinv.internal.common.container; +package com.lishid.openinv.internal.paper26_1.container; import com.lishid.openinv.internal.ISpecialPlayerInventory; import com.lishid.openinv.internal.InternalOwned; -import com.lishid.openinv.internal.common.container.bukkit.OpenPlayerInventory; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.common.container.menu.OpenInventoryMenu; -import com.lishid.openinv.internal.common.container.slot.Content; -import com.lishid.openinv.internal.common.container.slot.ContentCrafting; -import com.lishid.openinv.internal.common.container.slot.ContentCraftingResult; -import com.lishid.openinv.internal.common.container.slot.ContentCursor; -import com.lishid.openinv.internal.common.container.slot.ContentDrop; -import com.lishid.openinv.internal.common.container.slot.ContentEquipment; -import com.lishid.openinv.internal.common.container.slot.ContentList; -import com.lishid.openinv.internal.common.container.slot.ContentOffHand; -import com.lishid.openinv.internal.common.container.slot.ContentViewOnly; -import com.lishid.openinv.internal.common.container.slot.SlotViewOnly; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.common.player.PlayerManager; +import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenPlayerInventory; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenInventoryMenu; +import com.lishid.openinv.internal.paper26_1.container.slot.Content; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentCrafting; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentCraftingResult; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentCursor; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentDrop; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentEquipment; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentList; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentOffHand; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentViewOnly; +import com.lishid.openinv.internal.paper26_1.container.slot.SlotViewOnly; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.player.PlayerManager; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/OpenEnderChest.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/OpenEnderChest.java similarity index 95% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/OpenEnderChest.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/OpenEnderChest.java index 284bf7ab..5b1411a4 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/OpenEnderChest.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/OpenEnderChest.java @@ -1,10 +1,10 @@ -package com.lishid.openinv.internal.common.container; +package com.lishid.openinv.internal.paper26_1.container; import com.lishid.openinv.internal.ISpecialEnderChest; import com.lishid.openinv.internal.InternalOwned; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; -import com.lishid.openinv.internal.common.container.menu.OpenEnderChestMenu; -import com.lishid.openinv.internal.common.player.PlayerManager; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenEnderChestMenu; +import com.lishid.openinv.internal.paper26_1.player.PlayerManager; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/OpenInventory.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/OpenInventory.java similarity index 93% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/OpenInventory.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/OpenInventory.java index 641b4d54..7fdeff04 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/OpenInventory.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/OpenInventory.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container; +package com.lishid.openinv.internal.paper26_1.container; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FontDescription; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenDummyInventory.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenDummyInventory.java similarity index 98% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenDummyInventory.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenDummyInventory.java index e505c8c1..0c491a78 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenDummyInventory.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenDummyInventory.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.bukkit; +package com.lishid.openinv.internal.paper26_1.container.bukkit; import com.lishid.openinv.internal.ViewOnly; import net.minecraft.world.Container; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenDummyPlayerInventory.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenDummyPlayerInventory.java similarity index 97% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenDummyPlayerInventory.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenDummyPlayerInventory.java index 2c482710..a7be3663 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenDummyPlayerInventory.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenDummyPlayerInventory.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.bukkit; +package com.lishid.openinv.internal.paper26_1.container.bukkit; import net.minecraft.world.Container; import org.bukkit.Material; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenPlayerInventory.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenPlayerInventory.java similarity index 98% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenPlayerInventory.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenPlayerInventory.java index 9ef9a468..673346df 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenPlayerInventory.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenPlayerInventory.java @@ -1,7 +1,7 @@ -package com.lishid.openinv.internal.common.container.bukkit; +package com.lishid.openinv.internal.paper26_1.container.bukkit; import com.google.common.base.Preconditions; -import com.lishid.openinv.internal.common.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; import net.minecraft.core.NonNullList; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Inventory; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenPlayerInventorySelf.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenPlayerInventorySelf.java similarity index 79% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenPlayerInventorySelf.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenPlayerInventorySelf.java index 326a6f51..c5546997 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/bukkit/OpenPlayerInventorySelf.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/bukkit/OpenPlayerInventorySelf.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.bukkit; +package com.lishid.openinv.internal.paper26_1.container.bukkit; -import com.lishid.openinv.internal.common.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java similarity index 97% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java index d5f79b31..0914c33e 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenChestMenu.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java @@ -1,9 +1,9 @@ -package com.lishid.openinv.internal.common.container.menu; +package com.lishid.openinv.internal.paper26_1.container.menu; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.internal.InternalOwned; -import com.lishid.openinv.internal.common.container.bukkit.OpenDummyInventory; -import com.lishid.openinv.internal.common.container.slot.SlotViewOnly; +import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenDummyInventory; +import com.lishid.openinv.internal.paper26_1.container.slot.SlotViewOnly; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenEnderChestMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java similarity index 90% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenEnderChestMenu.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java index f0e70d33..2f80ebb0 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenEnderChestMenu.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.menu; +package com.lishid.openinv.internal.paper26_1.container.menu; -import com.lishid.openinv.internal.common.container.OpenEnderChest; +import com.lishid.openinv.internal.paper26_1.container.OpenEnderChest; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenInventoryMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java similarity index 94% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenInventoryMenu.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java index 52ca724e..5289d5f4 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/menu/OpenInventoryMenu.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java @@ -1,12 +1,12 @@ -package com.lishid.openinv.internal.common.container.menu; +package com.lishid.openinv.internal.paper26_1.container.menu; import com.google.common.base.Preconditions; -import com.lishid.openinv.internal.common.container.BaseOpenInventory; -import com.lishid.openinv.internal.common.container.bukkit.OpenDummyPlayerInventory; -import com.lishid.openinv.internal.common.container.bukkit.OpenPlayerInventorySelf; -import com.lishid.openinv.internal.common.container.slot.ContentDrop; -import com.lishid.openinv.internal.common.container.slot.ContentEquipment; -import com.lishid.openinv.internal.common.container.slot.SlotViewOnly; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenDummyPlayerInventory; +import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenPlayerInventorySelf; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentDrop; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentEquipment; +import com.lishid.openinv.internal.paper26_1.container.slot.SlotViewOnly; import com.lishid.openinv.util.Permissions; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EquipmentSlot; diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenSyncMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenSyncMenu.java new file mode 100644 index 00000000..5e26c733 --- /dev/null +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenSyncMenu.java @@ -0,0 +1,166 @@ +package com.lishid.openinv.internal.paper26_1.container.menu; + +import com.google.common.base.Suppliers; +import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InternalOwned; +import com.lishid.openinv.internal.paper26_1.container.slot.SlotPlaceholder; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.inventory.ContainerSynchronizer; +import net.minecraft.world.inventory.DataSlot; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.RemoteSlot; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * An extension of {@link OpenChestMenu} that supports {@link SlotPlaceholder placeholders}. + */ +@NullMarked +public abstract class OpenSyncMenu> + extends OpenChestMenu { + + // Syncher fields required to send placeholder items. + // All fields intentionally shadow AbstractContainerMenu fields so that warnings + // will be generated if they are no longer necessary. + protected @Nullable ContainerSynchronizer synchronizer; + protected final List listeners = new ArrayList<>(); + private @Nullable RemoteSlot remoteCarried = RemoteSlot.PLACEHOLDER; + protected boolean suppressRemoteUpdates; + + protected OpenSyncMenu( + MenuType type, + int containerCounter, + T container, + ServerPlayer viewer, + boolean viewOnly + ) { + super(type, containerCounter, container, viewer, viewOnly); + } + + @Override + public void broadcastChanges() { + for (int index = 0; index < this.slots.size(); ++index) { + Slot slot = this.slots.get(index); + ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); + Supplier supplier = Suppliers.memoize(itemstack::copy); + this.triggerSlotListeners(index, itemstack, supplier); + this.synchronizeSlotToRemote(index, itemstack, supplier); + } + + // See private synchronizeCarriedToRemote + if (!suppressRemoteUpdates && !getRemoteCarried().matches(getCarried())) { + this.broadcastCarriedItem(); + } + + for (int index = 0; index < this.dataSlots.size(); ++index) { + DataSlot dataSlot = this.dataSlots.get(index); + int current = dataSlot.get(); + if (dataSlot.checkAndClearUpdateFlag()) { + // See private updateDataSlotListeners + for (ContainerListener containerListener : this.listeners) { + containerListener.dataChanged(this, index, current); + } + } + + // See private synchronizeDataSlotToRemote + if (!suppressRemoteUpdates && remoteDataSlots.getInt(index) != current) { + remoteDataSlots.set(index, current); + if (synchronizer != null) { + synchronizer.sendDataChange(this, index, current); + } + } + } + } + + @Override + public void sendAllDataToRemote() { + List contentsCopy = new ArrayList<>(); + for (int index = 0; index < slots.size(); ++index) { + Slot slot = slots.get(index); + ItemStack itemStack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); + contentsCopy.add(itemStack); + this.remoteSlots.get(index).force(itemStack); + } + + getRemoteCarried().force(getCarried()); + + for (int index = 0; index < this.dataSlots.size(); ++index) { + this.remoteDataSlots.set(index, this.dataSlots.get(index).get()); + } + + if (this.synchronizer != null) { + this.synchronizer.sendInitialData(this, contentsCopy, this.getCarried().copy(), this.remoteDataSlots.toIntArray()); + this.synchronizer.sendOffHandSlotChange(); + } + } + + protected RemoteSlot getRemoteCarried() { + if (remoteCarried != null) { + return remoteCarried; + } + + try { + Field remoteCarried = AbstractContainerMenu.class.getDeclaredField("remoteCarried"); + remoteCarried.setAccessible(true); + Object slot = remoteCarried.get(this); + if (slot instanceof RemoteSlot remoteSlot) { + this.remoteCarried = remoteSlot; + } else { + this.remoteCarried = RemoteSlot.PLACEHOLDER; + } + } catch (NoSuchFieldException | IllegalAccessException e) { + remoteCarried = RemoteSlot.PLACEHOLDER; + } + + return remoteCarried; + } + + // Overrides from here on are purely to capture the contents of fields that aren't exposed. + // Note that super calls should likely always be last! Some send data to remotes after updating state. + @Override + public void addSlotListener(ContainerListener containerListener) { + if (!this.listeners.contains(containerListener)) { + this.listeners.add(containerListener); + } + super.addSlotListener(containerListener); + } + + @Override + public void setSynchronizer(ContainerSynchronizer containerSynchronizer) { + this.synchronizer = containerSynchronizer; + // Unset carried slot so we re-capture it when sending slots. + // setSynchronizer calls sendAllDataToRemote, so we can't just do the reflection here once after the fact. + this.remoteCarried = null; + super.setSynchronizer(containerSynchronizer); + } + + @Override + public void removeSlotListener(ContainerListener containerListener) { + this.listeners.remove(containerListener); + super.removeSlotListener(containerListener); + } + + @Override + public void suppressRemoteUpdates() { + this.suppressRemoteUpdates = true; + super.suppressRemoteUpdates(); + } + + @Override + public void resumeRemoteUpdates() { + this.suppressRemoteUpdates = false; + super.resumeRemoteUpdates(); + } + +} diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/Content.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/Content.java similarity index 96% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/Content.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/Content.java index 9b63ed54..225c5a8e 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/Content.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/Content.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCrafting.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java similarity index 94% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCrafting.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java index ee8b370f..11b66894 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCrafting.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java @@ -1,7 +1,7 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCraftingResult.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCraftingResult.java similarity index 89% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCraftingResult.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCraftingResult.java index e930c8e8..0db3071c 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCraftingResult.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCraftingResult.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.InventoryMenu; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCursor.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java similarity index 93% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCursor.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java index 2693698d..58bac718 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentCursor.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java @@ -1,7 +1,7 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentDrop.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java similarity index 89% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentDrop.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java index 7ed6e700..cff390a3 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentDrop.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java @@ -1,7 +1,7 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentEquipment.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentEquipment.java similarity index 94% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentEquipment.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentEquipment.java index 9087232d..0681bcb1 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentEquipment.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentEquipment.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.EntityEquipment; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentList.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentList.java similarity index 95% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentList.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentList.java index 5748c51a..289bd456 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentList.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentList.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentOffHand.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java similarity index 92% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentOffHand.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java index ba1db443..d4d9f418 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentOffHand.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentViewOnly.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentViewOnly.java similarity index 95% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentViewOnly.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentViewOnly.java index 319ef0e5..efeea121 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/ContentViewOnly.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentViewOnly.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/SlotPlaceholder.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/SlotPlaceholder.java similarity index 89% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/SlotPlaceholder.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/SlotPlaceholder.java index 7e7a79ad..84c2cc76 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/SlotPlaceholder.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/SlotPlaceholder.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/SlotViewOnly.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/SlotViewOnly.java similarity index 95% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/SlotViewOnly.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/SlotViewOnly.java index 3fe82fd9..a9c2ba80 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/SlotViewOnly.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/SlotViewOnly.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.slot; +package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders; +import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/PlaceholderLoader.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/PlaceholderLoader.java similarity index 94% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/PlaceholderLoader.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/PlaceholderLoader.java index c859e7d6..90efc9a0 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/PlaceholderLoader.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/PlaceholderLoader.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.slot.placeholder; +package com.lishid.openinv.internal.paper26_1.container.slot.placeholder; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/PlaceholderLoaderBase.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/PlaceholderLoaderBase.java similarity index 99% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/PlaceholderLoaderBase.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/PlaceholderLoaderBase.java index 4de686d0..40188258 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/PlaceholderLoaderBase.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/PlaceholderLoaderBase.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.container.slot.placeholder; +package com.lishid.openinv.internal.paper26_1.container.slot.placeholder; import com.mojang.serialization.DataResult; import net.minecraft.core.Registry; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/Placeholders.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java similarity index 90% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/Placeholders.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java index b9fcd7cb..1f938012 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/container/slot/placeholder/Placeholders.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java @@ -1,6 +1,6 @@ -package com.lishid.openinv.internal.common.container.slot.placeholder; +package com.lishid.openinv.internal.paper26_1.container.slot.placeholder; -import com.lishid.openinv.internal.common.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/player/BaseOpenPlayer.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java similarity index 99% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/player/BaseOpenPlayer.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java index 77e9fb50..793d8b1f 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/player/BaseOpenPlayer.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.player; +package com.lishid.openinv.internal.paper26_1.player; import com.lishid.openinv.event.OpenEvents; import net.minecraft.nbt.CompoundTag; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/player/OpenPlayer.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java similarity index 96% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/player/OpenPlayer.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java index 80f87129..9429dec2 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/player/OpenPlayer.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.common.player; +package com.lishid.openinv.internal.paper26_1.player; import com.mojang.logging.LogUtils; import net.minecraft.nbt.CompoundTag; diff --git a/internal/common/src/main/java/com/lishid/openinv/internal/common/player/PlayerManager.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java similarity index 97% rename from internal/common/src/main/java/com/lishid/openinv/internal/common/player/PlayerManager.java rename to internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java index b43348a5..26550305 100644 --- a/internal/common/src/main/java/com/lishid/openinv/internal/common/player/PlayerManager.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java @@ -1,9 +1,9 @@ -package com.lishid.openinv.internal.common.player; +package com.lishid.openinv.internal.paper26_1.player; import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.common.container.BaseOpenInventory; -import com.lishid.openinv.internal.common.container.OpenEnderChest; -import com.lishid.openinv.internal.common.container.menu.OpenChestMenu; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.OpenEnderChest; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import com.lishid.openinv.util.JulLoggerAdapter; import com.mojang.authlib.GameProfile; import io.papermc.paper.adventure.PaperAdventure; diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 7c231437..17187409 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -11,7 +11,7 @@ dependencies { compileOnly(libs.spigotapi) implementation(project(":openinvapi")) implementation(project(":openinvcommon")) - implementation(project(":openinvadaptercommon")) + implementation(project(":openinvadapterpaper26_1")) implementation(project(":openinvadapterpaper1_21_10")) implementation(project(":openinvadapterpaper1_21_8")) implementation(project(":openinvadapterspigot")) diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index ef73573a..4e5a0a67 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -74,7 +74,7 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { } Version maxSupported = Version.of(21, 1, 1); - Version minSupported = maxSupported;//Version.of(1, 21, 6); + Version minSupported = Version.of(1, 21, 6); // Ensure version is in supported range. if (BukkitVersions.MINECRAFT.greaterThan(maxSupported) || BukkitVersions.MINECRAFT.lessThan(minSupported)) { @@ -83,7 +83,11 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { // Paper or a Paper fork, can use Mojang-mapped internals. if (BukkitVersions.MINECRAFT.equals(maxSupported)) { // 1.21.11 - return new com.lishid.openinv.internal.common.InternalAccessor(logger, lang); + return new com.lishid.openinv.internal.paper26_1.InternalAccessor(logger, lang); + } + if (BukkitVersions.MINECRAFT.equals(Version.of(1, 21, 11))) { + // TODO + return null; } if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 10)) && BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 9))) { // 1.21.9, 1.21.10 diff --git a/settings.gradle.kts b/settings.gradle.kts index 06502b16..ba87c4c1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,7 +18,7 @@ if (!java.lang.Boolean.getBoolean("jitpack")) { project(":openinvcommon").projectDir = file("common") val internals = listOf( - "common", + "paper26_1", "paper1_21_10", "paper1_21_8", "spigot" From 27f3165f81e398d3e73b2502d20b022e90cf5976 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 10 Apr 2026 13:10:40 -0400 Subject: [PATCH 09/18] Move to NullMarked Should probably broadly apply this to minimize noisy diffs later, but oh well. --- .../paper26_1/player/PlayerManager.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java index 26550305..eb8506c9 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java @@ -33,20 +33,21 @@ import org.bukkit.craftbukkit.event.CraftEventFactory; import org.bukkit.entity.Player; import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.lang.reflect.Field; import java.util.Optional; import java.util.UUID; import java.util.logging.Logger; +@NullMarked public class PlayerManager implements com.lishid.openinv.internal.PlayerManager { - protected final @NotNull Logger logger; + protected final Logger logger; protected @Nullable Field bukkitEntity; - public PlayerManager(@NotNull Logger logger) { + public PlayerManager(Logger logger) { this.logger = logger; try { bukkitEntity = Entity.class.getDeclaredField("bukkitEntity"); @@ -57,7 +58,7 @@ public PlayerManager(@NotNull Logger logger) { } } - public static @NotNull ServerPlayer getHandle(final Player player) { + public static ServerPlayer getHandle(final Player player) { if (player instanceof CraftPlayer craftPlayer) { return craftPlayer.getHandle(); } @@ -78,7 +79,7 @@ public PlayerManager(@NotNull Logger logger) { } @Override - public @Nullable Player loadPlayer(@NotNull final OfflinePlayer offline) { + public @Nullable Player loadPlayer(final OfflinePlayer offline) { if (!(Bukkit.getServer() instanceof CraftServer craftServer)) { return null; } @@ -105,10 +106,10 @@ public PlayerManager(@NotNull Logger logger) { return null; } - protected @NotNull ServerPlayer createNewPlayer( - @NotNull MinecraftServer server, - @NotNull ServerLevel worldServer, - @NotNull final OfflinePlayer offline + protected ServerPlayer createNewPlayer( + MinecraftServer server, + ServerLevel worldServer, + final OfflinePlayer offline ) { // See net.minecraft.server.players.PlayerList#canPlayerLogin(ServerLoginPacketListenerImpl, GameProfile) // See net.minecraft.server.network.ServerLoginPacketListenerImpl#handleHello(ServerboundHelloPacket) @@ -143,7 +144,7 @@ public PlayerManager(@NotNull Logger logger) { return entity; } - protected boolean loadData(@NotNull MinecraftServer server, @NotNull ServerPlayer player) { + protected boolean loadData(MinecraftServer server, ServerPlayer player) { // See CraftPlayer#loadData try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), new JulLoggerAdapter(logger))) { @@ -167,9 +168,9 @@ protected boolean loadData(@NotNull MinecraftServer server, @NotNull ServerPlaye } protected void parseWorld( - @NotNull MinecraftServer server, - @NotNull ServerPlayer player, - @NotNull ValueInput loadedData + MinecraftServer server, + ServerPlayer player, + ValueInput loadedData ) { // See PlayerList#placeNewPlayer World bukkitWorld; @@ -188,7 +189,7 @@ protected void parseWorld( player.setServerLevel(((CraftWorld) bukkitWorld).getHandle()); } - protected void spawnInDefaultWorld(@NotNull MinecraftServer server, @NotNull ServerPlayer player) { + protected void spawnInDefaultWorld(MinecraftServer server, ServerPlayer player) { ServerLevel level = server.getLevel(Level.OVERWORLD); if (level != null) { // Adjust player to default spawn (in keeping with Paper handling) when world not found. @@ -200,7 +201,7 @@ protected void spawnInDefaultWorld(@NotNull MinecraftServer server, @NotNull Ser } } - protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlayer player) throws IllegalAccessException { + protected void injectPlayer(MinecraftServer server, ServerPlayer player) throws IllegalAccessException { if (bukkitEntity == null) { return; } @@ -211,7 +212,7 @@ protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlay } @Override - public @NotNull Player inject(@NotNull Player player) { + public Player inject(Player player) { try { ServerPlayer nmsPlayer = getHandle(player); if (nmsPlayer.getBukkitEntity() instanceof BaseOpenPlayer openPlayer) { @@ -232,7 +233,8 @@ protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlay @Override public @Nullable InventoryView openInventory( - @NotNull Player bukkitPlayer, @NotNull ISpecialInventory inventory, + Player bukkitPlayer, + ISpecialInventory inventory, boolean viewOnly ) { ServerPlayer player = getHandle(bukkitPlayer); From c49d9054c49d661be8724a6568724a00a4d2d41a Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 10 Apr 2026 19:32:26 -0400 Subject: [PATCH 10/18] Load Bukkit data into injected player Probably addresses #389 --- .../paper26_1/player/PlayerManager.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java index eb8506c9..4cdbb28e 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java @@ -6,6 +6,7 @@ import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import com.lishid.openinv.util.JulLoggerAdapter; import com.mojang.authlib.GameProfile; +import com.mojang.logging.LogUtils; import io.papermc.paper.adventure.PaperAdventure; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -22,7 +23,9 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.Server; @@ -218,9 +221,26 @@ public Player inject(Player player) { if (nmsPlayer.getBukkitEntity() instanceof BaseOpenPlayer openPlayer) { return openPlayer; } - MinecraftServer server = nmsPlayer.level().getServer(); - injectPlayer(server, nmsPlayer); - return nmsPlayer.getBukkitEntity(); + + org.slf4j.Logger logger = LogUtils.getLogger(); + + try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(nmsPlayer.problemPath(), logger)) { + CompoundTag extraData = new CompoundTag(); + + // Copy extra data out of existing player. + ValueOutput output = TagValueOutput.createWrappingWithContext(scopedCollector, nmsPlayer.registryAccess(), extraData); + nmsPlayer.getBukkitEntity().setExtraData(output); + + MinecraftServer server = nmsPlayer.level().getServer(); + injectPlayer(server, nmsPlayer); + CraftPlayer newPlayer = nmsPlayer.getBukkitEntity(); + + // Set extra data in new player. + ValueInput input = TagValueInput.create(scopedCollector, nmsPlayer.registryAccess(), extraData); + newPlayer.readExtraData(input); + + return newPlayer; + } } catch (IllegalAccessException e) { logger.log( java.util.logging.Level.WARNING, From 7f85c55fd0ee6e91426ad6129f24d36469eb440d Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 10 Apr 2026 19:50:52 -0400 Subject: [PATCH 11/18] Update tags to reset Removed tags from unsupported versions current_explosion_impact_pos moved from Player to LivingEntity Brain is now packed like warden spawn tracker and always set --- .../paper26_1/player/BaseOpenPlayer.java | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java index 793d8b1f..729862fa 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java @@ -48,29 +48,19 @@ public abstract class BaseOpenPlayer extends CraftPlayer { // ServerPlayer#addAdditionalSaveData(CompoundTag) // Intentional omissions to prevent mount loss: Attach, Entity, and RootVehicle "warden_spawn_tracker", // No longer needed as of 1.21.11 - "entered_nether_pos", // Replaces enteredNetherPosition as of 1.21.6 - "enteredNetherPosition", - "respawn", // Replaces SpawnXyz fields as of 1.21.6 - "SpawnX", - "SpawnY", - "SpawnZ", - "SpawnForced", - "SpawnAngle", - "SpawnDimension", + "entered_nether_pos", + "respawn", "raid_omen_position", "ender_pearls", "ShoulderEntityLeft", "ShoulderEntityRight", // Player#addAdditionalSaveData(CompoundTag) "LastDeathLocation", - "current_explosion_impact_pos", // LivingEntity#addAdditionalSaveData(CompoundTag) + "current_explosion_impact_pos", "active_effects", - "sleeping_pos", // Replaces SleepingXyz fields as of 1.21.6 - "SleepingX", - "SleepingY", - "SleepingZ", - "Brain", + "sleeping_pos", + "Brain", // No longer needed as of 26.1 "last_hurt_by_player", "last_hurt_by_player_memory_time", "last_hurt_by_mob", From 248b4736db231adae4de9148030f8ee251279407 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 10 Apr 2026 20:00:33 -0400 Subject: [PATCH 12/18] Bump Spigot version Love that BuildTools builds whatever it feels like even when you specify a version, really great --- internal/spigot/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/spigot/build.gradle.kts b/internal/spigot/build.gradle.kts index 1b3cb4df..aad0f58f 100644 --- a/internal/spigot/build.gradle.kts +++ b/internal/spigot/build.gradle.kts @@ -21,7 +21,7 @@ apply() dependencies { compileOnly(libs.spigotapi) - extensions.getByType(SpigotDependencyExtension::class.java).version = "26.1.1-R0.1-SNAPSHOT" + extensions.getByType(SpigotDependencyExtension::class.java).version = "26.1.2-R0.1-SNAPSHOT" compileOnly("com.mojang:logging:1.6.11") compileOnly("com.mojang:brigadier:1.3.10") compileOnly("com.mojang:datafixerupper:9.0.19") From 00b3c9bbc250a2c06dcf44e6a24b887452b98543 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Fri, 10 Apr 2026 20:04:36 -0400 Subject: [PATCH 13/18] Update internal accessor range --- .../src/main/java/com/lishid/openinv/util/InternalAccessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index 4e5a0a67..74f51fe4 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -66,7 +66,7 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { private @Nullable Accessor getAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { if (!PAPER) { if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(26, 1)) - && BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(26, 1, 1))) { + && BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(26, 1, 2))) { // Load Spigot accessor. return new com.github.jikoo.openinv.internal.spigot26_1.InternalAccessor(logger, lang); } From 06e3b17abaeb507b613529e88c08cac074b60af3 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Sat, 11 Apr 2026 16:53:13 -0400 Subject: [PATCH 14/18] Bump Paper version Looks like their publishing is still a bit of a mess, I expect they'll revisit the dev bundles later. --- internal/paper26_1/build.gradle.kts | 2 +- .../java/com/lishid/openinv/util/InternalAccessor.java | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/paper26_1/build.gradle.kts b/internal/paper26_1/build.gradle.kts index 02a0cfed..dfe9337f 100644 --- a/internal/paper26_1/build.gradle.kts +++ b/internal/paper26_1/build.gradle.kts @@ -58,7 +58,7 @@ dependencies { exclude(group = "org.spigotmc", module = "spigot-api") } - paperweight.paperDevBundle("26.1.1.build.15-alpha") + paperweight.paperDevBundle("26.1.2.build.5-alpha") } tasks.reobfJar { diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index 74f51fe4..b6f13fa5 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -73,7 +73,7 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { return null; } - Version maxSupported = Version.of(21, 1, 1); + Version maxSupported = Version.of(21, 1, 2); Version minSupported = Version.of(1, 21, 6); // Ensure version is in supported range. @@ -82,12 +82,11 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { } // Paper or a Paper fork, can use Mojang-mapped internals. - if (BukkitVersions.MINECRAFT.equals(maxSupported)) { // 1.21.11 + if (BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(26, 1))) { // 26.1.1, 26.1.2 return new com.lishid.openinv.internal.paper26_1.InternalAccessor(logger, lang); } if (BukkitVersions.MINECRAFT.equals(Version.of(1, 21, 11))) { - // TODO - return null; + return new com.lishid.openinv.internal.paper1_21_11.InternalAccessor(logger, lang); } if (BukkitVersions.MINECRAFT.lessThanOrEqual(Version.of(1, 21, 10)) && BukkitVersions.MINECRAFT.greaterThanOrEqual(Version.of(1, 21, 9))) { // 1.21.9, 1.21.10 From c95e5c68cf5b1b744619358d10e9e0d641095e5c Mon Sep 17 00:00:00 2001 From: Jikoo Date: Sat, 11 Apr 2026 16:56:13 -0400 Subject: [PATCH 15/18] Add 1.21.11 module Executed some gymnastics to prevent compilation errors due to conflicting overrides --- internal/paper1_21_10/build.gradle.kts | 7 +- .../paper1_21_10/InternalAccessor.java | 2 +- .../paper1_21_10/container/OpenInventory.java | 9 + internal/paper1_21_11/build.gradle.kts | 25 ++ .../paper1_21_11/InternalAccessor.java | 29 ++ .../container/OpenEnderChest.java | 25 ++ .../paper1_21_11/container/OpenInventory.java | 25 ++ .../container/menu/OpenEnderChestMenu.java | 68 +++++ .../container/menu/OpenInventoryMenu.java | 28 ++ internal/paper1_21_8/build.gradle.kts | 7 +- .../paper1_21_8/InternalAccessor.java | 2 +- .../paper1_21_8/container/OpenInventory.java | 9 + .../container/menu/BaseOpenInventoryMenu.java | 266 ++++++++++++++++++ .../container/menu/OpenChestMenu.java | 11 - .../container/menu/OpenEnderChestMenu.java | 20 +- .../container/menu/OpenInventoryMenu.java | 257 +---------------- plugin/build.gradle.kts | 19 +- settings.gradle.kts | 1 + 18 files changed, 539 insertions(+), 271 deletions(-) create mode 100644 internal/paper1_21_11/build.gradle.kts create mode 100644 internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/InternalAccessor.java create mode 100644 internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenEnderChest.java create mode 100644 internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenInventory.java create mode 100644 internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenEnderChestMenu.java create mode 100644 internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenInventoryMenu.java create mode 100644 internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/BaseOpenInventoryMenu.java diff --git a/internal/paper1_21_10/build.gradle.kts b/internal/paper1_21_10/build.gradle.kts index b143a17e..f47ab4f3 100644 --- a/internal/paper1_21_10/build.gradle.kts +++ b/internal/paper1_21_10/build.gradle.kts @@ -17,7 +17,12 @@ dependencies { implementation(project(":openinvcommon")) { exclude(group = "org.spigotmc", module = "spigot-api") } - implementation(project(":openinvadapterpaper26_1")) + implementation(project(":openinvadapterpaper26_1")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + implementation(project(":openinvadapterpaper1_21_11")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") } diff --git a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java index c49856da..778d318b 100644 --- a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java +++ b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/InternalAccessor.java @@ -9,7 +9,7 @@ import java.util.logging.Logger; -public class InternalAccessor extends com.lishid.openinv.internal.paper26_1.InternalAccessor { +public class InternalAccessor extends com.lishid.openinv.internal.paper1_21_11.InternalAccessor { private final @NotNull PlayerManager manager; diff --git a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java index 488baca9..c9bbc816 100644 --- a/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java +++ b/internal/paper1_21_10/src/main/java/com/lishid/openinv/internal/paper1_21_10/container/OpenInventory.java @@ -1,5 +1,6 @@ package com.lishid.openinv.internal.paper1_21_10.container; +import com.lishid.openinv.internal.paper1_21_11.container.menu.OpenInventoryMenu; import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import net.minecraft.ChatFormatting; @@ -47,4 +48,12 @@ public OpenInventory(@NotNull Player bukkitPlayer) { return component; } + @Override + public @Nullable OpenChestMenu createMenu(net.minecraft.world.entity.player.Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + } diff --git a/internal/paper1_21_11/build.gradle.kts b/internal/paper1_21_11/build.gradle.kts new file mode 100644 index 00000000..8390a382 --- /dev/null +++ b/internal/paper1_21_11/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + alias(libs.plugins.paperweight) +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +tasks.withType().configureEach { + options.release = 21 +} + +dependencies { + implementation(project(":openinvapi")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvcommon")) { + exclude(group = "org.spigotmc", module = "spigot-api") + } + implementation(project(":openinvadapterpaper26_1")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + + paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") +} diff --git a/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/InternalAccessor.java b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/InternalAccessor.java new file mode 100644 index 00000000..e58425a2 --- /dev/null +++ b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/InternalAccessor.java @@ -0,0 +1,29 @@ +package com.lishid.openinv.internal.paper1_21_11; + +import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.paper1_21_11.container.OpenEnderChest; +import com.lishid.openinv.internal.paper1_21_11.container.OpenInventory; +import com.lishid.openinv.util.lang.LanguageManager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.logging.Logger; + +public class InternalAccessor extends com.lishid.openinv.internal.paper26_1.InternalAccessor { + + public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { + super(logger, lang); + } + + @Override + public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) { + return new OpenEnderChest(player); + } + + @Override + public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) { + return new OpenInventory(player); + } + +} diff --git a/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenEnderChest.java b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenEnderChest.java new file mode 100644 index 00000000..3fe30bb7 --- /dev/null +++ b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenEnderChest.java @@ -0,0 +1,25 @@ +package com.lishid.openinv.internal.paper1_21_11.container; + +import com.lishid.openinv.internal.paper1_21_11.container.menu.OpenEnderChestMenu; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public class OpenEnderChest extends com.lishid.openinv.internal.paper26_1.container.OpenEnderChest { + + public OpenEnderChest(org.bukkit.entity.Player player) { + super(player); + } + + @Override + public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenEnderChestMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + +} diff --git a/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenInventory.java b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenInventory.java new file mode 100644 index 00000000..81ba97c8 --- /dev/null +++ b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/OpenInventory.java @@ -0,0 +1,25 @@ +package com.lishid.openinv.internal.paper1_21_11.container; + +import com.lishid.openinv.internal.paper1_21_11.container.menu.OpenInventoryMenu; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public class OpenInventory extends com.lishid.openinv.internal.paper26_1.container.OpenInventory { + + public OpenInventory(org.bukkit.entity.Player bukkitPlayer) { + super(bukkitPlayer); + } + + @Override + public @Nullable OpenChestMenu createMenu(Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + +} diff --git a/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenEnderChestMenu.java b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenEnderChestMenu.java new file mode 100644 index 00000000..7c0e487e --- /dev/null +++ b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenEnderChestMenu.java @@ -0,0 +1,68 @@ +package com.lishid.openinv.internal.paper1_21_11.container.menu; + +import com.lishid.openinv.internal.paper26_1.container.OpenEnderChest; +import com.lishid.openinv.internal.paper26_1.container.menu.OpenSyncMenu; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public class OpenEnderChestMenu extends OpenSyncMenu { + + public OpenEnderChestMenu( + OpenEnderChest enderChest, + ServerPlayer viewer, + int containerId, + boolean viewOnly + ) { + super(getChestMenuType(enderChest.getContainerSize()), containerId, enderChest, viewer, viewOnly); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + if (viewOnly) { + return ItemStack.EMPTY; + } + + // See ChestMenu + Slot slot = this.slots.get(index); + + if (slot.isFake() || !slot.hasItem()) { + return ItemStack.EMPTY; + } + + ItemStack itemStack = slot.getItem(); + ItemStack original = itemStack.copy(); + + if (index < topSize) { + if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemStack, 0, topSize, false)) { + return ItemStack.EMPTY; + } + + if (itemStack.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + return original; + } + + @Override + public void clicked(int i, int j, ClickType clickType, Player player) { + if (viewOnly) { + if (clickType == ClickType.QUICK_CRAFT) { + sendAllDataToRemote(); + } + return; + } + super.clicked(i, j, clickType, player); + } + +} diff --git a/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenInventoryMenu.java b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenInventoryMenu.java new file mode 100644 index 00000000..750c4a87 --- /dev/null +++ b/internal/paper1_21_11/src/main/java/com/lishid/openinv/internal/paper1_21_11/container/menu/OpenInventoryMenu.java @@ -0,0 +1,28 @@ +package com.lishid.openinv.internal.paper1_21_11.container.menu; + +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.menu.BaseOpenInventoryMenu; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ClickType; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public class OpenInventoryMenu extends BaseOpenInventoryMenu { + + public OpenInventoryMenu(BaseOpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { + super(inventory, viewer, i, viewOnly); + } + + @Override + public void clicked(int i, int j, ClickType clickType, Player player) { + if (viewOnly) { + if (clickType == ClickType.QUICK_CRAFT) { + sendAllDataToRemote(); + } + return; + } + super.clicked(i, j, clickType, player); + } + +} diff --git a/internal/paper1_21_8/build.gradle.kts b/internal/paper1_21_8/build.gradle.kts index d30bb1d1..d3468267 100644 --- a/internal/paper1_21_8/build.gradle.kts +++ b/internal/paper1_21_8/build.gradle.kts @@ -17,7 +17,12 @@ dependencies { implementation(project(":openinvcommon")) { exclude(group = "org.spigotmc", module = "spigot-api") } - implementation(project(":openinvadapterpaper26_1")) + implementation(project(":openinvadapterpaper26_1")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + implementation(project(":openinvadapterpaper1_21_11")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } paperweight.paperDevBundle("1.21.8-R0.1-SNAPSHOT") } diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java index ab3db0ed..888ece19 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/InternalAccessor.java @@ -9,7 +9,7 @@ import java.util.logging.Logger; -public class InternalAccessor extends com.lishid.openinv.internal.paper26_1.InternalAccessor { +public class InternalAccessor extends com.lishid.openinv.internal.paper1_21_11.InternalAccessor { private final @NotNull PlayerManager manager; diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java index 0b6ff43b..fc973a48 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/container/OpenInventory.java @@ -1,5 +1,6 @@ package com.lishid.openinv.internal.paper1_21_8.container; +import com.lishid.openinv.internal.paper1_21_11.container.menu.OpenInventoryMenu; import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; import com.lishid.openinv.internal.paper26_1.container.menu.OpenChestMenu; import net.minecraft.ChatFormatting; @@ -46,4 +47,12 @@ public OpenInventory(@NotNull Player bukkitPlayer) { return component; } + @Override + public @Nullable OpenChestMenu createMenu(net.minecraft.world.entity.player.Player player, int i, boolean viewOnly) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenInventoryMenu(this, serverPlayer, i, viewOnly); + } + return null; + } + } diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/BaseOpenInventoryMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/BaseOpenInventoryMenu.java new file mode 100644 index 00000000..78fcf18a --- /dev/null +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/BaseOpenInventoryMenu.java @@ -0,0 +1,266 @@ +package com.lishid.openinv.internal.paper26_1.container.menu; + +import com.google.common.base.Preconditions; +import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; +import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenDummyPlayerInventory; +import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenPlayerInventorySelf; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentDrop; +import com.lishid.openinv.internal.paper26_1.container.slot.ContentEquipment; +import com.lishid.openinv.internal.paper26_1.container.slot.SlotViewOnly; +import com.lishid.openinv.util.Permissions; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +public class BaseOpenInventoryMenu extends OpenSyncMenu { + + private int offset; + + public BaseOpenInventoryMenu(BaseOpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { + super(getMenuType(inventory, viewer), i, inventory, viewer, viewOnly); + } + + private static MenuType getMenuType(BaseOpenInventory inventory, ServerPlayer viewer) { + int size = inventory.getContainerSize(); + // Disallow duplicate access to own main inventory contents. + if (inventory.getOwnerHandle().equals(viewer)) { + size -= viewer.getInventory().getNonEquipmentItems().size(); + size = ((int) Math.ceil(size / 9.0)) * 9; + } + + return getChestMenuType(size); + } + + @Override + protected void preSlotSetup() { + offset = ownContainer ? viewer.getInventory().getNonEquipmentItems().size() : 0; + } + + @Override + protected Slot getUpperSlot(int index, int x, int y) { + index += offset; + Slot slot = container.getMenuSlot(index, x, y); + + // If the slot cannot be interacted with there's nothing to configure. + if (slot.getClass().equals(SlotViewOnly.class)) { + return slot; + } + + // Remove drop slot if viewer is not allowed to use it. + if (slot instanceof ContentDrop.SlotDrop + && (viewOnly || !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity()))) { + return new SlotViewOnly(container, index, x, y); + } + + if (slot instanceof ContentEquipment.SlotEquipment equipment) { + if (viewOnly) { + return SlotViewOnly.wrap(slot); + } + + Permissions perm = switch (equipment.getEquipmentSlot()) { + case HEAD -> Permissions.INVENTORY_SLOT_HEAD_ANY; + case CHEST -> Permissions.INVENTORY_SLOT_CHEST_ANY; + case LEGS -> Permissions.INVENTORY_SLOT_LEGS_ANY; + case FEET -> Permissions.INVENTORY_SLOT_FEET_ANY; + // Off-hand can hold anything, not just equipment. + default -> null; + }; + + // If the viewer doesn't have permission, only allow equipment the viewee can equip in the slot. + if (perm != null && !perm.hasPermission(viewer.getBukkitEntity())) { + equipment.onlyEquipmentFor(container.getOwnerHandle()); + } + + // Equipment slots are a core part of the inventory, so they will always be shown. + return slot; + } + + // When viewing own inventory, only allow access to equipment and drop slots (equipment allowed above). + if (ownContainer && !(slot instanceof ContentDrop.SlotDrop)) { + return new SlotViewOnly(container, index, x, y); + } + + if (viewOnly) { + return SlotViewOnly.wrap(slot); + } + + return slot; + } + + @Override + protected CraftInventoryView, Inventory> createBukkitEntity() { + org.bukkit.inventory.Inventory bukkitInventory; + if (viewOnly) { + bukkitInventory = new OpenDummyPlayerInventory(container); + } else if (ownContainer) { + bukkitInventory = new OpenPlayerInventorySelf(container, offset); + } else { + bukkitInventory = container.getBukkitInventory(); + } + + return new CraftInventoryView<>(viewer.getBukkitEntity(), bukkitInventory, this) { + @Override + public org.bukkit.inventory.@Nullable ItemStack getItem(int index) { + if (viewOnly || index < 0) { + return null; + } + + Slot slot = slots.get(index); + return CraftItemStack.asCraftMirror(slot.hasItem() ? slot.getItem() : ItemStack.EMPTY); + } + + @Override + public boolean isInTop(int rawSlot) { + return rawSlot < topSize; + } + + @Override + public @Nullable Inventory getInventory(int rawSlot) { + if (viewOnly) { + return null; + } + if (rawSlot == InventoryView.OUTSIDE || rawSlot == -1) { + return null; + } + Preconditions.checkArgument( + rawSlot >= 0 && rawSlot < topSize + offset + BOTTOM_INVENTORY_SIZE, + "Slot %s outside of inventory", + rawSlot + ); + if (rawSlot > topSize) { + return getBottomInventory(); + } + Slot slot = slots.get(rawSlot); + if (slot.isFake()) { + return null; + } + return getTopInventory(); + } + + @Override + public int convertSlot(int rawSlot) { + if (viewOnly) { + return InventoryView.OUTSIDE; + } + if (rawSlot < 0) { + return rawSlot; + } + if (rawSlot < topSize) { + Slot slot = slots.get(rawSlot); + if (slot.isFake()) { + return InventoryView.OUTSIDE; + } + return rawSlot; + } + + int slot = rawSlot - topSize; + + if (slot >= 27) { + slot -= 27; + } else { + slot += 9; + } + + return slot; + } + + @Override + public InventoryType.SlotType getSlotType(int slot) { + if (viewOnly || slot < 0) { + return InventoryType.SlotType.OUTSIDE; + } + if (slot >= topSize) { + slot -= topSize; + if (slot >= 27) { + return InventoryType.SlotType.QUICKBAR; + } + return InventoryType.SlotType.CONTAINER; + } + return BaseOpenInventoryMenu.this.container.getSlotType(offset + slot); + } + + @Override + public int countSlots() { + return topSize + BOTTOM_INVENTORY_SIZE; + } + }; + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + if (viewOnly) { + return ItemStack.EMPTY; + } + + // See ChestMenu and InventoryMenu + Slot slot = this.slots.get(index); + + if (!slot.hasItem() || slot.isFake()) { + return ItemStack.EMPTY; + } + + ItemStack itemStack = slot.getItem(); + ItemStack originalStack = itemStack.copy(); + + if (index < topSize) { + // If we're moving top to bottom, do a normal transfer. + if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { + return ItemStack.EMPTY; + } + } else { + EquipmentSlot equipmentSlot = player.getEquipmentSlotForItem(itemStack); + boolean movedGear = switch (equipmentSlot) { + // If this is gear, try to move it to the correct slot first. + case OFFHAND, FEET, LEGS, CHEST, HEAD -> { + // Locate the correct slot in the contents following the main inventory. + for (int extra = container.getOwnerHandle().getInventory().getNonEquipmentItems().size() - offset; extra < topSize; ++extra) { + Slot extraSlot = getSlot(extra); + if (extraSlot instanceof ContentEquipment.SlotEquipment equipSlot + && equipSlot.getEquipmentSlot() == equipmentSlot) { + // If we've found a matching slot, try to move to it. + // If this succeeds, even partially, we will not attempt to move to other slots. + // Otherwise, armor is already occupied, so we'll fall through to main inventory. + yield this.moveItemStackTo(itemStack, extra, extra + 1, false); + } + } + yield false; + } + // Non-gear gets no special treatment. + default -> false; + }; + + // If main inventory is not available, there's nowhere else to move. + if (offset != 0) { + if (!movedGear) { + return ItemStack.EMPTY; + } + } else { + // If we didn't move to a gear slot, try to move to a main inventory slot. + if (!movedGear && !this.moveItemStackTo(itemStack, 0, container.getOwnerHandle().getInventory().getNonEquipmentItems().size(), true)) { + return ItemStack.EMPTY; + } + } + } + + if (itemStack.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + return originalStack; + } + +} diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java index 0914c33e..8b6ea05e 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenChestMenu.java @@ -9,7 +9,6 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -269,16 +268,6 @@ private static boolean addToExistingStack(ItemStack itemStack, Slot slot) { return true; } - @Override - public void clicked(int slotIndex, int buttonNum, ContainerInput containerInput, Player player) { - if (viewOnly) { - if (containerInput == ContainerInput.QUICK_CRAFT) { - sendAllDataToRemote(); - } - } - super.clicked(slotIndex, buttonNum, containerInput, player); - } - @Override public boolean stillValid(Player player) { return true; diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java index 2f80ebb0..19cacfef 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenEnderChestMenu.java @@ -3,15 +3,17 @@ import com.lishid.openinv.internal.paper26_1.container.OpenEnderChest; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NullMarked; +@NullMarked public class OpenEnderChestMenu extends OpenSyncMenu { public OpenEnderChestMenu( - @NotNull OpenEnderChest enderChest, - @NotNull ServerPlayer viewer, + OpenEnderChest enderChest, + ServerPlayer viewer, int containerId, boolean viewOnly ) { @@ -19,7 +21,7 @@ public OpenEnderChestMenu( } @Override - public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { + public ItemStack quickMoveStack(Player player, int index) { if (viewOnly) { return ItemStack.EMPTY; } @@ -51,4 +53,14 @@ public OpenEnderChestMenu( return original; } + @Override + public void clicked(int slotIndex, int buttonNum, ContainerInput containerInput, Player player) { + if (viewOnly) { + if (containerInput == ContainerInput.QUICK_CRAFT) { + sendAllDataToRemote(); + } + } + super.clicked(slotIndex, buttonNum, containerInput, player); + } + } diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java index 5289d5f4..41765cfc 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/menu/OpenInventoryMenu.java @@ -1,265 +1,26 @@ package com.lishid.openinv.internal.paper26_1.container.menu; -import com.google.common.base.Preconditions; import com.lishid.openinv.internal.paper26_1.container.BaseOpenInventory; -import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenDummyPlayerInventory; -import com.lishid.openinv.internal.paper26_1.container.bukkit.OpenPlayerInventorySelf; -import com.lishid.openinv.internal.paper26_1.container.slot.ContentDrop; -import com.lishid.openinv.internal.paper26_1.container.slot.ContentEquipment; -import com.lishid.openinv.internal.paper26_1.container.slot.SlotViewOnly; -import com.lishid.openinv.util.Permissions; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.craftbukkit.inventory.CraftInventoryView; -import org.bukkit.craftbukkit.inventory.CraftItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import net.minecraft.world.inventory.ContainerInput; +import org.jspecify.annotations.NullMarked; -public class OpenInventoryMenu extends OpenSyncMenu { - - private int offset; +@NullMarked +public class OpenInventoryMenu extends BaseOpenInventoryMenu { public OpenInventoryMenu(BaseOpenInventory inventory, ServerPlayer viewer, int i, boolean viewOnly) { - super(getMenuType(inventory, viewer), i, inventory, viewer, viewOnly); - } - - private static MenuType getMenuType(BaseOpenInventory inventory, ServerPlayer viewer) { - int size = inventory.getContainerSize(); - // Disallow duplicate access to own main inventory contents. - if (inventory.getOwnerHandle().equals(viewer)) { - size -= viewer.getInventory().getNonEquipmentItems().size(); - size = ((int) Math.ceil(size / 9.0)) * 9; - } - - return getChestMenuType(size); - } - - @Override - protected void preSlotSetup() { - offset = ownContainer ? viewer.getInventory().getNonEquipmentItems().size() : 0; - } - - @Override - protected @NotNull Slot getUpperSlot(int index, int x, int y) { - index += offset; - Slot slot = container.getMenuSlot(index, x, y); - - // If the slot cannot be interacted with there's nothing to configure. - if (slot.getClass().equals(SlotViewOnly.class)) { - return slot; - } - - // Remove drop slot if viewer is not allowed to use it. - if (slot instanceof ContentDrop.SlotDrop - && (viewOnly || !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity()))) { - return new SlotViewOnly(container, index, x, y); - } - - if (slot instanceof ContentEquipment.SlotEquipment equipment) { - if (viewOnly) { - return SlotViewOnly.wrap(slot); - } - - Permissions perm = switch (equipment.getEquipmentSlot()) { - case HEAD -> Permissions.INVENTORY_SLOT_HEAD_ANY; - case CHEST -> Permissions.INVENTORY_SLOT_CHEST_ANY; - case LEGS -> Permissions.INVENTORY_SLOT_LEGS_ANY; - case FEET -> Permissions.INVENTORY_SLOT_FEET_ANY; - // Off-hand can hold anything, not just equipment. - default -> null; - }; - - // If the viewer doesn't have permission, only allow equipment the viewee can equip in the slot. - if (perm != null && !perm.hasPermission(viewer.getBukkitEntity())) { - equipment.onlyEquipmentFor(container.getOwnerHandle()); - } - - // Equipment slots are a core part of the inventory, so they will always be shown. - return slot; - } - - // When viewing own inventory, only allow access to equipment and drop slots (equipment allowed above). - if (ownContainer && !(slot instanceof ContentDrop.SlotDrop)) { - return new SlotViewOnly(container, index, x, y); - } - - if (viewOnly) { - return SlotViewOnly.wrap(slot); - } - - return slot; - } - - @Override - protected @NotNull CraftInventoryView, Inventory> createBukkitEntity() { - org.bukkit.inventory.Inventory bukkitInventory; - if (viewOnly) { - bukkitInventory = new OpenDummyPlayerInventory(container); - } else if (ownContainer) { - bukkitInventory = new OpenPlayerInventorySelf(container, offset); - } else { - bukkitInventory = container.getBukkitInventory(); - } - - return new CraftInventoryView<>(viewer.getBukkitEntity(), bukkitInventory, this) { - @Override - public org.bukkit.inventory.ItemStack getItem(int index) { - if (viewOnly || index < 0) { - return null; - } - - Slot slot = slots.get(index); - return CraftItemStack.asCraftMirror(slot.hasItem() ? slot.getItem() : ItemStack.EMPTY); - } - - @Override - public boolean isInTop(int rawSlot) { - return rawSlot < topSize; - } - - @Override - public @Nullable Inventory getInventory(int rawSlot) { - if (viewOnly) { - return null; - } - if (rawSlot == InventoryView.OUTSIDE || rawSlot == -1) { - return null; - } - Preconditions.checkArgument( - rawSlot >= 0 && rawSlot < topSize + offset + BOTTOM_INVENTORY_SIZE, - "Slot %s outside of inventory", - rawSlot - ); - if (rawSlot > topSize) { - return getBottomInventory(); - } - Slot slot = slots.get(rawSlot); - if (slot.isFake()) { - return null; - } - return getTopInventory(); - } - - @Override - public int convertSlot(int rawSlot) { - if (viewOnly) { - return InventoryView.OUTSIDE; - } - if (rawSlot < 0) { - return rawSlot; - } - if (rawSlot < topSize) { - Slot slot = slots.get(rawSlot); - if (slot.isFake()) { - return InventoryView.OUTSIDE; - } - return rawSlot; - } - - int slot = rawSlot - topSize; - - if (slot >= 27) { - slot -= 27; - } else { - slot += 9; - } - - return slot; - } - - @Override - public @NotNull InventoryType.SlotType getSlotType(int slot) { - if (viewOnly || slot < 0) { - return InventoryType.SlotType.OUTSIDE; - } - if (slot >= topSize) { - slot -= topSize; - if (slot >= 27) { - return InventoryType.SlotType.QUICKBAR; - } - return InventoryType.SlotType.CONTAINER; - } - return OpenInventoryMenu.this.container.getSlotType(offset + slot); - } - - @Override - public int countSlots() { - return topSize + BOTTOM_INVENTORY_SIZE; - } - }; + super(inventory, viewer, i, viewOnly); } @Override - public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { + public void clicked(int slotIndex, int buttonNum, ContainerInput containerInput, Player player) { if (viewOnly) { - return ItemStack.EMPTY; - } - - // See ChestMenu and InventoryMenu - Slot slot = this.slots.get(index); - - if (!slot.hasItem() || slot.isFake()) { - return ItemStack.EMPTY; - } - - ItemStack itemStack = slot.getItem(); - ItemStack originalStack = itemStack.copy(); - - if (index < topSize) { - // If we're moving top to bottom, do a normal transfer. - if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { - return ItemStack.EMPTY; - } - } else { - EquipmentSlot equipmentSlot = player.getEquipmentSlotForItem(itemStack); - boolean movedGear = switch (equipmentSlot) { - // If this is gear, try to move it to the correct slot first. - case OFFHAND, FEET, LEGS, CHEST, HEAD -> { - // Locate the correct slot in the contents following the main inventory. - for (int extra = container.getOwnerHandle().getInventory().getNonEquipmentItems().size() - offset; extra < topSize; ++extra) { - Slot extraSlot = getSlot(extra); - if (extraSlot instanceof ContentEquipment.SlotEquipment equipSlot - && equipSlot.getEquipmentSlot() == equipmentSlot) { - // If we've found a matching slot, try to move to it. - // If this succeeds, even partially, we will not attempt to move to other slots. - // Otherwise, armor is already occupied, so we'll fall through to main inventory. - yield this.moveItemStackTo(itemStack, extra, extra + 1, false); - } - } - yield false; - } - // Non-gear gets no special treatment. - default -> false; - }; - - // If main inventory is not available, there's nowhere else to move. - if (offset != 0) { - if (!movedGear) { - return ItemStack.EMPTY; - } - } else { - // If we didn't move to a gear slot, try to move to a main inventory slot. - if (!movedGear && !this.moveItemStackTo(itemStack, 0, container.getOwnerHandle().getInventory().getNonEquipmentItems().size(), true)) { - return ItemStack.EMPTY; - } + if (containerInput == ContainerInput.QUICK_CRAFT) { + sendAllDataToRemote(); } } - - if (itemStack.isEmpty()) { - slot.setByPlayer(ItemStack.EMPTY); - } else { - slot.setChanged(); - } - - return originalStack; + super.clicked(slotIndex, buttonNum, containerInput, player); } } diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 17187409..edd4609f 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -11,10 +11,21 @@ dependencies { compileOnly(libs.spigotapi) implementation(project(":openinvapi")) implementation(project(":openinvcommon")) - implementation(project(":openinvadapterpaper26_1")) - implementation(project(":openinvadapterpaper1_21_10")) - implementation(project(":openinvadapterpaper1_21_8")) - implementation(project(":openinvadapterspigot")) + implementation(project(":openinvadapterpaper26_1")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + implementation(project(":openinvadapterpaper1_21_11")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + implementation(project(":openinvadapterpaper1_21_10")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + implementation(project(":openinvadapterpaper1_21_8")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } + implementation(project(":openinvadapterspigot")) { + exclude(group = "io.papermc.paper", module = "dev-bundle") + } implementation(libs.planarwrappers) implementation(libs.folia.scheduler.wrapper) compileOnly(libs.sqlite.jdbc) diff --git a/settings.gradle.kts b/settings.gradle.kts index ba87c4c1..f3bce79c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ if (!java.lang.Boolean.getBoolean("jitpack")) { val internals = listOf( "paper26_1", + "paper1_21_11", "paper1_21_10", "paper1_21_8", "spigot" From c3eaacbc7877c2e004a53f6661555e264ef5f656 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Mon, 13 Apr 2026 14:17:35 -0400 Subject: [PATCH 16/18] Correct max version 1.21.X brain --- .../src/main/java/com/lishid/openinv/util/InternalAccessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java index b6f13fa5..9e142cab 100644 --- a/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/util/InternalAccessor.java @@ -73,7 +73,7 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { return null; } - Version maxSupported = Version.of(21, 1, 2); + Version maxSupported = Version.of(26, 1, 2); Version minSupported = Version.of(1, 21, 6); // Ensure version is in supported range. From f4e944738b7d5358801ccdfe0fbf2578278a0f97 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Mon, 13 Apr 2026 14:21:18 -0400 Subject: [PATCH 17/18] Remove now-unnecessary intermediary class Error handling is roughly the same across the board with 1.21.5- dropped --- .../paper1_21_8/player/OpenPlayer.java | 34 +-- .../paper1_21_8/player/PlayerManager.java | 6 +- .../container/slot/ContentCrafting.java | 4 +- .../container/slot/ContentCursor.java | 4 +- .../paper26_1/container/slot/ContentDrop.java | 6 +- .../container/slot/ContentOffHand.java | 4 +- .../slot/placeholder/Placeholders.java | 4 +- .../paper26_1/player/BaseOpenPlayer.java | 202 ------------------ .../internal/paper26_1/player/OpenPlayer.java | 202 +++++++++++++++++- .../paper26_1/player/PlayerManager.java | 4 +- 10 files changed, 218 insertions(+), 252 deletions(-) delete mode 100644 internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java index 4e045292..2795a7dd 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/OpenPlayer.java @@ -1,20 +1,16 @@ package com.lishid.openinv.internal.paper1_21_8.player; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; -import com.mojang.logging.LogUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.ProblemReporter; import net.minecraft.world.level.storage.PlayerDataStorage; -import net.minecraft.world.level.storage.TagValueOutput; -import net.minecraft.world.level.storage.ValueOutput; import org.bukkit.craftbukkit.CraftServer; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; import java.nio.file.Path; +import java.util.Optional; -public class OpenPlayer extends BaseOpenPlayer { +public class OpenPlayer extends com.lishid.openinv.internal.paper26_1.player.OpenPlayer { protected OpenPlayer( CraftServer server, @@ -25,24 +21,12 @@ protected OpenPlayer( } @Override - protected void trySave(ServerPlayer player) { - Logger logger = LogUtils.getLogger(); - // See net.minecraft.world.level.storage.PlayerDataStorage#save(EntityHuman) - try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), logger)) { - PlayerDataStorage worldNbtStorage = server.getServer().getPlayerList().playerIo; - - CompoundTag oldData = isOnline() - ? null - : worldNbtStorage.load(player.getName().getString(), player.getStringUUID(), scopedCollector).orElse(null); - CompoundTag playerData = getWritableTag(oldData); - - ValueOutput valueOutput = TagValueOutput.createWrappingWithContext(scopedCollector, player.registryAccess(), playerData); - player.saveWithoutId(valueOutput); - - saveSafe(player, oldData, playerData, worldNbtStorage); - } catch (Exception e) { - LogUtils.getLogger().warn("Failed to save player data for {}: {}", player.getScoreboardName(), e); - } + protected Optional load( + PlayerDataStorage storage, + ServerPlayer player, + ProblemReporter.ScopedCollector collector + ) { + return storage.load(player.getName().getString(), player.getStringUUID(), collector); } @Override @@ -52,6 +36,8 @@ protected void safeReplaceFile(@NotNull Path dataFile, @NotNull Path tempFile, @ @Override protected void remove(@NotNull CompoundTag tag, @NotNull String key) { + // Note that the method signature here is different, though the usage + // appears identical. This version does not return the removed tag. tag.remove(key); } diff --git a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java index b997c21e..09290e5b 100644 --- a/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java +++ b/internal/paper1_21_8/src/main/java/com/lishid/openinv/internal/paper1_21_8/player/PlayerManager.java @@ -1,6 +1,6 @@ package com.lishid.openinv.internal.paper1_21_8.player; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.OpenPlayer; import com.lishid.openinv.util.JulLoggerAdapter; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -65,14 +65,14 @@ protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlay bukkitEntity.setAccessible(true); - bukkitEntity.set(player, new OpenPlayer(server.server, player, this)); + bukkitEntity.set(player, new com.lishid.openinv.internal.paper1_21_8.player.OpenPlayer(server.server, player, this)); } @Override public @NotNull Player inject(@NotNull Player player) { try { ServerPlayer nmsPlayer = getHandle(player); - if (nmsPlayer.getBukkitEntity() instanceof BaseOpenPlayer openPlayer) { + if (nmsPlayer.getBukkitEntity() instanceof OpenPlayer openPlayer) { return openPlayer; } MinecraftServer server = nmsPlayer.getServer(); diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java index 11b66894..8e30623c 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCrafting.java @@ -1,7 +1,7 @@ package com.lishid.openinv.internal.paper26_1.container.slot; import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.OpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; @@ -35,7 +35,7 @@ public static boolean isAvailable(@NotNull ServerPlayer holder) { // Player must be online and not in creative - since the creative client is (semi-)authoritative, // it ignores changes without extra help, and will delete the item as a result. // Spectator mode is technically possible but may cause the item to be dropped if the client opens an inventory. - return BaseOpenPlayer.isConnected(holder.connection) && holder.gameMode.isSurvival(); + return OpenPlayer.isConnected(holder.connection) && holder.gameMode.isSurvival(); } @Override diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java index 58bac718..d6b6ab3b 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentCursor.java @@ -1,7 +1,7 @@ package com.lishid.openinv.internal.paper26_1.container.slot; import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.OpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; @@ -64,7 +64,7 @@ private boolean isAvailable() { // Player must be online and not in creative - since the creative client is (semi-)authoritative, // it ignores changes without extra help, and will delete the item as a result. // Spectator mode is technically possible but may cause the item to be dropped if the client opens an inventory. - return BaseOpenPlayer.isConnected(holder.connection) && holder.gameMode.isSurvival(); + return OpenPlayer.isConnected(holder.connection) && holder.gameMode.isSurvival(); } @Override diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java index cff390a3..aaa747ea 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentDrop.java @@ -1,7 +1,7 @@ package com.lishid.openinv.internal.paper26_1.container.slot; import com.lishid.openinv.internal.paper26_1.container.slot.placeholder.Placeholders; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.OpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; @@ -64,14 +64,14 @@ private SlotDrop(Container container, int index, int x, int y) { @Override public ItemStack getOrDefault() { - return BaseOpenPlayer.isConnected(holder.connection) + return OpenPlayer.isConnected(holder.connection) ? Placeholders.drop : Placeholders.blockedOffline; } @Override public boolean mayPlace(@NotNull ItemStack itemStack) { - return BaseOpenPlayer.isConnected(holder.connection); + return OpenPlayer.isConnected(holder.connection); } @Override diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java index d4d9f418..97217e8a 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/ContentOffHand.java @@ -1,6 +1,6 @@ package com.lishid.openinv.internal.paper26_1.container.slot; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.OpenPlayer; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; @@ -37,7 +37,7 @@ public Slot asSlot(Container container, int slot, int x, int y) { return new SlotEquipment(container, slot, x, y) { @Override public void setChanged() { - if (BaseOpenPlayer.isConnected(holder.connection) && holder.containerMenu != holder.inventoryMenu) { + if (OpenPlayer.isConnected(holder.connection) && holder.containerMenu != holder.inventoryMenu) { holder.connection.send( new ClientboundContainerSetSlotPacket( holder.inventoryMenu.containerId, diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java index 1f938012..97f70952 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/container/slot/placeholder/Placeholders.java @@ -1,6 +1,6 @@ package com.lishid.openinv.internal.paper26_1.container.slot.placeholder; -import com.lishid.openinv.internal.paper26_1.player.BaseOpenPlayer; +import com.lishid.openinv.internal.paper26_1.player.OpenPlayer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; @@ -23,7 +23,7 @@ public final class Placeholders { public static @NotNull ItemStack blockedOffline = ItemStack.EMPTY; public static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) { - if (!BaseOpenPlayer.isConnected(serverPlayer.connection)) { + if (!OpenPlayer.isConnected(serverPlayer.connection)) { return blockedOffline; } diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java deleted file mode 100644 index 729862fa..00000000 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/BaseOpenPlayer.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.lishid.openinv.internal.paper26_1.player; - -import com.lishid.openinv.event.OpenEvents; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NumericTag; -import net.minecraft.nbt.Tag; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.level.storage.PlayerDataStorage; -import net.minecraft.world.level.storage.ValueOutput; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Set; - -public abstract class BaseOpenPlayer extends CraftPlayer { - - /** - * List of tags to always reset when saving. These are items that do not get written - * if unset or empty, resulting in older values not being clobbered appropriately. - * - * @see net.minecraft.world.entity.Entity#saveWithoutId(ValueOutput, boolean, boolean, boolean) - * @see net.minecraft.server.level.ServerPlayer#addAdditionalSaveData(ValueOutput) - * @see net.minecraft.world.entity.player.Player#addAdditionalSaveData(ValueOutput) - * @see net.minecraft.world.entity.LivingEntity#addAdditionalSaveData(ValueOutput) - */ - @Unmodifiable - protected static final Set RESET_TAGS = Set.of( - // Entity#saveWithoutId(CompoundTag) - "CustomName", - "CustomNameVisible", - "Silent", - "NoGravity", - "Glowing", - "TicksFrozen", - "HasVisualFire", - "Tags", - "data", - "Passengers", - // ServerPlayer#addAdditionalSaveData(CompoundTag) - // Intentional omissions to prevent mount loss: Attach, Entity, and RootVehicle - "warden_spawn_tracker", // No longer needed as of 1.21.11 - "entered_nether_pos", - "respawn", - "raid_omen_position", - "ender_pearls", - "ShoulderEntityLeft", - "ShoulderEntityRight", - // Player#addAdditionalSaveData(CompoundTag) - "LastDeathLocation", - // LivingEntity#addAdditionalSaveData(CompoundTag) - "current_explosion_impact_pos", - "active_effects", - "sleeping_pos", - "Brain", // No longer needed as of 26.1 - "last_hurt_by_player", - "last_hurt_by_player_memory_time", - "last_hurt_by_mob", - "ticks_since_last_hurt_by_mob", - "equipment", - "locator_bar_icon" - ); - - private final PlayerManager manager; - - protected BaseOpenPlayer(CraftServer server, ServerPlayer entity, PlayerManager manager) { - super(server, entity); - this.manager = manager; - } - - @Override - public void loadData() { - manager.loadData(server.getServer(), getHandle()); - } - - @Override - public void saveData() { - if (OpenEvents.saveCancelled(this)) { - return; - } - - trySave(this.getHandle()); - } - - protected abstract void trySave(ServerPlayer player); - - protected void saveSafe( - @NotNull ServerPlayer player, - @Nullable CompoundTag oldData, - @NotNull CompoundTag playerData, - @NotNull PlayerDataStorage worldNbtStorage - ) throws IOException { - // Revert certain special data values when offline. - revertSpecialValues(playerData, oldData); - - Path playerDataDir = worldNbtStorage.getPlayerDir().toPath(); - Path tempFile = Files.createTempFile(playerDataDir, player.getStringUUID() + "-", ".dat"); - NbtIo.writeCompressed(playerData, tempFile); - Path dataFile = playerDataDir.resolve(player.getStringUUID() + ".dat"); - Path backupFile = playerDataDir.resolve(player.getStringUUID() + ".dat_old"); - safeReplaceFile(dataFile, tempFile, backupFile); - } - - protected void safeReplaceFile( - @NotNull Path dataFile, - @NotNull Path tempFile, - @NotNull Path backupFile - ) { - net.minecraft.util.Util.safeReplaceFile(dataFile, tempFile, backupFile); - } - - @Contract("null -> new") - protected @NotNull CompoundTag getWritableTag(@Nullable CompoundTag oldData) { - if (oldData == null) { - return new CompoundTag(); - } - - // Copy old data. This is a deep clone, so operating on it should be safe. - oldData = oldData.copy(); - - // Remove vanilla/server data that is not written every time. - oldData.keySet().removeIf( - key -> RESET_TAGS.contains(key) - || key.startsWith("Bukkit") - || (key.startsWith("Paper") && key.length() > 5) - ); - - return oldData; - } - - protected void revertSpecialValues(@NotNull CompoundTag newData, @Nullable CompoundTag oldData) { - if (oldData == null) { - return; - } - - // Revert automatic updates to play timestamps. - copyValue(oldData, newData, "bukkit", "lastPlayed", NumericTag.class); - copyValue(oldData, newData, "Paper", "LastSeen", NumericTag.class); - copyValue(oldData, newData, "Paper", "LastLogin", NumericTag.class); - } - - private void copyValue( - @NotNull CompoundTag source, - @NotNull CompoundTag target, - @NotNull String container, - @NotNull String key, - @SuppressWarnings("SameParameterValue") @NotNull Class tagType - ) { - CompoundTag oldContainer = getTag(source, container, CompoundTag.class); - CompoundTag newContainer = getTag(target, container, CompoundTag.class); - - // New container being null means the server implementation doesn't store this data. - if (newContainer == null) { - return; - } - - // If old tag exists, copy it to new location, removing otherwise. - setTag(newContainer, key, getTag(oldContainer, key, tagType)); - } - - private @Nullable T getTag( - @Nullable CompoundTag container, - @NotNull String key, - @NotNull Class dataType - ) { - if (container == null) { - return null; - } - Tag value = container.get(key); - if (value == null || !dataType.isAssignableFrom(value.getClass())) { - return null; - } - return dataType.cast(value); - } - - private void setTag( - @NotNull CompoundTag container, - @NotNull String key, - @Nullable T data - ) { - if (data == null) { - remove(container, key); - } else { - container.put(key, data); - } - } - - protected abstract void remove(@NotNull CompoundTag tag, @NotNull String key); - - public static boolean isConnected(@Nullable ServerGamePacketListenerImpl connection) { - return connection != null && !connection.isDisconnected(); - } - -} diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java index 9429dec2..4991952e 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/OpenPlayer.java @@ -1,28 +1,98 @@ package com.lishid.openinv.internal.paper26_1.player; +import com.lishid.openinv.event.OpenEvents; import com.mojang.logging.LogUtils; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NumericTag; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.util.ProblemReporter; import net.minecraft.world.level.storage.PlayerDataStorage; import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.level.storage.ValueOutput; import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; import org.slf4j.Logger; -public class OpenPlayer extends BaseOpenPlayer { +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; +import java.util.Set; - protected OpenPlayer( - CraftServer server, - ServerPlayer entity, - PlayerManager manager - ) { - super(server, entity, manager); +public class OpenPlayer extends CraftPlayer { + + /** + * List of tags to always reset when saving. These are items that do not get written + * if unset or empty, resulting in older values not being clobbered appropriately. + * + * @see net.minecraft.world.entity.Entity#saveWithoutId(ValueOutput, boolean, boolean, boolean) + * @see net.minecraft.server.level.ServerPlayer#addAdditionalSaveData(ValueOutput) + * @see net.minecraft.world.entity.player.Player#addAdditionalSaveData(ValueOutput) + * @see net.minecraft.world.entity.LivingEntity#addAdditionalSaveData(ValueOutput) + */ + @Unmodifiable + protected static final Set RESET_TAGS = Set.of( + // Entity#saveWithoutId(CompoundTag) + "CustomName", + "CustomNameVisible", + "Silent", + "NoGravity", + "Glowing", + "TicksFrozen", + "HasVisualFire", + "Tags", + "data", + "Passengers", + // ServerPlayer#addAdditionalSaveData(CompoundTag) + // Intentional omissions to prevent mount loss: Attach, Entity, and RootVehicle + "warden_spawn_tracker", // No longer needed as of 1.21.11 + "entered_nether_pos", + "respawn", + "raid_omen_position", + "ender_pearls", + "ShoulderEntityLeft", + "ShoulderEntityRight", + // Player#addAdditionalSaveData(CompoundTag) + "LastDeathLocation", + // LivingEntity#addAdditionalSaveData(CompoundTag) + "current_explosion_impact_pos", + "active_effects", + "sleeping_pos", + "Brain", // No longer needed as of 26.1 + "last_hurt_by_player", + "last_hurt_by_player_memory_time", + "last_hurt_by_mob", + "ticks_since_last_hurt_by_mob", + "equipment", + "locator_bar_icon" + ); + + private final PlayerManager manager; + + protected OpenPlayer(CraftServer server, ServerPlayer entity, PlayerManager manager) { + super(server, entity); + this.manager = manager; + } + + @Override + public void loadData() { + manager.loadData(server.getServer(), getHandle()); } @Override - protected void trySave(ServerPlayer player) { + public void saveData() { + if (OpenEvents.saveCancelled(this)) { + return; + } + + ServerPlayer player = getHandle(); Logger logger = LogUtils.getLogger(); // See net.minecraft.world.level.storage.PlayerDataStorage#save(EntityHuman) try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), logger)) { @@ -30,7 +100,7 @@ protected void trySave(ServerPlayer player) { CompoundTag oldData = isOnline() ? null - : worldNbtStorage.load(player.nameAndId()).orElse(null); + : load(worldNbtStorage, player, scopedCollector).orElse(null); CompoundTag playerData = getWritableTag(oldData); ValueOutput valueOutput = TagValueOutput.createWrappingWithContext(scopedCollector, player.registryAccess(), playerData); @@ -42,9 +112,121 @@ protected void trySave(ServerPlayer player) { } } - @Override + protected Optional load( + PlayerDataStorage storage, + ServerPlayer player, + ProblemReporter.ScopedCollector collector + ) { + return storage.load(player.nameAndId()); + } + + protected void saveSafe( + @NotNull ServerPlayer player, + @Nullable CompoundTag oldData, + @NotNull CompoundTag playerData, + @NotNull PlayerDataStorage worldNbtStorage + ) throws IOException { + // Revert certain special data values when offline. + revertSpecialValues(playerData, oldData); + + Path playerDataDir = worldNbtStorage.getPlayerDir().toPath(); + Path tempFile = Files.createTempFile(playerDataDir, player.getStringUUID() + "-", ".dat"); + NbtIo.writeCompressed(playerData, tempFile); + Path dataFile = playerDataDir.resolve(player.getStringUUID() + ".dat"); + Path backupFile = playerDataDir.resolve(player.getStringUUID() + ".dat_old"); + safeReplaceFile(dataFile, tempFile, backupFile); + } + + protected void safeReplaceFile( + @NotNull Path dataFile, + @NotNull Path tempFile, + @NotNull Path backupFile + ) { + net.minecraft.util.Util.safeReplaceFile(dataFile, tempFile, backupFile); + } + + @Contract("null -> new") + protected @NotNull CompoundTag getWritableTag(@Nullable CompoundTag oldData) { + if (oldData == null) { + return new CompoundTag(); + } + + // Copy old data. This is a deep clone, so operating on it should be safe. + oldData = oldData.copy(); + + // Remove vanilla/server data that is not written every time. + oldData.keySet().removeIf( + key -> RESET_TAGS.contains(key) + || key.startsWith("Bukkit") + || (key.startsWith("Paper") && key.length() > 5) + ); + + return oldData; + } + + protected void revertSpecialValues(@NotNull CompoundTag newData, @Nullable CompoundTag oldData) { + if (oldData == null) { + return; + } + + // Revert automatic updates to play timestamps. + copyValue(oldData, newData, "bukkit", "lastPlayed", NumericTag.class); + copyValue(oldData, newData, "Paper", "LastSeen", NumericTag.class); + copyValue(oldData, newData, "Paper", "LastLogin", NumericTag.class); + } + + private void copyValue( + @NotNull CompoundTag source, + @NotNull CompoundTag target, + @NotNull String container, + @NotNull String key, + @SuppressWarnings("SameParameterValue") @NotNull Class tagType + ) { + CompoundTag oldContainer = getTag(source, container, CompoundTag.class); + CompoundTag newContainer = getTag(target, container, CompoundTag.class); + + // New container being null means the server implementation doesn't store this data. + if (newContainer == null) { + return; + } + + // If old tag exists, copy it to new location, removing otherwise. + setTag(newContainer, key, getTag(oldContainer, key, tagType)); + } + + private @Nullable T getTag( + @Nullable CompoundTag container, + @NotNull String key, + @NotNull Class dataType + ) { + if (container == null) { + return null; + } + Tag value = container.get(key); + if (value == null || !dataType.isAssignableFrom(value.getClass())) { + return null; + } + return dataType.cast(value); + } + + private void setTag( + @NotNull CompoundTag container, + @NotNull String key, + @Nullable T data + ) { + if (data == null) { + remove(container, key); + } else { + container.put(key, data); + } + } + protected void remove(@NotNull CompoundTag tag, @NotNull String key) { tag.remove(key); } + public static boolean isConnected(@Nullable ServerGamePacketListenerImpl connection) { + return connection != null && !connection.isDisconnected(); + } + } diff --git a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java index 4cdbb28e..1f3a0820 100644 --- a/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java +++ b/internal/paper26_1/src/main/java/com/lishid/openinv/internal/paper26_1/player/PlayerManager.java @@ -218,7 +218,7 @@ protected void injectPlayer(MinecraftServer server, ServerPlayer player) throws public Player inject(Player player) { try { ServerPlayer nmsPlayer = getHandle(player); - if (nmsPlayer.getBukkitEntity() instanceof BaseOpenPlayer openPlayer) { + if (nmsPlayer.getBukkitEntity() instanceof OpenPlayer openPlayer) { return openPlayer; } @@ -259,7 +259,7 @@ public Player inject(Player player) { ) { ServerPlayer player = getHandle(bukkitPlayer); - if (!BaseOpenPlayer.isConnected(player.connection)) { + if (!OpenPlayer.isConnected(player.connection)) { return null; } From 9c54f0dcad3b9eb063bfa47710a45ca19caddfee Mon Sep 17 00:00:00 2001 From: Jikoo Date: Mon, 13 Apr 2026 15:07:13 -0400 Subject: [PATCH 18/18] Fix shield rotation Appears to be backwards-compatible, so likely just defaults that the renderer no longer sets. --- .../assets/minecraft/items/shield.json | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/resource-pack/openinv-legibility-pack/openinv_44/assets/minecraft/items/shield.json b/resource-pack/openinv-legibility-pack/openinv_44/assets/minecraft/items/shield.json index cfac9c50..344ba77a 100644 --- a/resource-pack/openinv-legibility-pack/openinv_44/assets/minecraft/items/shield.json +++ b/resource-pack/openinv-legibility-pack/openinv_44/assets/minecraft/items/shield.json @@ -26,7 +26,31 @@ "type": "minecraft:shield" } }, - "property": "minecraft:using_item" + "property": "minecraft:using_item", + "transformation": { + "left_rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "right_rotation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "scale": [ + 1.0, + -1.0, + -1.0 + ], + "translation": [ + 0.0, + 0.0, + 0.0 + ] + } }, "property": "minecraft:custom_model_data" }