diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..cea14e5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Discord + url: https://discord.gg/ZcwpSsE/ + about: Issues have moved to Discord, please join the server to get help! diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md new file mode 100644 index 0000000..db998f9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -0,0 +1,11 @@ +--- +name: Report a Bug +about: Report an issue with the plugin +title: '' +labels: bug +assignees: '' +--- + +# Please report bugs on the discord! + +[Join by clicking here](https://discord.gg/ZcwpSsE/) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..4a1a7c3 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,33 @@ +name: Publish Packages +on: + workflow_dispatch: + release: + types: [ created ] + push: + tags: + - '*' + +jobs: + publish: + runs-on: ubuntu-latest + steps: + + - name: Checkout latest code + uses: actions/checkout@v2 + + - name: Set up JDK 17 + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: 17 + + - name: Change wrapper permissions + run: chmod +x ./gradlew + + - name: Publish package + uses: gradle/gradle-build-action@v2 + with: + arguments: publish + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} diff --git a/build.gradle.kts b/build.gradle.kts index fed4f4d..157d2f4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,10 +4,12 @@ plugins { `maven-publish` kotlin("jvm") version "1.7.10" id("com.github.johnrengelman.shadow") version "8.0.0" + id("com.willfp.libreforge-gradle-plugin") version "1.0.0" } group = "com.willfp" version = findProperty("version")!! +val libreforgeVersion = findProperty("libreforge-version") base { archivesName.set(project.name) @@ -38,7 +40,6 @@ allprojects { compileOnly("com.willfp:eco:6.63.0") compileOnly("org.jetbrains:annotations:23.0.0") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.7.10") - implementation("com.willfp:ecomponent:1.4.1") } java { @@ -48,6 +49,7 @@ allprojects { tasks { shadowJar { + relocate("com.willfp.libreforge.loader", "com.willfp.ecomenus.libreforge.loader") relocate("com.willfp.ecomponent", "com.willfp.ecomenus.ecomponent") } @@ -68,6 +70,7 @@ allprojects { filesMatching(listOf("**plugin.yml", "**eco.yml")) { expand( "version" to project.version, + "libreforgeVersion" to libreforgeVersion, "pluginName" to rootProject.name ) } @@ -77,17 +80,4 @@ allprojects { dependsOn(shadowJar) } } -} - -tasks { - clean { - doLast { - file("${rootDir}/bin").deleteRecursively() - } - } - - shadowJar { - destinationDirectory.set(file("$rootDir/bin/")) - archiveFileName.set("${project.name} v${project.version}.jar") - } -} +} \ No newline at end of file diff --git a/eco-core/core-plugin/build.gradle.kts b/eco-core/core-plugin/build.gradle.kts index 450a31e..12f1cf3 100644 --- a/eco-core/core-plugin/build.gradle.kts +++ b/eco-core/core-plugin/build.gradle.kts @@ -3,13 +3,19 @@ version = rootProject.version dependencies { compileOnly("io.papermc.paper:paper-api:1.19.3-R0.1-SNAPSHOT") + compileOnly("com.github.ben-manes.caffeine:caffeine:3.0.5") + + implementation("com.willfp:ecomponent:1.4.1") } publishing { publications { - register("maven", MavenPublication::class) { - from(components["java"]) + register("maven") { + groupId = project.group.toString() + version = project.version.toString() artifactId = rootProject.name + + artifact(rootProject.tasks.shadowJar.get().archiveFile) } } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/EcoMenusPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/EcoMenusPlugin.kt index 2cfeb04..1c1fe96 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/EcoMenusPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/EcoMenusPlugin.kt @@ -1,31 +1,21 @@ package com.willfp.ecomenus -import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.command.impl.PluginCommand import com.willfp.ecomenus.commands.CommandEcoMenus -import com.willfp.ecomenus.config.ConfigCategory import com.willfp.ecomenus.menus.EcoMenus +import com.willfp.libreforge.loader.LibreforgePlugin +import com.willfp.libreforge.loader.configs.ConfigCategory -class EcoMenusPlugin : EcoPlugin() { - private val categories = setOf( - EcoMenus - ) - - override fun handleEnable() { - for (category in categories) { - category.copyConfigs(this) - } - } - - override fun handleReload() { - for (category in categories) { - category.reload(this) - } - } - +class EcoMenusPlugin : LibreforgePlugin() { override fun loadPluginCommands(): List { return listOf( CommandEcoMenus(this) ) } + + override fun loadConfigCategories(): List { + return listOf( + EcoMenus + ) + } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/commands/DynamicMenuCommand.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/commands/DynamicMenuCommand.kt index 68e7a23..b02705d 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/commands/DynamicMenuCommand.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/commands/DynamicMenuCommand.kt @@ -16,6 +16,6 @@ class DynamicMenuCommand( true ) { override fun onExecute(sender: Player, args: List) { - menu.menu.open(sender) + menu.open(sender) } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/ConfigurableSlot.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/ConfigurableSlot.kt new file mode 100644 index 0000000..69a0c3c --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/ConfigurableSlot.kt @@ -0,0 +1,83 @@ +package com.willfp.ecomenus.components + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.fast.fast +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.menu.MenuLayer +import com.willfp.eco.core.gui.onClick +import com.willfp.eco.core.gui.slot +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.eco.core.items.Items +import com.willfp.eco.core.placeholder.context.placeholderContext +import com.willfp.ecomenus.slots.SlotTypes +import com.willfp.libreforge.EmptyProvidedHolder +import com.willfp.libreforge.ViolationContext +import com.willfp.libreforge.conditions.Conditions +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType + +class ConfigurableSlot( + private val plugin: EcoPlugin, + baseContext: ViolationContext, + private val config: Config +) : PositionedComponent { + override val row: Int = config.getInt("location.row") + override val column: Int = config.getInt("location.column") + + override val layer = runCatching { enumValueOf(config.getString("layer")) } + .getOrElse { MenuLayer.MIDDLE } + + val context = baseContext.with("slot at row ${row}, column $column") + + private val conditions = Conditions.compile( + config.getSubsections("conditions"), + context.with("conditions") + ) + + private val showIfNotMet = config.getBool("show-if-not-met") + + private val baseItem = Items.lookup(config.getString("item")).item + + private val slot = slot({ player, _ -> + baseItem.clone().fast().apply { + if (config.has("lore")) { + this.lore = config.getFormattedStrings( + "lore", placeholderContext( + player = player + ) + ) + } + + if (!conditions.areMet(player, EmptyProvidedHolder)) { + this.lore = this.lore + conditions.getNotMetLines(player, EmptyProvidedHolder) + } + }.unwrap() + }) { + for (clickType in ClickType.values()) { + val section = "${clickType.name.lowercase().replace("_", "-")}-click" + val actions = config.getSubsections(section) + + for (action in actions) { + val typeName = action.getString("type") + val type = SlotTypes[typeName] ?: continue + + val function = type.create( + action, + plugin, + context.with("slot at row ${row}, column $column").with(section).with(typeName) + )?.toSlotAction() ?: continue + + onClick(clickType, function) + } + } + } + + override fun getSlotAt(row: Int, column: Int, player: Player, menu: Menu): Slot? { + if (!showIfNotMet && !conditions.areMet(player, EmptyProvidedHolder)) { + return null + } + + return slot + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/PositionedComponent.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/PositionedComponent.kt index 8c9ce44..20664b4 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/PositionedComponent.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/PositionedComponent.kt @@ -16,6 +16,9 @@ interface PositionedComponent : GUIComponent { val columnSize: Int get() = 1 + val layer: MenuLayer + get() = MenuLayer.MIDDLE + override fun getRows() = rowSize override fun getColumns() = columnSize } @@ -23,16 +26,7 @@ interface PositionedComponent : GUIComponent { fun MenuBuilder.addComponent( component: PositionedComponent ) = if (component.isEnabled) addComponent( - component.row, - component.column, - component -) else this - -fun MenuBuilder.addComponent( - layer: MenuLayer, - component: PositionedComponent -) = if (component.isEnabled) addComponent( - layer, + component.layer, component.row, component.column, component diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/impl/BackButton.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/impl/BackButton.kt deleted file mode 100644 index 2ae721e..0000000 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/impl/BackButton.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.willfp.ecomenus.components.impl - -import com.willfp.eco.core.config.interfaces.Config -import com.willfp.eco.core.gui.menu.Menu -import com.willfp.eco.core.gui.onLeftClick -import com.willfp.eco.core.gui.slot -import com.willfp.eco.core.items.Items -import com.willfp.eco.core.items.builder.ItemStackBuilder -import com.willfp.ecomenus.components.PositionedComponent -import org.bukkit.entity.Player - -class BackButton( - config: Config, - goBack: (Player, Menu) -> Unit -) : PositionedComponent { - private val slot = slot( - ItemStackBuilder(Items.lookup(config.getString("item"))) - .setDisplayName(config.getFormattedString("name")) - .build() - ) { - onLeftClick { _, event, _, menu -> - goBack(event.whoClicked as Player, menu) - } - } - - override val row: Int = config.getInt("location.row") - override val column: Int = config.getInt("location.column") - - override val isEnabled = config.getBool("enabled") - - override fun getSlotAt(row: Int, column: Int) = slot -} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/impl/PositionedPageChanger.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/impl/PositionedPageChanger.kt new file mode 100644 index 0000000..fd5efa8 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/components/impl/PositionedPageChanger.kt @@ -0,0 +1,26 @@ +package com.willfp.ecomenus.components.impl + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.page.PageChanger +import com.willfp.eco.core.items.Items +import com.willfp.ecomenus.components.PositionedComponent +import org.bukkit.entity.Player + +class PositionedPageChanger( + direction: PageChanger.Direction, + config: Config, +) : PositionedComponent { + private val component = PageChanger( + Items.lookup(config.getString("item")).item, + direction + ) + + override val row: Int = config.getInt("location.row") + override val column: Int = config.getInt("location.column") + + override val isEnabled = config.getBool("enabled") + + override fun getSlotAt(row: Int, column: Int, player: Player, menu: Menu) = + component.getSlotAt(row, column, player, menu) +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/ConfigCategory.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/ConfigCategory.kt deleted file mode 100644 index 46a3f2e..0000000 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/ConfigCategory.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.willfp.ecomenus.config - -import com.willfp.eco.core.EcoPlugin -import com.willfp.eco.core.config.interfaces.Config -import com.willfp.eco.core.config.readConfig -import java.util.zip.ZipFile - -abstract class ConfigCategory( - val directory: String -) { - abstract fun clear(plugin: EcoPlugin) - - abstract fun acceptConfig(plugin: EcoPlugin, id: String, config: Config) - - internal fun reload(plugin: EcoPlugin) { - this.clear(plugin) - - for (config in this.fetchConfigs(plugin)) { - this.acceptConfig(plugin, config.id, config.config) - } - } - - internal fun copyConfigs(plugin: EcoPlugin) { - val folder = plugin.dataFolder.resolve(this.directory) - if (!folder.exists()) { - getDefaultConfigNames(plugin).forEach { configName -> - FoundConfig(configName, this.directory, plugin).copy() - } - } - } - - private fun getDefaultConfigNames(plugin: EcoPlugin): Collection { - val files = mutableListOf() - - try { - ZipFile(plugin.file).use { zipFile -> - zipFile.entries().asSequence() - .filter { it.name.startsWith("${this.directory}/") } - .mapTo(files) { it.name.removePrefix("${this.directory}/") } - } - } catch (_: Exception) { - // Sometimes, ZipFile likes to completely fail. No idea why, but here's the 'solution'! - } - - return files.filter { it.endsWith(".yml") }.map { it.removeSuffix(".yml") } - } - - private fun fetchConfigs(plugin: EcoPlugin): Set { - return plugin.dataFolder.resolve(directory) - .walk() - .filter { it.isFile && it.name.endsWith(".yml") && it.nameWithoutExtension != "_example" } - .map { file -> - val id = file.nameWithoutExtension - val config = file.readConfig() - IdentifiedConfig(config, id) - }.toSet() - } -} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/FoundConfig.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/FoundConfig.kt deleted file mode 100644 index 6e65da4..0000000 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/FoundConfig.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.willfp.ecomenus.config - -import com.willfp.eco.core.EcoPlugin -import java.io.FileOutputStream - -class FoundConfig( - name: String, - directory: String, - private val plugin: EcoPlugin -) { - private val source = plugin::class.java.classLoader - private val resourcePath = "$directory/$name.yml" - - fun copy() { - val inputStream = source.getResourceAsStream(resourcePath) ?: return - val outFile = plugin.dataFolder.resolve(resourcePath) - - if (!outFile.exists()) { - outFile.parentFile.mkdirs() - FileOutputStream(outFile).use { outStream -> - inputStream.copyTo(outStream) - } - } - - inputStream.close() - } -} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/IdentifiedConfig.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/IdentifiedConfig.kt deleted file mode 100644 index 791ad1c..0000000 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/config/IdentifiedConfig.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.willfp.ecomenus.config - -import com.willfp.eco.core.config.interfaces.Config - -internal data class IdentifiedConfig( - val config: Config, - val id: String -) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenu.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenu.kt index e609ede..9716bab 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenu.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenu.kt @@ -2,21 +2,44 @@ package com.willfp.ecomenus.menus import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu import com.willfp.eco.core.registry.KRegistrable import com.willfp.ecomenus.commands.DynamicMenuCommand +import com.willfp.libreforge.EmptyProvidedHolder +import com.willfp.libreforge.ViolationContext +import com.willfp.libreforge.conditions.Conditions +import org.bukkit.entity.Player class EcoMenu( private val plugin: EcoPlugin, override val id: String, val config: Config ) : KRegistrable { - val menu = buildMenu(plugin, config) + private val menu = buildMenu(plugin, this, config) private val commandName = config.getStringOrNull("command") + private val conditions = Conditions.compile( + config.getSubsections("conditions"), + ViolationContext(plugin, "Menu $id conditions") + ) + + private val cannotOpenMessages = config.getFormattedStrings("cannot-open-messages") + init { if (commandName != null) { DynamicMenuCommand(plugin, this, commandName).register() } } + + fun open(player: Player, parent: Menu? = null) { + if (!conditions.areMet(player, EmptyProvidedHolder)) { + for (message in cannotOpenMessages) { + player.sendMessage(message) + } + return + } + + menu.open(player, parent) + } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenus.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenus.kt index 0225acc..ffc6837 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenus.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/EcoMenus.kt @@ -1,18 +1,18 @@ package com.willfp.ecomenus.menus -import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.registry.Registry -import com.willfp.ecomenus.config.ConfigCategory +import com.willfp.libreforge.loader.LibreforgePlugin +import com.willfp.libreforge.loader.configs.ConfigCategory -object EcoMenus : ConfigCategory("menus") { +object EcoMenus : ConfigCategory("menu", "menus") { private val registry = Registry() - override fun clear(plugin: EcoPlugin) { + override fun clear(plugin: LibreforgePlugin) { registry.clear() } - override fun acceptConfig(plugin: EcoPlugin, id: String, config: Config) { + override fun acceptConfig(plugin: LibreforgePlugin, id: String, config: Config) { registry.register(EcoMenu(plugin, id, config)) } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/Menu.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/Menu.kt index 22ed8da..a44bfd3 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/Menu.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/menus/Menu.kt @@ -2,15 +2,19 @@ package com.willfp.ecomenus.menus import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.addPage import com.willfp.eco.core.gui.menu import com.willfp.eco.core.gui.menu.Menu -import com.willfp.eco.core.gui.slot.ConfigSlot +import com.willfp.eco.core.gui.page.PageChanger import com.willfp.eco.core.gui.slot.FillerMask import com.willfp.eco.core.gui.slot.MaskItems +import com.willfp.ecomenus.components.ConfigurableSlot +import com.willfp.ecomenus.components.PositionedComponent import com.willfp.ecomenus.components.addComponent -import com.willfp.ecomenus.components.impl.BackButton -import com.willfp.ecomenus.components.impl.CloseButton +import com.willfp.ecomenus.components.impl.PositionedPageChanger import com.willfp.ecomponent.menuStateVar +import com.willfp.libreforge.ConfigViolation +import com.willfp.libreforge.ViolationContext import org.bukkit.entity.Player import java.util.Stack @@ -32,7 +36,7 @@ fun Menu.open( fun Menu.close(player: Player) = this.previousMenus[player].popOrNull()?.open(player) ?: player.closeInventory() -fun buildMenu(plugin: EcoPlugin, config: Config): Menu { +fun buildMenu(plugin: EcoPlugin, menu: EcoMenu, config: Config): Menu { val mask = FillerMask( MaskItems.fromItemNames(config.getStrings("mask.materials")), *config.getStrings("mask.pattern").toTypedArray() @@ -44,26 +48,35 @@ fun buildMenu(plugin: EcoPlugin, config: Config): Menu { setMask(mask) addComponent( - CloseButton( - plugin.configYml.getSubsection("stats-gui.close") + PositionedPageChanger( + PageChanger.Direction.FORWARDS, + config.getSubsection("forwards-arrow") ) ) addComponent( - BackButton( - plugin.configYml.getSubsection("stats-gui.back") - ) { player, menu -> - menu.close(player) - } + PositionedPageChanger( + PageChanger.Direction.BACKWARDS, + config.getSubsection("backwards-arrow") + ) ) - // TODO: Implement Slots - for (test in plugin.configYml.getSubsections("stats-gui.custom-slots")) { - setSlot( - test.getInt("row"), - test.getInt("column"), - ConfigSlot(test) - ) + for (page in config.getSubsections("pages")) { + addPage(page.getInt("page")) { + for (slotConfig in config.getSubsections("slots")) { + val slot = ConfigurableSlot( + plugin, + ViolationContext(plugin, "menu ${menu.id}"), + slotConfig + ) + + try { + addComponent(slot) + } catch (e: Exception) { + slot.context.log(ConfigViolation("location", "The location of the slot is invalid!")) + } + } + } } } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotFunction.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotFunction.kt new file mode 100644 index 0000000..8bb3a7e --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotFunction.kt @@ -0,0 +1,13 @@ +package com.willfp.ecomenus.slots + +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.ecomponent.SlotAction +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent + +interface SlotFunction { + fun execute(player: Player, event: InventoryClickEvent, slot: Slot, menu: Menu) + + fun toSlotAction(): SlotAction = this::execute +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotType.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotType.kt new file mode 100644 index 0000000..4954820 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotType.kt @@ -0,0 +1,12 @@ +package com.willfp.ecomenus.slots + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.slot.SlotBuilder +import com.willfp.eco.core.registry.KRegistrable +import com.willfp.ecomponent.SlotAction +import com.willfp.libreforge.ViolationContext + +abstract class SlotType(override val id: String) : KRegistrable { + abstract fun create(config: Config, plugin: EcoPlugin, context: ViolationContext): SlotFunction? +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotTypes.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotTypes.kt new file mode 100644 index 0000000..a8d6cc2 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/SlotTypes.kt @@ -0,0 +1,18 @@ +package com.willfp.ecomenus.slots + +import com.willfp.eco.core.registry.Registry +import com.willfp.ecomenus.slots.impl.SlotTypeClose +import com.willfp.ecomenus.slots.impl.SlotTypeCommand +import com.willfp.ecomenus.slots.impl.SlotTypeConsoleCommand +import com.willfp.ecomenus.slots.impl.SlotTypeEffects +import com.willfp.ecomenus.slots.impl.SlotTypeMenu + +object SlotTypes : Registry() { + init { + register(SlotTypeCommand) + register(SlotTypeConsoleCommand) + register(SlotTypeMenu) + register(SlotTypeClose) + register(SlotTypeEffects) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeClose.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeClose.kt new file mode 100644 index 0000000..8fe2aaf --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeClose.kt @@ -0,0 +1,26 @@ +package com.willfp.ecomenus.slots.impl + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.ecomenus.menus.EcoMenu +import com.willfp.ecomenus.menus.EcoMenus +import com.willfp.ecomenus.menus.close +import com.willfp.ecomenus.menus.open +import com.willfp.ecomenus.slots.SlotFunction +import com.willfp.ecomenus.slots.SlotType +import com.willfp.libreforge.ViolationContext +import org.bukkit.Bukkit +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent + +object SlotTypeClose : SlotType("close") { + override fun create(config: Config, plugin: EcoPlugin, context: ViolationContext): SlotFunction { + return object : SlotFunction { + override fun execute(player: Player, event: InventoryClickEvent, slot: Slot, menu: Menu) { + menu.close(player) + } + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeCommand.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeCommand.kt new file mode 100644 index 0000000..ecf137c --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeCommand.kt @@ -0,0 +1,41 @@ +package com.willfp.ecomenus.slots.impl + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.eco.core.integrations.placeholder.PlaceholderManager +import com.willfp.eco.core.placeholder.context.placeholderContext +import com.willfp.ecomenus.slots.SlotFunction +import com.willfp.ecomenus.slots.SlotType +import com.willfp.libreforge.ViolationContext +import org.bukkit.Bukkit +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent + +object SlotTypeCommand : SlotType("command") { + override fun create(config: Config, plugin: EcoPlugin, context: ViolationContext): SlotFunction { + val commands = config.getStrings("commands") + + return CommandSlotFunction(commands) + } +} + +class CommandSlotFunction( + private val commands: List, + private val sender: CommandSender? = null +) : SlotFunction { + override fun execute(player: Player, event: InventoryClickEvent, slot: Slot, menu: Menu) { + for (command in commands) { + Bukkit.dispatchCommand( + sender ?: player, + PlaceholderManager.translatePlaceholders( + command, placeholderContext( + player = player + ) + ) + ) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeConsoleCommand.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeConsoleCommand.kt new file mode 100644 index 0000000..2e50786 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeConsoleCommand.kt @@ -0,0 +1,20 @@ +package com.willfp.ecomenus.slots.impl + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.ecomenus.slots.SlotFunction +import com.willfp.ecomenus.slots.SlotType +import com.willfp.libreforge.ViolationContext +import org.bukkit.Bukkit +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent + +object SlotTypeConsoleCommand : SlotType("console_command") { + override fun create(config: Config, plugin: EcoPlugin, context: ViolationContext): SlotFunction { + val commands = config.getStrings("commands") + + return CommandSlotFunction(commands, Bukkit.getConsoleSender()) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeEffects.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeEffects.kt new file mode 100644 index 0000000..1b12f65 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeEffects.kt @@ -0,0 +1,52 @@ +package com.willfp.ecomenus.slots.impl + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.ecomenus.slots.SlotFunction +import com.willfp.ecomenus.slots.SlotType +import com.willfp.libreforge.ViolationContext +import com.willfp.libreforge.effects.Chain +import com.willfp.libreforge.effects.Effects +import com.willfp.libreforge.effects.executors.ChainExecutors +import com.willfp.libreforge.triggers.DispatchedTrigger +import com.willfp.libreforge.triggers.Trigger +import com.willfp.libreforge.triggers.TriggerData +import com.willfp.libreforge.triggers.TriggerParameter +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent + +object SlotTypeEffects : SlotType("effects") { + override fun create(config: Config, plugin: EcoPlugin, context: ViolationContext): SlotFunction? { + val chain = Effects.compileChain( + config.getSubsections("effects"), + ChainExecutors.getByID(config.getString("run-type")), + context + ) ?: return null + + return SlotFunctionEffects(chain) + } + + private class SlotFunctionEffects( + private val chain: Chain + ) : SlotFunction { + override fun execute(player: Player, event: InventoryClickEvent, slot: Slot, menu: Menu) { + chain.trigger( + DispatchedTrigger( + player, + TriggerClickSlot, + TriggerData( + player = player + ) + ) + ) + } + } + + private object TriggerClickSlot : Trigger("click_slot") { + override val parameters = setOf( + TriggerParameter.PLAYER + ) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeMenu.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeMenu.kt new file mode 100644 index 0000000..a7f22e2 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecomenus/slots/impl/SlotTypeMenu.kt @@ -0,0 +1,27 @@ +package com.willfp.ecomenus.slots.impl + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.core.gui.menu.Menu +import com.willfp.eco.core.gui.slot.Slot +import com.willfp.ecomenus.menus.EcoMenu +import com.willfp.ecomenus.menus.EcoMenus +import com.willfp.ecomenus.menus.open +import com.willfp.ecomenus.slots.SlotFunction +import com.willfp.ecomenus.slots.SlotType +import com.willfp.libreforge.ViolationContext +import org.bukkit.Bukkit +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent + +object SlotTypeMenu : SlotType("menu") { + override fun create(config: Config, plugin: EcoPlugin, context: ViolationContext): SlotFunction? { + val ecoMenu = EcoMenus[config.getString("menu")] ?: return null + + return object : SlotFunction { + override fun execute(player: Player, event: InventoryClickEvent, slot: Slot, menu: Menu) { + ecoMenu.open(player, menu) + } + } + } +} diff --git a/eco-core/core-plugin/src/main/resources/eco.yml b/eco-core/core-plugin/src/main/resources/eco.yml index 9cf5ce7..6115c99 100644 --- a/eco-core/core-plugin/src/main/resources/eco.yml +++ b/eco-core/core-plugin/src/main/resources/eco.yml @@ -1,3 +1,7 @@ +environment: + - name: libreforge version + value: ${libreforgeVersion} + options: bstats-id: 0 resource-id: 0 diff --git a/eco-core/core-plugin/src/main/resources/menus/_example.yml b/eco-core/core-plugin/src/main/resources/menus/_example.yml index ea27c92..a4786c6 100644 --- a/eco-core/core-plugin/src/main/resources/menus/_example.yml +++ b/eco-core/core-plugin/src/main/resources/menus/_example.yml @@ -1,13 +1,20 @@ +# The ID of the menu is the name of the .yml file, +# for example help.yml has the ID of help +# You can place menus anywhere in this folder, +# including in subfolders if you want to organize your menu configs +# _example.yml is not loaded. + # The title of the GUI title: "Example GUI" -command: examplemenu # (Optional) The command to open the GUI, if not set, there will be no command. +# (Optional) The command to open the GUI, if not set, there will be no command. +command: examplemenu mask: # The way the mask works is by having a list of materials # And then a pattern to use those materials. - # The size of the GUI is the size of the mask. + # The size of the GUI is determined by the size of the mask. # The pattern is the rows in the GUI # Each line must be 9 long, and the amount of rows should be the amount of rows in the GUI @@ -27,14 +34,66 @@ mask: - "211111112" - "211101112" -# Options for the close item -close: - item: barrier - name: "&cClose" - enabled: false - location: - row: 6 - column: 5 -# Custom GUI slots; see here for a how-to: https://plugins.auxilor.io/all-plugins/custom-gui-slots -custom-slots: [ ] +# Read https://plugins.auxilor.io/effects/configuring-a-condition +# The conditions required to open the GUI +conditions: [ ] + +# The messages to send when the conditions are not met +cannot-open-messages: + - "&cYou cannot open this menu!" + +# Options for the page arrows +# If on the first page, the backwards arrow will not be shown, +# and if on the last page, the forwards arrow will not be shown. +forwards-arrow: + item: arrow name:"&fNext Page" + enabled: true + location: + row: 3 + column: 6 + +backwards-arrow: + item: arrow name:"&fPrevious Page" + enabled: true + location: + row: 3 + column: 4 + +pages: + - page: 1 + slots: + - item: barrier name:"&cClose" + lore: [ ] + location: + row: 6 + column: 5 + # (Optional) You can specify the layer of the slot. + # The layer can be any of: lower, middle, upper, or top (defaults to middle) + # This is useful if you want to have a slot on top of another slot, and + # have the upper slot show if some conditions are met. + layer: middle + + # Read https://plugins.auxilor.io/effects/configuring-a-condition + # The conditions required to click the item + conditions: [ ] + + # If the item should be shown if the conditions are not met + show-if-not-met: true + + left-click: + - type: effects + effects: + - id: send_message + args: + message: "&cYou clicked the close button!" + + - type: command + commands: [ ] + + - type: menu + menu: other_example_menu + + - item: console_command + commands: + - "eco give %player% 100" diff --git a/eco-core/core-plugin/src/main/resources/paper-plugin.yml b/eco-core/core-plugin/src/main/resources/paper-plugin.yml index e50d97a..ecaffe8 100644 --- a/eco-core/core-plugin/src/main/resources/paper-plugin.yml +++ b/eco-core/core-plugin/src/main/resources/paper-plugin.yml @@ -8,6 +8,10 @@ dependencies: required: true bootstrap: false + - name: libreforge + required: false + bootstrap: false + load-after: - name: eco bootstrap: false diff --git a/eco-core/core-plugin/src/main/resources/plugin.yml b/eco-core/core-plugin/src/main/resources/plugin.yml index 9de8e55..da21c6f 100644 --- a/eco-core/core-plugin/src/main/resources/plugin.yml +++ b/eco-core/core-plugin/src/main/resources/plugin.yml @@ -7,6 +7,8 @@ website: willfp.com load: STARTUP depend: - eco +softdepend: + - libreforge commands: ecomenus: diff --git a/gradle.properties b/gradle.properties index 7a0b8c1..e34db91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,5 @@ +#libreforge-updater +#Sat Jun 03 15:45:10 BST 2023 kotlin.code.style=official -version=1.0.0 +libreforge-version=4.17.2 +version=1.0.0 \ No newline at end of file