diff --git a/api/.gradle/caches/paperweight/taskCache/reobfJar.log b/api/.gradle/caches/paperweight/taskCache/reobfJar.log index 40902d9..46e4669 100644 --- a/api/.gradle/caches/paperweight/taskCache/reobfJar.log +++ b/api/.gradle/caches/paperweight/taskCache/reobfJar.log @@ -1,17 +1,2 @@ Command: C:\Program Files\Java\jdk-17\bin\java.exe -Xmx1G -classpath C:\Users\Mangr\.gradle\caches\modules-2\files-2.1\net.fabricmc\tiny-remapper\0.10.1\c293b2384ae12af74f407fa3aaa553bba4ac6763\tiny-remapper-0.10.1-fat.jar net.fabricmc.tinyremapper.Main D:\PC\Projects\KtBukkitGui\api\build\libs\ktgui-2.4.1-dev-all.jar D:\PC\Projects\KtBukkitGui\api\build\libs\api-2.4.1.jar C:\Users\Mangr\.gradle\caches\paperweight-userdev\ff775525efc29c3503a07d1006e63e5695a742b7505cf63e157d49d32419c69f\module\io.papermc.paper\dev-bundle\1.20.4-R0.1-SNAPSHOT\paperweight\setupCache\extractDevBundle.dir\data\mojang+yarn-spigot-reobf.tiny mojang+yarn spigot C:\Users\Mangr\.gradle\caches\paperweight-userdev\ff775525efc29c3503a07d1006e63e5695a742b7505cf63e157d49d32419c69f\module\io.papermc.paper\dev-bundle\1.20.4-R0.1-SNAPSHOT\paperweight\setupCache\applyMojangMappedPaperclipPatch.jar --threads=1 -Exception in thread "main" java.lang.RuntimeException: java.nio.file.FileSystemException: D:\PC\Projects\KtBukkitGui\api\build\libs\api-2.4.1.jar: The process cannot access the file because it is being used by another process - at net.fabricmc.tinyremapper.Main.main(Main.java:267) -Caused by: java.nio.file.FileSystemException: D:\PC\Projects\KtBukkitGui\api\build\libs\api-2.4.1.jar: The process cannot access the file because it is being used by another process - at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92) - at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) - at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108) - at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:275) - at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:105) - at java.base/java.nio.file.Files.delete(Files.java:1152) - at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.sync(ZipFileSystem.java:1914) - at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.lambda$close$10(ZipFileSystem.java:494) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) - at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.close(ZipFileSystem.java:493) - at net.fabricmc.tinyremapper.FileSystemReference.close(FileSystemReference.java:131) - at net.fabricmc.tinyremapper.OutputConsumerPath.close(OutputConsumerPath.java:213) - at net.fabricmc.tinyremapper.Main.main(Main.java:266) +Finished after 2782.23 ms. diff --git a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/ChainCommandBuilder.kt b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/ChainCommandBuilder.kt index 86024f4..09f6af9 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/ChainCommandBuilder.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/ChainCommandBuilder.kt @@ -20,7 +20,8 @@ class ChainCommandBuilder(val name: String) { subcommands.addAll(command) } - inline infix fun runs(noinline block: RunnableCommandContext.() -> Unit) = build().runs(block) + inline infix fun runs(noinline block: RunnableCommandContext.() -> Unit) = + build().runs(block) fun build() = build(DeclarativeCommandBuilder(name)) diff --git a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/Argument.kt b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/Argument.kt index 7200c48..a1aac1a 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/Argument.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/Argument.kt @@ -2,15 +2,13 @@ package com.mattmx.ktgui.commands.declarative.arg import com.mattmx.ktgui.commands.declarative.DeclarativeCommandBuilder import com.mattmx.ktgui.commands.declarative.arg.impl.OptionArgument -import com.mattmx.ktgui.commands.declarative.invocation.BaseCommandContext -import com.mattmx.ktgui.commands.declarative.invocation.InvalidArgContext -import com.mattmx.ktgui.commands.declarative.invocation.RunnableCommandContext -import com.mattmx.ktgui.commands.declarative.invocation.SuggestionInvocation +import com.mattmx.ktgui.commands.declarative.invocation.* import com.mattmx.ktgui.commands.suggestions.CommandSuggestion import com.mattmx.ktgui.commands.suggestions.CommandSuggestionRegistry import com.mattmx.ktgui.event.EventCallback import com.mattmx.ktgui.utils.Invokable import com.mattmx.ktgui.utils.JavaCompatibility +import org.bukkit.Bukkit import java.util.* open class Argument( @@ -63,6 +61,9 @@ open class Argument( this.optional = value } + infix fun optionalWithDefault(default: T) = + optional(true).defaultValue(default) + infix fun defaultValue(default: T) = apply { this.default = default } @@ -92,7 +93,7 @@ open class Argument( } open fun getDefaultSuggestions(): Collection? { - val context = SuggestionInvocation(Optional.empty(), "", emptyList()) + val context = StorageCommandContext(Bukkit.getConsoleSender(), "", emptyList()) return if (suggests.isPresent) { suggests.get().getSuggestion(context) } else { @@ -111,12 +112,20 @@ open class Argument( open fun consume(processor: ArgumentProcessor) = this.consumer.consume(processor) - open fun getValueOfString(cmd: DeclarativeCommandBuilder, context: BaseCommandContext<*>, split: List): T? { + open fun getValueOfString( + cmd: DeclarativeCommandBuilder?, + context: BaseCommandContext<*>, + split: List + ): T? { return getValueOfString(cmd, context, split.joinToString(" ")) } - open fun getValueOfString(cmd: DeclarativeCommandBuilder, context: BaseCommandContext<*>, stringValue: String?): T? { - return if (cmd.localArgumentSuggestions.contains(name())) { + open fun getValueOfString( + cmd: DeclarativeCommandBuilder?, + context: BaseCommandContext<*>?, + stringValue: String? + ): T? { + return if (cmd?.localArgumentSuggestions?.contains(name()) == true) { cmd.localArgumentSuggestions[name()]?.getValue(stringValue) as T? } else if (suggests.isPresent) { suggests.get().getValue(stringValue) @@ -131,6 +140,9 @@ open class Argument( @JavaCompatibility fun getValue(context: RunnableCommandContext<*>) = context.getArgumentContext(name())?.getOrNull() + fun createContext(cmd: DeclarativeCommandBuilder?, context: BaseCommandContext<*>?, stringValue: String?) = + createContext(stringValue, getValueOfString(cmd, context, stringValue)) + fun createContext(stringValue: String?, actualValue: Any?): ArgumentContext { return ArgumentContext(stringValue, Optional.ofNullable(actualValue as T?), this) } @@ -142,7 +154,7 @@ open class Argument( open fun applyToClone(cloned: Argument) = cloned - fun clone() : Argument { + fun clone(): Argument { return Argument(name, typeName) .let { it.consumer = consumer diff --git a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/ArgumentProcessor.kt b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/ArgumentProcessor.kt index 075b0eb..12cc27b 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/ArgumentProcessor.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/ArgumentProcessor.kt @@ -6,7 +6,7 @@ import com.mattmx.ktgui.commands.declarative.invocation.StorageCommandContext class ArgumentProcessor( val command: DeclarativeCommandBuilder, - val context: StorageCommandContext<*>, + val context: StorageCommandContext<*>?, val args: List ) { var pointer = -1 @@ -37,7 +37,8 @@ class ArgumentProcessor( } if (option != null) { - val passed = if (option.requiresCheck.isEmpty) true else option.requiresCheck.get()(context) + val passed = if (option.requiresCheck.isEmpty) true + else context?.let { option.requiresCheck.get()(it) } == true if (passed) { val value = peek(1) ?: continue diff --git a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/impl/args.kt b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/impl/args.kt index 8e262a6..ec88705 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/impl/args.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/commands/declarative/arg/impl/args.kt @@ -1,6 +1,7 @@ package com.mattmx.ktgui.commands.declarative.arg.impl import com.mattmx.ktgui.commands.declarative.arg.Argument +import it.unimi.dsi.fastutil.Hash import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty @@ -52,5 +53,11 @@ fun multiChoiceArgument(vararg choices: Pair) = fun multiChoiceArgument(choiceSupplier: () -> HashMap) = delegateArgument(MultiChoiceArgument(DELEGATED_ARG_NAME) { choiceSupplier() }) +fun multiChoiceStringArgument(vararg choiceSupplier: String) = + delegateArgument(MultiChoiceArgument(DELEGATED_ARG_NAME) { choiceSupplier.associateWithTo(HashMap()) { it } }) + +fun multiChoiceStringArgument(choiceSupplier: () -> List) = + delegateArgument(MultiChoiceArgument(DELEGATED_ARG_NAME) { choiceSupplier().associateWithTo(HashMap()) { it } }) + fun simpleMappedArgument() = delegateArgument(SimpleArgument(DELEGATED_ARG_NAME, "type")) \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderExpansionWrapper.kt b/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderExpansionWrapper.kt index e0551e1..9806aa7 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderExpansionWrapper.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderExpansionWrapper.kt @@ -1,8 +1,13 @@ package com.mattmx.ktgui.papi +import com.mattmx.ktgui.commands.declarative.DeclarativeCommandBuilder +import com.mattmx.ktgui.commands.declarative.arg.ArgumentContext +import com.mattmx.ktgui.commands.declarative.arg.ArgumentProcessor +import com.mattmx.ktgui.commands.declarative.invocation.StorageCommandContext import me.clip.placeholderapi.expansion.PlaceholderExpansion import org.bukkit.entity.Player import org.bukkit.plugin.java.JavaPlugin +import java.util.* class PlaceholderExpansionWrapper( private val owner: JavaPlugin @@ -10,17 +15,23 @@ class PlaceholderExpansionWrapper( private val placeholders = arrayListOf() var id = owner.name private set + var _persists = false + private set var _author = owner.pluginMeta.authors.joinToString(", ") private set var _version = owner.pluginMeta.version private set var splitArgs = { params: String -> params.split("_") } private set + var requiresPredicate = Optional.empty<() -> Boolean>() + var isDebug = false override fun getIdentifier() = id override fun getAuthor() = _author override fun getVersion() = _version override fun getPlaceholders() = placeholders.map { it.toString() }.toMutableList() + override fun persist() = _persists + override fun canRegister() = if (requiresPredicate.isPresent) requiresPredicate.get()() else true infix fun id(id: String) = apply { this.id = id @@ -38,17 +49,61 @@ class PlaceholderExpansionWrapper( this.splitArgs = splitArgs } + infix fun persists(persists: Boolean) = apply { + this._persists = persists + } + + infix fun requires(predicate: () -> Boolean) = apply { + this.requiresPredicate = Optional.of(predicate) + } + infix fun registerPlaceholder(placeholder: Placeholder) = placeholders.add(placeholder) override fun onPlaceholderRequest(player: Player?, params: String): String? { - val context = PlaceholderParseContext(player, splitArgs(params)) + val paramsSplit = splitArgs(params) + + val args = hashMapOf>() + val baseContext = if (player != null) + StorageCommandContext(player, paramsSplit.firstOrNull() ?: "", paramsSplit) + else null + for (placeholder in placeholders.sortedByDescending { it.priority }) { - val content = placeholder.parse(context) + val identifier = placeholder.match.name + if (paramsSplit.getOrNull(0) != identifier) continue + + val argumentParser = ArgumentProcessor(emptyCommand, baseContext, paramsSplit) + + var invalid = false - if (content != null) { - return content.toString() + for (expArg in placeholder.match.arguments) { + if (invalid) continue + + val stringValue = expArg.consume(argumentParser) + + if (isDebug) { + owner.logger.warning("Failed parsing for arg $expArg in placeholder $name") + } + + if (expArg.isRequired() && stringValue.isEmpty()) { + invalid = true + continue + } else { + args[expArg.name()] = expArg.createContext(emptyCommand, baseContext, stringValue.stringValue) + } + } + if (invalid) continue + + val context = PlaceholderParseContext(player, paramsSplit, args) + val result = placeholder.parse(context) + + if (result != null) { + return result.toString() } } return null } + + companion object { + val emptyCommand = DeclarativeCommandBuilder("null") + } } \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderParseContext.kt b/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderParseContext.kt index f00a4f9..dce5c35 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderParseContext.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/papi/PlaceholderParseContext.kt @@ -1,13 +1,18 @@ package com.mattmx.ktgui.papi import com.mattmx.ktgui.commands.declarative.arg.Argument +import com.mattmx.ktgui.commands.declarative.arg.ArgumentContext import org.bukkit.entity.Player class PlaceholderParseContext( val requestedBy: Player?, - val params: List + val params: List, + val providedArguments: HashMap> ) { - operator fun Argument.invoke(): T = TODO() + operator fun Argument.invoke(): T = context.getOrNull()!! + + val Argument.context + get() = providedArguments[name()] as ArgumentContext? ?: ArgumentContext.empty(this) } \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/papi/dsl.kt b/api/src/main/kotlin/com/mattmx/ktgui/papi/dsl.kt index db63fad..bfe64d4 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/papi/dsl.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/papi/dsl.kt @@ -6,8 +6,8 @@ import org.bukkit.plugin.java.JavaPlugin inline fun JavaPlugin.placeholderExpansion(builder: PlaceholderExpansionWrapper.() -> Unit) = PlaceholderExpansionWrapper(this).apply(builder).apply { register() } -fun placeholder(string: String, supplier: PlaceholderParseContext.() -> Any?) = - Placeholder(ChainCommandBuilder(string), supplier) +fun PlaceholderExpansionWrapper.placeholder(string: String, supplier: PlaceholderParseContext.() -> Any?) = + Placeholder(ChainCommandBuilder(string), supplier).apply { registerPlaceholder(this) } -fun placeholder(chain: ChainCommandBuilder, supplier: PlaceholderParseContext.() -> Any?) = - Placeholder(chain, supplier) \ No newline at end of file +fun PlaceholderExpansionWrapper.placeholder(chain: ChainCommandBuilder, supplier: PlaceholderParseContext.() -> Any?) = + Placeholder(chain, supplier).apply { registerPlaceholder(this) } \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/utils/formatting.kt b/api/src/main/kotlin/com/mattmx/ktgui/utils/formatting.kt index 3257243..8a89e87 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/utils/formatting.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/utils/formatting.kt @@ -83,4 +83,13 @@ fun Number.pretty(): String { * * @return formatted [Int] as a [String] */ -fun Int.commas() = "%,d".format(this) \ No newline at end of file +fun Int.commas() = "%,d".format(this) + +/** + * Insert commas every 3 digits. + * + * `e.g 142332 -> 142,332` + * + * @return formatted [Long] as a [String] + */ +fun Long.commas() = "%,d".format(this) \ No newline at end of file diff --git a/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt b/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt index d8e131d..ea0c75c 100644 --- a/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt +++ b/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt @@ -12,13 +12,16 @@ import com.mattmx.ktgui.components.screen.GuiScreen import com.mattmx.ktgui.cooldown.ActionCoolDown import com.mattmx.ktgui.designer.GuiDesigner import com.mattmx.ktgui.examples.* +import com.mattmx.ktgui.papi.PlaceholderParseContext import com.mattmx.ktgui.papi.placeholder import com.mattmx.ktgui.papi.placeholderExpansion import com.mattmx.ktgui.scheduling.sync import com.mattmx.ktgui.sound.playSound import com.mattmx.ktgui.sound.soundBuilder +import com.mattmx.ktgui.utils.commas import com.mattmx.ktgui.utils.not import com.mattmx.ktgui.utils.pretty +import me.clip.placeholderapi.PlaceholderAPI import org.bukkit.Bukkit import org.bukkit.Sound import org.bukkit.command.CommandSender @@ -75,11 +78,19 @@ class KotlinGui : JavaPlugin() { placeholderExpansion { - val player by playerArgument() + val startCharIndex = 'a'.code + val fontMap = "ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ" + .map { Char(startCharIndex) to it } + .toMap(HashMap()) + val stringToConvert by greedyStringArgument() + placeholder("st" / stringToConvert) { + String(stringToConvert().map { fontMap[it] ?: it }.toCharArray()) + } - placeholder("ping" / player) { player().ping } - placeholder("ping") { requestedBy?.ping } - placeholder("iscool" / player) { if (player().name == author) "this player's sick" else "nah not rly" } + placeholder("stph" / stringToConvert) { + val string = PlaceholderAPI.setPlaceholders(requestedBy, stringToConvert()) + String(string.map { fontMap[it] ?: it }.toCharArray()) + } } id "ktgui" author "MattMX"