From a74ff426b2de43be3b1c5682123e9f49387196a3 Mon Sep 17 00:00:00 2001 From: Ben Woodworth Date: Tue, 23 Sep 2025 18:18:35 -0400 Subject: [PATCH 1/5] Add repository for missing bungeecord dependencies --- fastcraft-bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/fastcraft-bukkit/build.gradle b/fastcraft-bukkit/build.gradle index 5377eb66..c04ca844 100644 --- a/fastcraft-bukkit/build.gradle +++ b/fastcraft-bukkit/build.gradle @@ -2,6 +2,7 @@ allprojects { repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots" } + maven { url "https://maven.elmakers.com/repository/" } } } From f708226a0c38169307e7a456d6c95d1d8b781323 Mon Sep 17 00:00:00 2001 From: Ben Woodworth Date: Tue, 23 Sep 2025 17:20:42 -0400 Subject: [PATCH 2/5] Implement CraftingInventoryViewFactory for Bukkit 1.15 --- .../CraftingInventoryViewFactory_1_15.kt | 125 ++++++++++++++++++ .../fastcraft/bukkit/BukkitFastCraftModule.kt | 2 + 2 files changed, 127 insertions(+) create mode 100644 fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt diff --git a/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt b/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt new file mode 100644 index 00000000..4b67a99c --- /dev/null +++ b/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt @@ -0,0 +1,125 @@ +package net.benwoodworth.fastcraft.bukkit.recipe + +import org.bukkit.Material +import org.bukkit.Server +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryType +import org.bukkit.inventory.* +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CraftingInventoryViewFactory_1_15 @Inject constructor( + private val server: Server, +) : CraftingInventoryViewFactory { + override fun create( + player: Player, + inventoryHolder: InventoryHolder?, + recipe: Recipe?, + ): InventoryView { + return CustomInventoryView( + player = player, + topInventory = CustomCraftingInventory(inventoryHolder, recipe) + ) + } + + private class CustomInventoryView( + private val player: Player, + private val topInventory: Inventory, + ) : InventoryView() { + override fun getPlayer(): Player { + return player + } + + override fun getType(): InventoryType { + return topInventory.type + } + + override fun getBottomInventory(): Inventory { + return player.inventory + } + + override fun getTopInventory(): Inventory { + return topInventory + } + + override fun getTitle(): String { + return "Crafting" + } + } + + private inner class CustomCraftingInventory private constructor( + private val recipe: Recipe?, + private val baseInventory: Inventory, + ) : CraftingInventory, Inventory by baseInventory { + constructor(inventoryHolder: InventoryHolder?, recipe: Recipe?) : this( + recipe = recipe, + baseInventory = server.createInventory(inventoryHolder, InventoryType.WORKBENCH) + ) + + private fun air() = ItemStack(Material.AIR) + + override fun getItem(index: Int): ItemStack { + return baseInventory.getItem(index) ?: air() + } + + override fun getContents(): Array { + val contents = baseInventory.contents + for (i in contents.indices) { + contents[i] = contents[i] ?: air() + } + + return contents + } + + override fun getStorageContents(): Array { + val storageContents = baseInventory.storageContents + for (i in storageContents.indices) { + storageContents[i] = storageContents[i] ?: air() + } + + return storageContents + } + + override fun getRecipe(): Recipe? { + return recipe + } + + override fun getMatrix(): Array { + return Array(size - 1) { slot -> getItem(slot) } + } + + override fun setMatrix(contents: Array) { + if (contents.size > baseInventory.size - 1) { + throw IllegalArgumentException("matrix contents too large") + } + + setContents(contents) + } + + override fun getResult(): ItemStack { + return getItem(9) + } + + override fun setResult(newResult: ItemStack?) { + setItem(size - 1, newResult) + } + + override fun iterator(index: Int): MutableListIterator { + val baseIterator = baseInventory.iterator(index) + return object : MutableListIterator by baseIterator { + override fun next(): ItemStack { + return baseIterator.next() ?: air() + } + + override fun previous(): ItemStack { + return baseIterator.previous() ?: air() + } + } + } + + override fun iterator(): MutableListIterator { + return iterator(0) + } + } +} diff --git a/fastcraft-bukkit/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/BukkitFastCraftModule.kt b/fastcraft-bukkit/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/BukkitFastCraftModule.kt index 47ba762c..fbb19f36 100644 --- a/fastcraft-bukkit/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/BukkitFastCraftModule.kt +++ b/fastcraft-bukkit/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/BukkitFastCraftModule.kt @@ -209,11 +209,13 @@ class BukkitFastCraftModule( @Provides fun provideCraftingInventoryViewFactory( + instance_1_15: Provider, instance_1_14: Provider, instance_1_9: Provider, instance_1_7: Provider, ): CraftingInventoryViewFactory { return when { + bukkitVersion >= VERSION_1_15 -> instance_1_15.get() bukkitVersion >= VERSION_1_14 -> instance_1_14.get() bukkitVersion >= VERSION_1_9 -> instance_1_9.get() bukkitVersion >= VERSION_1_7 -> instance_1_7.get() From 8cb381e296196121753aabf0aa3c0d421c37f160 Mon Sep 17 00:00:00 2001 From: Ben Woodworth Date: Tue, 23 Sep 2025 19:28:49 -0400 Subject: [PATCH 3/5] Implement Paper's `Inventory.getHolder(useSnapshot)` method Paper added it in 1.15, and other plugins that use this method will throw if they try to use FastCraft's CraftingInventory implementation. --- fastcraft-bukkit/build.gradle | 10 ++++++ .../CraftingInventoryViewFactory_1_15.kt | 22 +++++++++++-- fastcraft-bukkit/paper-1.15/build.gradle | 4 +++ .../CraftingInventoryViewFactoryTest.kt | 33 +++++++++++++++++++ settings.gradle | 1 + 5 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 fastcraft-bukkit/paper-1.15/build.gradle create mode 100644 fastcraft-bukkit/paper-1.15/src/test/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactoryTest.kt diff --git a/fastcraft-bukkit/build.gradle b/fastcraft-bukkit/build.gradle index c04ca844..16c62b27 100644 --- a/fastcraft-bukkit/build.gradle +++ b/fastcraft-bukkit/build.gradle @@ -3,6 +3,16 @@ allprojects { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots" } maven { url "https://maven.elmakers.com/repository/" } + maven { url "https://repo.papermc.io/repository/maven-public/" } + } + + dependencies { + testImplementation 'org.jetbrains.kotlin:kotlin-test' + testImplementation "io.mockk:mockk:1.12.4" + } + + test { + useJUnitPlatform() } } diff --git a/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt b/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt index 4b67a99c..d850c64c 100644 --- a/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt +++ b/fastcraft-bukkit/bukkit-1.15/src/main/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactory_1_15.kt @@ -12,6 +12,18 @@ import javax.inject.Singleton class CraftingInventoryViewFactory_1_15 @Inject constructor( private val server: Server, ) : CraftingInventoryViewFactory { + private companion object { + fun air() = ItemStack(Material.AIR) + + /** + * The `getHolder` method available in Paper starting with 1.15.2: + * https://jd.papermc.io/paper/1.15.2/org/bukkit/inventory/Inventory.html#getHolder-boolean- + */ + private val paperInventoryGetHolderMethodWithUseSnapshot by lazy { + CraftingInventory::class.java.getMethod("getHolder", Boolean::class.java) + } + } + override fun create( player: Player, inventoryHolder: InventoryHolder?, @@ -57,8 +69,6 @@ class CraftingInventoryViewFactory_1_15 @Inject constructor( baseInventory = server.createInventory(inventoryHolder, InventoryType.WORKBENCH) ) - private fun air() = ItemStack(Material.AIR) - override fun getItem(index: Int): ItemStack { return baseInventory.getItem(index) ?: air() } @@ -121,5 +131,13 @@ class CraftingInventoryViewFactory_1_15 @Inject constructor( override fun iterator(): MutableListIterator { return iterator(0) } + + /** + * Delegates interface method added by PaperMC in 1.15.2: + * https://jd.papermc.io/paper/1.15.2/org/bukkit/inventory/Inventory.html#getHolder-boolean- + */ + fun getHolder(useSnapshot: Boolean): InventoryHolder? { + return paperInventoryGetHolderMethodWithUseSnapshot.invoke(baseInventory, useSnapshot) as InventoryHolder? + } } } diff --git a/fastcraft-bukkit/paper-1.15/build.gradle b/fastcraft-bukkit/paper-1.15/build.gradle new file mode 100644 index 00000000..cd4a9671 --- /dev/null +++ b/fastcraft-bukkit/paper-1.15/build.gradle @@ -0,0 +1,4 @@ +dependencies { + testImplementation project(':fastcraft-bukkit:bukkit-1.15') + testImplementation 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT' +} diff --git a/fastcraft-bukkit/paper-1.15/src/test/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactoryTest.kt b/fastcraft-bukkit/paper-1.15/src/test/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactoryTest.kt new file mode 100644 index 00000000..2ede3e63 --- /dev/null +++ b/fastcraft-bukkit/paper-1.15/src/test/kotlin/net/benwoodworth/fastcraft/bukkit/recipe/CraftingInventoryViewFactoryTest.kt @@ -0,0 +1,33 @@ +package net.benwoodworth.fastcraft.bukkit.recipe + +import io.mockk.every +import io.mockk.mockk +import org.bukkit.Server +import org.bukkit.event.inventory.InventoryType +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.InventoryHolder +import kotlin.test.Test +import kotlin.test.assertSame + +class CraftingInventoryViewFactoryTest { + @Test + fun get_holder_with_use_snapshot_should_delegate_correctly() { + val inventoryHolder = mockk("non-snapshot") + val inventoryHolderSnapshot = mockk("snapshot") + + val baseInventory = mockk() + every { baseInventory.getHolder(false) } returns inventoryHolder + every { baseInventory.getHolder(true) } returns inventoryHolderSnapshot + + val server = mockk() + every { server.createInventory(any(), InventoryType.WORKBENCH) } returns baseInventory + + val inventoryFactory = CraftingInventoryViewFactory_1_15(server) + val customInventoryView = inventoryFactory.create(mockk(), null, null) + val customCraftingInventory = customInventoryView.topInventory + + assertSame(inventoryHolder, customCraftingInventory.getHolder(false)) + assertSame(inventoryHolderSnapshot, customCraftingInventory.getHolder(true)) + } + +} diff --git a/settings.gradle b/settings.gradle index 26cc3f5e..e05137a0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,6 +16,7 @@ include ":fastcraft-bukkit:bukkit-1.13" include ":fastcraft-bukkit:bukkit-1.14" include ":fastcraft-bukkit:bukkit-1.15" include ":fastcraft-bukkit:bukkit-platform" +include ":fastcraft-bukkit:paper-1.15" gradleEnterprise { From 32d45db526194e5e9be57a97ed192bdf2ff70625 Mon Sep 17 00:00:00 2001 From: Ben Woodworth Date: Tue, 23 Sep 2025 20:21:55 -0400 Subject: [PATCH 4/5] Update actions/upload-artifact to v4 --- .github/workflows/build-test-upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-test-upload.yml b/.github/workflows/build-test-upload.yml index 8bce94ce..b94da685 100644 --- a/.github/workflows/build-test-upload.yml +++ b/.github/workflows/build-test-upload.yml @@ -25,7 +25,7 @@ jobs: run: ./gradlew test - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: FastCraft.jar path: build/libs/FastCraft*.jar From 1059f6fadc6cca5624ef25a4a1d23aeccd25136d Mon Sep 17 00:00:00 2001 From: Ben Woodworth Date: Tue, 23 Sep 2025 20:26:15 -0400 Subject: [PATCH 5/5] Add actions/setup-java --- .github/workflows/build-test-upload.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-test-upload.yml b/.github/workflows/build-test-upload.yml index b94da685..b75cce20 100644 --- a/.github/workflows/build-test-upload.yml +++ b/.github/workflows/build-test-upload.yml @@ -15,6 +15,11 @@ jobs: # For versioning, fetch everything so `git describe` works fetch-depth: 0 + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '8' + - name: Setup Gradle uses: gradle/gradle-build-action@v2