9
0
mirror of https://github.com/Auxilor/EcoMenus.git synced 2025-12-19 15:09:20 +00:00

Implemented pretty much the rest of the plugin

This commit is contained in:
Auxilor
2023-06-03 19:19:57 +01:00
parent b208d52feb
commit cafc3ed343
30 changed files with 539 additions and 209 deletions

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -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!

11
.github/ISSUE_TEMPLATE/report-a-bug.md vendored Normal file
View File

@@ -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/)

33
.github/workflows/publish-release.yml vendored Normal file
View File

@@ -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 }}

View File

@@ -4,10 +4,12 @@ plugins {
`maven-publish` `maven-publish`
kotlin("jvm") version "1.7.10" kotlin("jvm") version "1.7.10"
id("com.github.johnrengelman.shadow") version "8.0.0" id("com.github.johnrengelman.shadow") version "8.0.0"
id("com.willfp.libreforge-gradle-plugin") version "1.0.0"
} }
group = "com.willfp" group = "com.willfp"
version = findProperty("version")!! version = findProperty("version")!!
val libreforgeVersion = findProperty("libreforge-version")
base { base {
archivesName.set(project.name) archivesName.set(project.name)
@@ -38,7 +40,6 @@ allprojects {
compileOnly("com.willfp:eco:6.63.0") compileOnly("com.willfp:eco:6.63.0")
compileOnly("org.jetbrains:annotations:23.0.0") compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.7.10") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.7.10")
implementation("com.willfp:ecomponent:1.4.1")
} }
java { java {
@@ -48,6 +49,7 @@ allprojects {
tasks { tasks {
shadowJar { shadowJar {
relocate("com.willfp.libreforge.loader", "com.willfp.ecomenus.libreforge.loader")
relocate("com.willfp.ecomponent", "com.willfp.ecomenus.ecomponent") relocate("com.willfp.ecomponent", "com.willfp.ecomenus.ecomponent")
} }
@@ -68,6 +70,7 @@ allprojects {
filesMatching(listOf("**plugin.yml", "**eco.yml")) { filesMatching(listOf("**plugin.yml", "**eco.yml")) {
expand( expand(
"version" to project.version, "version" to project.version,
"libreforgeVersion" to libreforgeVersion,
"pluginName" to rootProject.name "pluginName" to rootProject.name
) )
} }
@@ -77,17 +80,4 @@ allprojects {
dependsOn(shadowJar) dependsOn(shadowJar)
} }
} }
} }
tasks {
clean {
doLast {
file("${rootDir}/bin").deleteRecursively()
}
}
shadowJar {
destinationDirectory.set(file("$rootDir/bin/"))
archiveFileName.set("${project.name} v${project.version}.jar")
}
}

View File

@@ -3,13 +3,19 @@ version = rootProject.version
dependencies { dependencies {
compileOnly("io.papermc.paper:paper-api:1.19.3-R0.1-SNAPSHOT") 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 { publishing {
publications { publications {
register("maven", MavenPublication::class) { register<MavenPublication>("maven") {
from(components["java"]) groupId = project.group.toString()
version = project.version.toString()
artifactId = rootProject.name artifactId = rootProject.name
artifact(rootProject.tasks.shadowJar.get().archiveFile)
} }
} }
} }

View File

@@ -1,31 +1,21 @@
package com.willfp.ecomenus package com.willfp.ecomenus
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.command.impl.PluginCommand import com.willfp.eco.core.command.impl.PluginCommand
import com.willfp.ecomenus.commands.CommandEcoMenus import com.willfp.ecomenus.commands.CommandEcoMenus
import com.willfp.ecomenus.config.ConfigCategory
import com.willfp.ecomenus.menus.EcoMenus import com.willfp.ecomenus.menus.EcoMenus
import com.willfp.libreforge.loader.LibreforgePlugin
import com.willfp.libreforge.loader.configs.ConfigCategory
class EcoMenusPlugin : EcoPlugin() { class EcoMenusPlugin : LibreforgePlugin() {
private val categories = setOf<ConfigCategory>(
EcoMenus
)
override fun handleEnable() {
for (category in categories) {
category.copyConfigs(this)
}
}
override fun handleReload() {
for (category in categories) {
category.reload(this)
}
}
override fun loadPluginCommands(): List<PluginCommand> { override fun loadPluginCommands(): List<PluginCommand> {
return listOf( return listOf(
CommandEcoMenus(this) CommandEcoMenus(this)
) )
} }
override fun loadConfigCategories(): List<ConfigCategory> {
return listOf(
EcoMenus
)
}
} }

View File

@@ -16,6 +16,6 @@ class DynamicMenuCommand(
true true
) { ) {
override fun onExecute(sender: Player, args: List<String>) { override fun onExecute(sender: Player, args: List<String>) {
menu.menu.open(sender) menu.open(sender)
} }
} }

View File

@@ -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<MenuLayer>(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
}
}

View File

@@ -16,6 +16,9 @@ interface PositionedComponent : GUIComponent {
val columnSize: Int val columnSize: Int
get() = 1 get() = 1
val layer: MenuLayer
get() = MenuLayer.MIDDLE
override fun getRows() = rowSize override fun getRows() = rowSize
override fun getColumns() = columnSize override fun getColumns() = columnSize
} }
@@ -23,16 +26,7 @@ interface PositionedComponent : GUIComponent {
fun MenuBuilder.addComponent( fun MenuBuilder.addComponent(
component: PositionedComponent component: PositionedComponent
) = if (component.isEnabled) addComponent( ) = if (component.isEnabled) addComponent(
component.row, component.layer,
component.column,
component
) else this
fun MenuBuilder.addComponent(
layer: MenuLayer,
component: PositionedComponent
) = if (component.isEnabled) addComponent(
layer,
component.row, component.row,
component.column, component.column,
component component

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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<String> {
val files = mutableListOf<String>()
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<IdentifiedConfig> {
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()
}
}

View File

@@ -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()
}
}

View File

@@ -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
)

View File

@@ -2,21 +2,44 @@ package com.willfp.ecomenus.menus
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config 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.eco.core.registry.KRegistrable
import com.willfp.ecomenus.commands.DynamicMenuCommand 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( class EcoMenu(
private val plugin: EcoPlugin, private val plugin: EcoPlugin,
override val id: String, override val id: String,
val config: Config val config: Config
) : KRegistrable { ) : KRegistrable {
val menu = buildMenu(plugin, config) private val menu = buildMenu(plugin, this, config)
private val commandName = config.getStringOrNull("command") 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 { init {
if (commandName != null) { if (commandName != null) {
DynamicMenuCommand(plugin, this, commandName).register() 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)
}
} }

View File

@@ -1,18 +1,18 @@
package com.willfp.ecomenus.menus package com.willfp.ecomenus.menus
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.registry.Registry 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<EcoMenu>() private val registry = Registry<EcoMenu>()
override fun clear(plugin: EcoPlugin) { override fun clear(plugin: LibreforgePlugin) {
registry.clear() 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)) registry.register(EcoMenu(plugin, id, config))
} }

View File

@@ -2,15 +2,19 @@ package com.willfp.ecomenus.menus
import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config 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
import com.willfp.eco.core.gui.menu.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.FillerMask
import com.willfp.eco.core.gui.slot.MaskItems 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.addComponent
import com.willfp.ecomenus.components.impl.BackButton import com.willfp.ecomenus.components.impl.PositionedPageChanger
import com.willfp.ecomenus.components.impl.CloseButton
import com.willfp.ecomponent.menuStateVar import com.willfp.ecomponent.menuStateVar
import com.willfp.libreforge.ConfigViolation
import com.willfp.libreforge.ViolationContext
import org.bukkit.entity.Player import org.bukkit.entity.Player
import java.util.Stack import java.util.Stack
@@ -32,7 +36,7 @@ fun Menu.open(
fun Menu.close(player: Player) = fun Menu.close(player: Player) =
this.previousMenus[player].popOrNull()?.open(player) ?: player.closeInventory() 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( val mask = FillerMask(
MaskItems.fromItemNames(config.getStrings("mask.materials")), MaskItems.fromItemNames(config.getStrings("mask.materials")),
*config.getStrings("mask.pattern").toTypedArray() *config.getStrings("mask.pattern").toTypedArray()
@@ -44,26 +48,35 @@ fun buildMenu(plugin: EcoPlugin, config: Config): Menu {
setMask(mask) setMask(mask)
addComponent( addComponent(
CloseButton( PositionedPageChanger(
plugin.configYml.getSubsection("stats-gui.close") PageChanger.Direction.FORWARDS,
config.getSubsection("forwards-arrow")
) )
) )
addComponent( addComponent(
BackButton( PositionedPageChanger(
plugin.configYml.getSubsection("stats-gui.back") PageChanger.Direction.BACKWARDS,
) { player, menu -> config.getSubsection("backwards-arrow")
menu.close(player) )
}
) )
// TODO: Implement Slots for (page in config.getSubsections("pages")) {
for (test in plugin.configYml.getSubsections("stats-gui.custom-slots")) { addPage(page.getInt("page")) {
setSlot( for (slotConfig in config.getSubsections("slots")) {
test.getInt("row"), val slot = ConfigurableSlot(
test.getInt("column"), plugin,
ConfigSlot(test) ViolationContext(plugin, "menu ${menu.id}"),
) slotConfig
)
try {
addComponent(slot)
} catch (e: Exception) {
slot.context.log(ConfigViolation("location", "The location of the slot is invalid!"))
}
}
}
} }
} }
} }

View File

@@ -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
}

View File

@@ -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?
}

View File

@@ -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<SlotType>() {
init {
register(SlotTypeCommand)
register(SlotTypeConsoleCommand)
register(SlotTypeMenu)
register(SlotTypeClose)
register(SlotTypeEffects)
}
}

View File

@@ -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)
}
}
}
}

View File

@@ -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<String>,
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
)
)
)
}
}
}

View File

@@ -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())
}
}

View File

@@ -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
)
}
}

View File

@@ -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)
}
}
}
}

View File

@@ -1,3 +1,7 @@
environment:
- name: libreforge version
value: ${libreforgeVersion}
options: options:
bstats-id: 0 bstats-id: 0
resource-id: 0 resource-id: 0

View File

@@ -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 # The title of the GUI
title: "Example 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: mask:
# The way the mask works is by having a list of materials # The way the mask works is by having a list of materials
# And then a pattern to use those 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 # 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 # 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" - "211111112"
- "211101112" - "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 # Read https://plugins.auxilor.io/effects/configuring-a-condition
custom-slots: [ ] # 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"

View File

@@ -8,6 +8,10 @@ dependencies:
required: true required: true
bootstrap: false bootstrap: false
- name: libreforge
required: false
bootstrap: false
load-after: load-after:
- name: eco - name: eco
bootstrap: false bootstrap: false

View File

@@ -7,6 +7,8 @@ website: willfp.com
load: STARTUP load: STARTUP
depend: depend:
- eco - eco
softdepend:
- libreforge
commands: commands:
ecomenus: ecomenus:

View File

@@ -1,2 +1,5 @@
#libreforge-updater
#Sat Jun 03 15:45:10 BST 2023
kotlin.code.style=official kotlin.code.style=official
version=1.0.0 libreforge-version=4.17.2
version=1.0.0