diff --git a/.idea/kotlinScripting.xml b/.idea/kotlinScripting.xml deleted file mode 100644 index bc444dea..00000000 --- a/.idea/kotlinScripting.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 0e65ceac..8d81632f 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 5268d7b6..b409d5a8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -11,7 +11,7 @@ - + \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/build.gradle.kts b/ScriptableMC-Engine-Core/build.gradle.kts index cbd5cecb..9a006635 100644 --- a/ScriptableMC-Engine-Core/build.gradle.kts +++ b/ScriptableMC-Engine-Core/build.gradle.kts @@ -3,16 +3,17 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java id("org.jetbrains.kotlin.jvm") - id("com.github.johnrengelman.shadow") +// id("com.github.johnrengelman.shadow") + id("io.github.goooler.shadow") id("org.jetbrains.gradle.plugin.idea-ext") } -var graalvmVersion = findProperty("dependencies.graalvm.version") ?: "22.3.0" -var spigotmcVersion = findProperty("dependencies.spigotmc.version") ?: "1.19.2-R0.1-SNAPSHOT" +var graalvmVersion = findProperty("dependencies.graalvm.version") ?: "23.0.2" +var spigotmcVersion = findProperty("dependencies.spigotmc.version") ?: "1.20.4-R0.1-SNAPSHOT" java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } idea { @@ -42,9 +43,7 @@ dependencies { implementation("com.github.kittinunf.fuel:fuel:2.3.1") implementation("com.github.kittinunf.fuel:fuel-json:2.3.1") implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT") - implementation("de.tr7zw:item-nbt-api:2.8.0") - implementation("fr.minuskube.inv:smart-invs:1.2.7") - compileOnly("me.clip:placeholderapi:2.11.2") + compileOnly("me.clip:placeholderapi:2.11.5") coreShadow(project) @@ -54,9 +53,7 @@ dependencies { coreShadow("com.github.kittinunf.fuel:fuel:2.3.1") coreShadow("com.github.kittinunf.fuel:fuel-json:2.3.1") coreShadow("co.aikar:acf-paper:0.5.1-SNAPSHOT") - coreShadow("de.tr7zw:item-nbt-api:2.8.0") - coreShadow("fr.minuskube.inv:smart-invs:1.2.7") - coreShadow("me.clip:placeholderapi:2.11.2") + coreShadow("me.clip:placeholderapi:2.11.5") testImplementation("junit", "junit", "4.12") } @@ -67,10 +64,10 @@ tasks.shadowJar { } tasks.compileKotlin { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "17" kotlinOptions.javaParameters = true } tasks.compileTestKotlin { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "17" kotlinOptions.javaParameters = true } \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/ScriptablePluginEngineBootstrapper.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/ScriptablePluginEngineBootstrapper.kt index f0234f00..a4c5a324 100644 --- a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/ScriptablePluginEngineBootstrapper.kt +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/ScriptablePluginEngineBootstrapper.kt @@ -3,22 +3,71 @@ package com.pixlfox.scriptablemc import co.aikar.commands.PaperCommandManager import com.pixlfox.scriptablemc.core.ScriptablePluginEngine import com.smc.version.Version -import org.bukkit.ChatColor import org.bukkit.command.CommandSender import org.bukkit.plugin.java.JavaPlugin +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.OutputStream +import java.util.logging.Level -@Suppress("unused") +@Suppress("unused", "MemberVisibilityCanBePrivate") abstract class ScriptablePluginEngineBootstrapper : JavaPlugin() { lateinit var scriptEngine: ScriptablePluginEngine lateinit var commandManager: PaperCommandManager abstract val chatMessagePrefix: String abstract val scriptLanguage: String + lateinit var sharedDataFolder: File + val pluginVersion: Version get() = Version.parse("v${description.version}") abstract fun reloadScriptEngine(sender: CommandSender? = null) + override fun onLoad() { + sharedDataFolder = File(file.parent, "ScriptableMC") + registerScriptEngine(scriptLanguage, this) + } + + override fun saveResource(resourcePath: String, replace: Boolean) { + val resourceStream = getResource(resourcePath.replace('\\', '/')) + ?: throw IllegalArgumentException("The embedded resource '$resourcePath' cannot be found in $file") + val outFile = File(sharedDataFolder, resourcePath) + val lastIndex = resourcePath.lastIndexOf('/') + val outDir = File(sharedDataFolder, resourcePath.substring(0, if (lastIndex >= 0) lastIndex else 0)) + if (!outDir.exists()) { + outDir.mkdirs() + } + try { + if (!outFile.exists() || replace) { + val out: OutputStream = FileOutputStream(outFile) + val buf = ByteArray(1024) + var len: Int + while (resourceStream.read(buf).also { len = it } > 0) { + out.write(buf, 0, len) + } + out.close() + resourceStream.close() + } else { + logger.log( + Level.WARNING, + "Could not save " + outFile.name + " to " + outFile + " because " + outFile.name + " already exists." + ) + } + } catch (ex: IOException) { + logger.log(Level.SEVERE, "Could not save " + outFile.name + " to " + outFile, ex) + } + } + + override fun saveDefaultConfig() { + + } + + override fun saveConfig() { + super.saveConfig() + } + fun versionCheck(sender: CommandSender? = null) { // if(config.getBoolean("version_check", true)) { // khttp.async.get("https://api.github.com/repos/astorks/ScriptableMC-Engine/releases/latest") { diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginCommandManager.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginCommandManager.kt new file mode 100644 index 00000000..3b629ea0 --- /dev/null +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginCommandManager.kt @@ -0,0 +1,87 @@ +package com.pixlfox.scriptablemc.core + +import org.bukkit.Bukkit +import org.bukkit.command.CommandMap +import org.bukkit.command.PluginCommand +import org.bukkit.plugin.Plugin +import java.lang.reflect.InvocationTargetException +import java.util.HashMap + +@Suppress("unused", "MemberVisibilityCanBePrivate") +class ScriptablePluginCommandManager(private val context: ScriptablePluginContext) { + + private val commands: MutableList = mutableListOf() + + fun newCommand(name: String): PluginCommand? { + var command: PluginCommand? = null + + try { + val c = PluginCommand::class.java.getDeclaredConstructor(String::class.java, Plugin::class.java) + c.isAccessible = true + + command = c.newInstance(name, context.javaPlugin as Plugin) + } catch (e: SecurityException) { + e.printStackTrace() + } catch (e: IllegalArgumentException) { + e.printStackTrace() + } catch (e: IllegalAccessException) { + e.printStackTrace() + } catch (e: InstantiationException) { + e.printStackTrace() + } catch (e: InvocationTargetException) { + e.printStackTrace() + } catch (e: NoSuchMethodException) { + e.printStackTrace() + } + + return command + } + + fun registerCommand(command: PluginCommand) { + val bukkitCommandMap = Bukkit.getServer().javaClass.getDeclaredField("commandMap") + bukkitCommandMap.isAccessible = true + val commandMap = bukkitCommandMap.get(Bukkit.getServer()) as CommandMap + commandMap.register(context.pluginName.lowercase(), command) + commands.add(command) + bukkitCommandMap.isAccessible = false + + if(context.engine.debugEnabled) { + context.engine.bootstrapper.logger.info("[${context.pluginName}] Registered command ${command.name}.") + } + } + + fun unregisterCommand(command: PluginCommand) { + val commandMapField = Bukkit.getServer().javaClass.getDeclaredField("commandMap") + commandMapField.isAccessible = true + val commandMap = commandMapField.get(Bukkit.getServer()) as CommandMap + + var knownCommandsField = commandMap.javaClass.superclass.declaredFields.firstOrNull { it.name.equals("knownCommands", false) } + + if(knownCommandsField == null) { // Pre-MCv1.13 command unregister fix + knownCommandsField = commandMap.javaClass.declaredFields.firstOrNull { it.name.equals("knownCommands", false) } + } + + knownCommandsField?.isAccessible = true + val knownCommands = knownCommandsField?.get(commandMap) as HashMap<*, *>? + + command.unregister(commandMap) + + knownCommands?.remove(command.name) + commands.remove(command) + + commandMapField.isAccessible = false + knownCommandsField?.isAccessible = false + + if(context.engine.debugEnabled) { + context.engine.bootstrapper.logger.info("[${context.pluginName}] Unregistered command ${command.name}.") + } + } + + fun unregisterAllCommands(): Int { + val commands = commands.toTypedArray() + for(command in commands) { + unregisterCommand(command) + } + return commands.size + } +} \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginContext.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginContext.kt index d3211d96..0902eeed 100644 --- a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginContext.kt +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginContext.kt @@ -6,12 +6,8 @@ import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.OfflinePlayer import org.bukkit.Server -import org.bukkit.command.CommandMap import org.bukkit.event.Event -import org.bukkit.event.EventPriority import org.bukkit.event.Listener -import java.util.HashMap -import java.lang.reflect.InvocationTargetException import org.bukkit.command.PluginCommand import org.bukkit.entity.Player import org.bukkit.plugin.* @@ -26,111 +22,165 @@ abstract class ScriptablePluginContext: Listener { abstract val engine: ScriptablePluginEngine abstract val pluginName: String abstract val pluginInstance: Value - abstract val pluginVersion: Version - abstract val logger: ScriptablePluginLogger - abstract val scheduler: ScriptablePluginScheduler open val pluginIcon: Material = Material.STONE open val pluginPriority: Int = 0 + lateinit var logger: ScriptablePluginLogger + internal set + + lateinit var scheduler: ScriptablePluginScheduler + internal set + + lateinit var commandManager: ScriptablePluginCommandManager + internal set + + lateinit var eventManager: ScriptablePluginEventManager + internal set + + lateinit var messenger: ScriptablePluginMessenger + internal set + var isEnabled: Boolean = false internal set val server: Server get() = Bukkit.getServer() + val pluginVersion: Version + get() = engine.pluginVersion + val javaPlugin: JavaPlugin get() = engine.bootstrapper val servicesManager: ServicesManager get() = Bukkit.getServicesManager() - val commands: MutableList = mutableListOf() + open fun load() { + logger = ScriptablePluginLogger(this) + eventManager = ScriptablePluginEventManager(this) + scheduler = ScriptablePluginScheduler(this) + commandManager = ScriptablePluginCommandManager(this) + messenger = ScriptablePluginMessenger(this) + + if(engine.debugEnabled) { + logger.info("Loading scriptable plugin context.") + } + + if(pluginInstance.hasMember("onLoad")) { + if(pluginInstance.canInvokeMember("onLoad")) { + pluginInstance.invokeMember("onLoad") + } else { + logger.warning("onLoad method is not invokable.") + } + } + } + + open fun enable() { + if(engine.debugEnabled) { + logger.info("Enabling scriptable plugin context.") + } - abstract fun load() + if(pluginInstance.hasMember("onEnable")) { + if(pluginInstance.canInvokeMember("onEnable")) { + pluginInstance.invokeMember("onEnable") + } else { + logger.warning("onEnable method is not invokable.") + } + } - abstract fun enable() + isEnabled = true + } - abstract fun disable() + open fun disable() { + if(engine.debugEnabled) { + logger.info("Disabling scriptable plugin context.") + } - abstract fun unload() + if(pluginInstance.hasMember("onDisable")) { + if(pluginInstance.canInvokeMember("onDisable")) { + pluginInstance.invokeMember("onDisable") + } else { + logger.warning("onDisable method is not invokable.") + } + } + isEnabled = false + } + + open fun unload() { + scheduler.cancelAllTasks() + commandManager.unregisterAllCommands() + eventManager.unregisterAllEvents() + + if(engine.debugEnabled) { + logger.info("Unloading scriptable plugin context.") + } + + if(pluginInstance.hasMember("onUnload")) { + if(pluginInstance.canInvokeMember("onUnload")) { + pluginInstance.invokeMember("onUnload") + } else { + logger.warning("onUnload method is not invokable.") + } + } + } + + fun getBukkitServiceRegistration(className: String): Any? { + val serviceClass = servicesManager.knownServices.firstOrNull { e -> e.name == className } + + if(serviceClass != null) { + return getBukkitServiceRegistration(serviceClass) + } + + return null + } + + fun getBukkitServiceRegistration(_class: Class<*>): Any? { + return servicesManager.getRegistration(_class) + } + + // + @Deprecated("use getEventManager().registerEvent(eventClass, executor)", ReplaceWith("eventManager.registerEvent(eventClass, executor)")) fun registerEvent(eventClass: Class, executor: EventExecutor) { - Bukkit.getServer().pluginManager.registerEvent(eventClass, this, EventPriority.NORMAL, executor, javaPlugin) + eventManager.registerEvent(eventClass, executor) } + @Deprecated("use getMessenger().registerIncomingPluginChannel(channelName, listener)", ReplaceWith("messenger.registerIncomingPluginChannel(channelName, listener)")) fun registerIncomingPluginChannel(channelName: String, listener: PluginMessageListener): PluginMessageListenerRegistration { - return Bukkit.getMessenger().registerIncomingPluginChannel(javaPlugin, channelName, listener) + return messenger.registerIncomingPluginChannel(channelName, listener) } + @Deprecated("use getMessenger().unregisterIncomingPluginChannel(channel)", ReplaceWith("messenger.unregisterIncomingPluginChannel(channel)")) fun unregisterIncomingPluginChannel(channel: String) { - Bukkit.getMessenger().unregisterIncomingPluginChannel(javaPlugin, channel) + messenger.unregisterIncomingPluginChannel(channel) } + @Deprecated("use getMessenger().registerOutgoingPluginChannel(channel)", ReplaceWith("messenger.registerOutgoingPluginChannel(channel)")) fun registerOutgoingPluginChannel(channel: String) { - Bukkit.getMessenger().registerOutgoingPluginChannel(javaPlugin, channel) + messenger.registerOutgoingPluginChannel(channel) } + @Deprecated("use getMessenger().unregisterOutgoingPluginChannel(channel)", ReplaceWith("messenger.unregisterOutgoingPluginChannel(channel)")) fun unregisterOutgoingPluginChannel(channel: String) { - Bukkit.getMessenger().unregisterOutgoingPluginChannel(javaPlugin, channel) + messenger.unregisterOutgoingPluginChannel(channel) } + @Deprecated("use getCommandManager().newCommand(name)", ReplaceWith("commandManager.newCommand(name)")) fun newCommand(name: String): PluginCommand? { - var command: PluginCommand? = null - - try { - val c = PluginCommand::class.java.getDeclaredConstructor(String::class.java, Plugin::class.java) - c.isAccessible = true - - command = c.newInstance(name, javaPlugin as Plugin) - } catch (e: SecurityException) { - e.printStackTrace() - } catch (e: IllegalArgumentException) { - e.printStackTrace() - } catch (e: IllegalAccessException) { - e.printStackTrace() - } catch (e: InstantiationException) { - e.printStackTrace() - } catch (e: InvocationTargetException) { - e.printStackTrace() - } catch (e: NoSuchMethodException) { - e.printStackTrace() - } - - return command + return commandManager.newCommand(name) } + @Deprecated("use getCommandManager().registerCommand(command)", ReplaceWith("commandManager.registerCommand(command)")) fun registerCommand(command: PluginCommand) { - val bukkitCommandMap = Bukkit.getServer().javaClass.getDeclaredField("commandMap") - bukkitCommandMap.isAccessible = true - val commandMap = bukkitCommandMap.get(Bukkit.getServer()) as CommandMap - commandMap.register(this.pluginName.lowercase(), command) - commands.add(command) - bukkitCommandMap.isAccessible = false + commandManager.registerCommand(command) } + @Deprecated("use getCommandManager().unregisterCommand(command)", ReplaceWith("commandManager.unregisterCommand(command)")) fun unregisterCommand(command: PluginCommand) { - val commandMapField = Bukkit.getServer().javaClass.getDeclaredField("commandMap") - commandMapField.isAccessible = true - val commandMap = commandMapField.get(Bukkit.getServer()) as CommandMap - - var knownCommandsField = commandMap.javaClass.superclass.declaredFields.firstOrNull { it.name.equals("knownCommands", false) } - - if(knownCommandsField == null) { // Pre-MCv1.13 command unregister fix - knownCommandsField = commandMap.javaClass.declaredFields.firstOrNull { it.name.equals("knownCommands", false) } - } - - knownCommandsField?.isAccessible = true - val knownCommands = knownCommandsField?.get(commandMap) as HashMap<*, *>? - - command.unregister(commandMap) - - knownCommands?.remove(command.name) - commands.remove(command) - - commandMapField.isAccessible = false - knownCommandsField?.isAccessible = false + return commandManager.unregisterCommand(command) } + @Deprecated("use PlaceholderAPI.setPlaceholders(player, placeholderText)", ReplaceWith("PlaceholderAPI.setPlaceholders(player, placeholderText)")) fun setPlaceholders(player: Player, placeholderText: String): String { if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { return PlaceholderAPI.setPlaceholders(player, placeholderText) @@ -140,6 +190,7 @@ abstract class ScriptablePluginContext: Listener { return placeholderText } + @Deprecated("use PlaceholderAPI.setPlaceholders(player, placeholderText)", ReplaceWith("PlaceholderAPI.setPlaceholders(player, placeholderText)")) fun setPlaceholders(player: OfflinePlayer, placeholderText: String): String { if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { return PlaceholderAPI.setPlaceholders(player, placeholderText) @@ -148,18 +199,5 @@ abstract class ScriptablePluginContext: Listener { engine.bootstrapper.logger.warning("[$pluginName] Placeholder API is missing.") return placeholderText } - - fun getBukkitServiceRegistration(className: String): Any? { - val serviceClass = servicesManager.knownServices.firstOrNull { e -> e.name == className } - - if(serviceClass != null) { - return getBukkitServiceRegistration(serviceClass) - } - - return null - } - - fun getBukkitServiceRegistration(_class: Class<*>): Any? { - return servicesManager.getRegistration(_class) - } + // } \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEngine.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEngine.kt index 51304df0..be4c9a32 100644 --- a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEngine.kt +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEngine.kt @@ -4,8 +4,6 @@ import com.pixlfox.scriptablemc.ScriptablePluginEngineBootstrapper import com.pixlfox.scriptablemc.ScriptablePluginEngineConfig import com.smc.exceptions.ScriptNotFoundException import com.smc.version.Version -import fr.minuskube.inv.InventoryManager -import org.bukkit.Bukkit import org.bukkit.command.CommandSender import org.graalvm.polyglot.* import java.io.File @@ -25,9 +23,6 @@ abstract class ScriptablePluginEngine { abstract val config: ScriptablePluginEngineConfig - val inventoryManager: InventoryManager - get() = InventoryManager(bootstrapper) - val pluginVersion: Version get() = bootstrapper.pluginVersion @@ -217,14 +212,9 @@ abstract class ScriptablePluginEngine { val preLoadClasses: Array = arrayOf( "com.smc.version.Version", "com.smc.version.MinecraftVersions", - "com.smc.utils.ItemBuilder", "com.smc.utils.MysqlWrapper", - - "com.smc.smartinvs.SmartInventory", - "com.smc.smartinvs.SmartInventoryProvider", - "org.apache.commons.io.FileUtils", - + "*org.apache.commons.io.FileUtils", "*me.clip.placeholderapi.PlaceholderAPI" ) } diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEventManager.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEventManager.kt new file mode 100644 index 00000000..6e2629c1 --- /dev/null +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginEventManager.kt @@ -0,0 +1,25 @@ +package com.pixlfox.scriptablemc.core + +import org.bukkit.Bukkit +import org.bukkit.event.Event +import org.bukkit.event.EventPriority +import org.bukkit.event.HandlerList +import org.bukkit.plugin.EventExecutor + +@Suppress("unused", "MemberVisibilityCanBePrivate") +class ScriptablePluginEventManager(private val context: ScriptablePluginContext) { + @JvmOverloads + fun registerEvent( + eventClass: Class, + executor: EventExecutor, + priority: EventPriority = EventPriority.NORMAL, + ignoreCancelled: Boolean = false + ) { + Bukkit.getServer().pluginManager.registerEvent(eventClass, context, priority, executor, context.javaPlugin, ignoreCancelled) + } + + fun unregisterAllEvents() { + HandlerList.unregisterAll(context.javaPlugin) + } +} + diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginMessenger.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginMessenger.kt new file mode 100644 index 00000000..7bed96f1 --- /dev/null +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginMessenger.kt @@ -0,0 +1,26 @@ +package com.pixlfox.scriptablemc.core + +import org.bukkit.Bukkit +import org.bukkit.plugin.messaging.PluginMessageListener +import org.bukkit.plugin.messaging.PluginMessageListenerRegistration + +@Suppress("unused", "MemberVisibilityCanBePrivate") +class ScriptablePluginMessenger(private val context: ScriptablePluginContext) { + private val messenger = Bukkit.getMessenger() + + fun registerIncomingPluginChannel(channelName: String, listener: PluginMessageListener): PluginMessageListenerRegistration { + return messenger.registerIncomingPluginChannel(context.javaPlugin, channelName, listener) + } + + fun unregisterIncomingPluginChannel(channel: String) { + messenger.unregisterIncomingPluginChannel(context.javaPlugin, channel) + } + + fun registerOutgoingPluginChannel(channel: String) { + messenger.registerOutgoingPluginChannel(context.javaPlugin, channel) + } + + fun unregisterOutgoingPluginChannel(channel: String) { + messenger.unregisterOutgoingPluginChannel(context.javaPlugin, channel) + } +} \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginScheduler.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginScheduler.kt index 6110ba96..79104b91 100644 --- a/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginScheduler.kt +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/pixlfox/scriptablemc/core/ScriptablePluginScheduler.kt @@ -1,23 +1,32 @@ package com.pixlfox.scriptablemc.core import org.bukkit.Bukkit +import org.bukkit.plugin.java.JavaPlugin import org.bukkit.scheduler.BukkitTask +@Suppress("unused", "MemberVisibilityCanBePrivate") class ScriptablePluginScheduler(private val context: ScriptablePluginContext) { private val serverScheduler = Bukkit.getScheduler() private val tasks = mutableListOf() - fun runTaskTimer(run: () -> Unit, delay: Long, period: Long): BukkitTask { + fun runTaskTimer(delay: Long, period: Long, run: () -> Unit): BukkitTask { val task = serverScheduler.runTaskTimer(context.javaPlugin, Runnable { run.invoke() }, delay, period) tasks.add(task) return task } - fun cancelAllTasks() { + fun cancelTask(task: BukkitTask) { + if(!task.isCancelled) { + task.cancel() + } + tasks.remove(task) + } + + fun cancelAllTasks(): Int { + val tasks = tasks.toTypedArray() for(task in tasks) { - if(!task.isCancelled) { - task.cancel() - } + cancelTask(task) } + return tasks.size } } \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/smartinvs/SmartInventory.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/smartinvs/SmartInventory.kt deleted file mode 100644 index 9122234e..00000000 --- a/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/smartinvs/SmartInventory.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.smc.smartinvs - -import com.pixlfox.scriptablemc.core.ScriptablePluginEngine -import fr.minuskube.inv.ClickableItem -import fr.minuskube.inv.InventoryManager -import fr.minuskube.inv.SmartInventory -import fr.minuskube.inv.content.InventoryContents -import fr.minuskube.inv.content.InventoryProvider -import org.bukkit.entity.Player -import org.bukkit.event.inventory.InventoryClickEvent -import org.bukkit.inventory.ItemStack -import org.graalvm.polyglot.Value -import java.util.function.Consumer - -@Suppress("unused", "MemberVisibilityCanBePrivate") -class SmartInventory { - companion object { - @JvmStatic - fun builder(inventoryManager: InventoryManager): SmartInventory.Builder = SmartInventory.builder().manager(inventoryManager) - - @JvmStatic - fun provider(scriptableObject: Value): SmartInventoryProvider { - if (scriptableObject.canInstantiate()) { - return provider(scriptableObject.newInstance()) - } - - return SmartInventoryProvider(scriptableObject) - } - - @JvmStatic - fun clickableItem(item: ItemStack): ClickableItem = ClickableItem.empty(item) - - @JvmStatic - fun clickableItem(item: ItemStack, consumer: Consumer): ClickableItem = ClickableItem.of(item, consumer) - } -} - -class SmartInventoryProvider(private val scriptableObject: Value) : InventoryProvider { - override fun init(player: Player, contents: InventoryContents) { - if(scriptableObject.hasMember("init") && scriptableObject.canInvokeMember("init")) { - scriptableObject.invokeMember("init", player, contents) - } - } - - override fun update(player: Player, contents: InventoryContents) { - if(scriptableObject.hasMember("update") && scriptableObject.canInvokeMember("update")) { - scriptableObject.invokeMember("update", player, contents) - } - } -} \ No newline at end of file diff --git a/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/version/MinecraftVersions.kt b/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/version/MinecraftVersions.kt index 310e0971..e5a4af76 100644 --- a/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/version/MinecraftVersions.kt +++ b/ScriptableMC-Engine-Core/src/main/kotlin/com/smc/version/MinecraftVersions.kt @@ -34,6 +34,18 @@ import java.util.regex.Pattern @Suppress("unused") class MinecraftVersions private constructor(){ companion object { + /** + * Version 1.20 + */ + @JvmField + val v1_20 = parse("1.20") + + /** + * Version 1.19.3 - the update the broke a ton of plugins... + */ + @JvmField + val v1_19_3 = parse("1.19.3") + /** * Version 1.19 */ diff --git a/ScriptableMC-Engine-JS/build.gradle.kts b/ScriptableMC-Engine-JS/build.gradle.kts index ac6fc122..76f9f923 100644 --- a/ScriptableMC-Engine-JS/build.gradle.kts +++ b/ScriptableMC-Engine-JS/build.gradle.kts @@ -1,20 +1,25 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.apache.tools.ant.filters.ReplaceTokens +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName plugins { java id("org.jetbrains.kotlin.jvm") - id("com.github.johnrengelman.shadow") +// id("com.github.johnrengelman.shadow") + id("io.github.goooler.shadow") id("org.jetbrains.gradle.plugin.idea-ext") } -var pluginVersion = findProperty("plugin.version") ?: "1.0.0-SNAPSHOT" -var graalvmVersion = findProperty("dependencies.graalvm.version") ?: "22.3.0" -var spigotmcVersion = findProperty("dependencies.spigotmc.version") ?: "1.19.2-R0.1-SNAPSHOT" +var pluginVersion = findProperty("plugin.version") ?: "2.0.0-dev" +var graalvmVersion = findProperty("dependencies.graalvm.version") ?: "23.0.2" +var spigotmcVersion = findProperty("dependencies.spigotmc.version") ?: "1.20.4-R0.1-SNAPSHOT" + +version = pluginVersion java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } idea { @@ -24,8 +29,8 @@ idea { } } -val baseShadow by configurations.creating -val engineShadow by configurations.creating +val baseShadow: Configuration by configurations.creating +val engineShadow: Configuration by configurations.creating dependencies { implementation(project(":ScriptableMC-Engine-Core")) @@ -40,7 +45,6 @@ dependencies { compileOnly("co.aikar:acf-paper:0.5.1-SNAPSHOT") compileOnly("com.github.kittinunf.fuel:fuel:2.3.1") compileOnly("com.github.kittinunf.fuel:fuel-json:2.3.1") - compileOnly("fr.minuskube.inv:smart-invs:1.2.7") baseShadow(project) baseShadow("org.graalvm.sdk:graal-sdk:$graalvmVersion") @@ -48,7 +52,6 @@ dependencies { baseShadow("com.github.kittinunf.fuel:fuel:2.3.1") baseShadow("com.github.kittinunf.fuel:fuel-json:2.3.1") baseShadow("co.aikar:acf-paper:0.5.1-SNAPSHOT") - baseShadow("de.tr7zw:item-nbt-api:2.8.0") baseShadow("fr.minuskube.inv:smart-invs:1.2.7") engineShadow("org.graalvm.js:js:$graalvmVersion") @@ -69,21 +72,29 @@ tasks { } compileKotlin { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "17" kotlinOptions.javaParameters = true } compileTestKotlin { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "17" kotlinOptions.javaParameters = true } - jar { } + jar { + archiveBaseName.set("smcjs-classes") + } + + shadowJar { + enabled = false + dependsOn("shadowJarBase") + dependsOn("shadowJarEngine") + } register("shadowJarBase", ShadowJar::class.java) { group = "shadow" configurations = listOf(baseShadow) - archiveFileName.set("ScriptableMC-Engine-JS.jar") + archiveFileName.set("smcjs-$pluginVersion.jar") dependencies { exclude(dependency("org.spigotmc:spigot-api")) @@ -105,7 +116,7 @@ tasks { register("shadowJarEngine", ShadowJar::class.java) { group = "shadow" configurations = listOf(baseShadow, engineShadow) - archiveFileName.set("ScriptableMC-Engine-JS-Bundled.jar") + archiveFileName.set("smcjs-bundle-$pluginVersion.jar") dependencies { exclude(dependency("org.spigotmc:spigot-api")) diff --git a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineBootstrapper.kt b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineBootstrapper.kt index 65b79575..ec7f7391 100644 --- a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineBootstrapper.kt +++ b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineBootstrapper.kt @@ -1,23 +1,30 @@ package com.pixlfox.scriptablemc.js import co.aikar.commands.PaperCommandManager -import com.pixlfox.scriptablemc.ScriptablePluginEngineCommands +import com.google.common.base.Charsets import com.pixlfox.scriptablemc.ScriptablePluginEngineBootstrapper +import com.pixlfox.scriptablemc.ScriptablePluginEngineCommands import com.pixlfox.scriptablemc.js.core.JavaScriptPluginEngine import org.bukkit.ChatColor import org.bukkit.command.CommandSender +import org.bukkit.configuration.file.FileConfiguration +import org.bukkit.configuration.file.YamlConfiguration +import java.io.File +import java.io.InputStreamReader @Suppress("unused") class JavaScriptPluginEngineBootstrapper : ScriptablePluginEngineBootstrapper() { override val chatMessagePrefix = "${ChatColor.GRAY}[${ChatColor.DARK_AQUA}ScriptableMC-JS${ChatColor.GRAY}]${ChatColor.RESET}" override val scriptLanguage = "js" - + private var newConfig: YamlConfiguration? = null + lateinit var jsConfigFile: File lateinit var jsConfig: JavaScriptPluginEngineConfig override fun onLoad() { + super.onLoad() + jsConfigFile = File(sharedDataFolder, "config_js.yml") instance = this - registerScriptEngine(scriptLanguage, this) saveDefaultConfig() } @@ -29,7 +36,6 @@ class JavaScriptPluginEngineBootstrapper : ScriptablePluginEngineBootstrapper() server.scheduler.scheduleSyncDelayedTask(this, Runnable { fullLoadScriptEngine() enableScriptEngine() - server.dispatchCommand(server.consoleSender, "minecraft:reload") }) } @@ -39,6 +45,26 @@ class JavaScriptPluginEngineBootstrapper : ScriptablePluginEngineBootstrapper() unloadScriptEngine() } + override fun saveDefaultConfig() { + super.saveDefaultConfig() + if (!jsConfigFile.exists()) { + saveResource("config_js.yml", false) + } + } + + override fun reloadConfig() { + newConfig = YamlConfiguration.loadConfiguration(jsConfigFile) + val defConfigStream = getResource("config_js.yml") ?: return + newConfig?.setDefaults(YamlConfiguration.loadConfiguration(InputStreamReader(defConfigStream, Charsets.UTF_8))) + } + + override fun getConfig(): FileConfiguration { + if (newConfig == null) { + reloadConfig() + } + return newConfig!! + } + private fun fullUnloadScriptEngine(sender: CommandSender? = null) { patchClassLoader(javaClass) { try { diff --git a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineCommands.kt b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineCommands.kt index 8ff53cc8..ca13adcc 100644 --- a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineCommands.kt +++ b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/JavaScriptPluginEngineCommands.kt @@ -31,12 +31,49 @@ class JavaScriptPluginEngineCommands(private val bootstrapper: JavaScriptPluginE bootstrapper.fullReloadScriptEngine(sender) } - @Subcommand("pastebin|pb") - @CommandAlias("jsexpb") - @CommandPermission("scriptablemc.js.execute.pastebin") - @Syntax("") - fun executePastebin(sender: CommandSender, code: String) { - val (_, _, result) = "https://pastebin.com/raw/$code".httpGet().responseString() +// @Subcommand("pastebin|pb") +// @CommandAlias("jsexpb") +// @CommandPermission("scriptablemc.js.execute.pastebin") +// @Syntax("") +// fun executePastebin(sender: CommandSender, code: String) { +// val (_, _, result) = "https://pastebin.com/raw/$code".httpGet().responseString() +// result.success { +// executeCode(sender, it) +// } +// } + + @Subcommand("exhttp|exh") + @CommandAlias("jsexh") + @CommandPermission("scriptablemc.js.execute.http") + @Syntax("") + fun executeHttp(sender: CommandSender, url: String) { + var pixlfoxRegex = Regex("https://paste.pixlfox.net/([a-zA-Z0-9]*?)\$") + val pastebinRegex = Regex("https://pastebin.com/(.*?)\$") + + var parsedUrl = url + + + if(url.matches(pixlfoxRegex)) { + val match = pixlfoxRegex.matchEntire(url) + if(match != null) { + val pasteCode = match.groups[1]?.value + if(pasteCode != null) { + parsedUrl = "https://paste.pixlfox.net/$pasteCode/raw" + } + } + } + + if(url.matches(pastebinRegex)) { + val match = pastebinRegex.matchEntire(url) + if(match != null) { + val pastebinCode = match.groups[1]?.value + if(pastebinCode != null) { + parsedUrl = "https://pastebin.com/raw/$pastebinCode" + } + } + } + + val (_, _, result) = parsedUrl.httpGet().responseString() result.success { executeCode(sender, it) } diff --git a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginContext.kt b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginContext.kt index 6b93ba0f..88e50ecb 100644 --- a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginContext.kt +++ b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginContext.kt @@ -11,78 +11,6 @@ import org.graalvm.polyglot.Value @Suppress("MemberVisibilityCanBePrivate", "unused") class JavaScriptPluginContext(override val engine: ScriptablePluginEngine, override val pluginName: String, override val pluginPriority: Int, override val pluginIcon: Material, override val pluginInstance: Value) : ScriptablePluginContext() { - override val pluginVersion = engine.pluginVersion - override val logger = ScriptablePluginLogger(this) - override val scheduler = ScriptablePluginScheduler(this) - - override fun load() { - if(engine.debugEnabled) { - engine.bootstrapper.logger.info("[$pluginName] Loading JavaScript plugin context.") - } - - if(pluginInstance.hasMember("onLoad")) { - if(pluginInstance.canInvokeMember("onLoad")) { - pluginInstance.invokeMember("onLoad") - } else { - engine.bootstrapper.logger.warning("$pluginName::onLoad is not a method.") - } - } - } - - override fun enable() { - if(engine.debugEnabled) { - engine.bootstrapper.logger.info("[$pluginName] Enabling JavaScript plugin context.") - } - - if(pluginInstance.hasMember("onEnable")) { - if(pluginInstance.canInvokeMember("onEnable")) { - pluginInstance.invokeMember("onEnable") - } else { - engine.bootstrapper.logger.warning("$pluginName::onEnable is not a method.") - } - } - - isEnabled = true - } - - override fun disable() { - if(engine.debugEnabled) { - engine.bootstrapper.logger.info("[$pluginName] Disabling JavaScript plugin context.") - } - - if(pluginInstance.hasMember("onDisable")) { - if(pluginInstance.canInvokeMember("onDisable")) { - pluginInstance.invokeMember("onDisable") - } else { - engine.bootstrapper.logger.warning("$pluginName::onDisable is not a method.") - } - } - - HandlerList.unregisterAll(this) - - val commands = commands.toTypedArray() - for(command in commands) { - unregisterCommand(command) - } - isEnabled = false - } - - override fun unload() { - scheduler.cancelAllTasks() - - if(engine.debugEnabled) { - engine.bootstrapper.logger.info("[$pluginName] Unloading JavaScript plugin context.") - } - - if(pluginInstance.hasMember("onUnload")) { - if(pluginInstance.canInvokeMember("onUnload")) { - pluginInstance.invokeMember("onUnload") - } else { - engine.bootstrapper.logger.warning("$pluginName::onUnload is not a method.") - } - } - } - companion object { fun newInstance(pluginName: String, pluginPriority: Int, pluginIcon: Material, engine: ScriptablePluginEngine, pluginInstance: Value): ScriptablePluginContext { if(engine.debugEnabled) { diff --git a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginEngine.kt b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginEngine.kt index a1f08cbf..ec7c3456 100644 --- a/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginEngine.kt +++ b/ScriptableMC-Engine-JS/src/main/kotlin/com/pixlfox/scriptablemc/js/core/JavaScriptPluginEngine.kt @@ -5,9 +5,9 @@ import com.pixlfox.scriptablemc.core.ScriptablePluginContext import com.pixlfox.scriptablemc.core.ScriptablePluginEngine import com.pixlfox.scriptablemc.js.JavaScriptPluginEngineConfig import com.pixlfox.scriptablemc.utils.UnzipUtility -import fr.minuskube.inv.InventoryManager import org.bukkit.Material import org.graalvm.polyglot.* +import org.graalvm.polyglot.io.IOAccess import java.io.File @@ -39,13 +39,12 @@ class JavaScriptPluginEngine(override val bootstrapper: ScriptablePluginEngineBo .allowExperimentalOptions(true) .allowHostAccess(HostAccess.ALL) .allowHostClassLoading(true) - .allowIO(true) + .allowIO(IOAccess.ALL) .allowCreateThread(true) .option("js.ecmascript-version", "latest") .option("engine.WarnInterpreterOnly", "false") .option("log.file", "logs/script-engine.log") .option("js.esm-eval-returns-exports", "true") - .fileSystem(JavaScriptPluginFileSystem(this)) if(config.commonJsModulesEnabled) { if(config.debug) { diff --git a/ScriptableMC-Engine-JS/src/main/resources/config.yml b/ScriptableMC-Engine-JS/src/main/resources/config_js.yml similarity index 100% rename from ScriptableMC-Engine-JS/src/main/resources/config.yml rename to ScriptableMC-Engine-JS/src/main/resources/config_js.yml diff --git a/build.gradle.kts b/build.gradle.kts index 8704dc0e..ff4285ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,13 +1,14 @@ plugins { java - id("org.jetbrains.kotlin.jvm") version "1.7.21" apply false - id("com.github.johnrengelman.shadow") version "7.1.2" apply false - id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.6" apply false + id("org.jetbrains.kotlin.jvm") version "1.9.22" apply false +// id("com.github.johnrengelman.shadow") version "8.1.1" apply false + id("io.github.goooler.shadow") version "8.1.2" apply false + id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7" apply false } allprojects { group = project.findProperty("maven_group") ?: "com.pixlfox.scriptablemc" - version = project.findProperty("plugin_version") ?: "1.0.0-SNAPSHOT" + version = project.findProperty("plugin.version") ?: "2.0.0-SNAPSHOT" repositories { mavenCentral() @@ -54,16 +55,13 @@ tasks.register("shadowJarAll") { dependsOn(":ScriptableMC-Engine-JS:shadowJarEngine") doFirst { - if(!file("./build").exists()) file("./build").mkdirs() - if(file("./build/ScriptableMC-Engine-Core.jar").exists()) file("./build/ScriptableMC-Engine-Core.jar").delete() - if(file("./build/ScriptableMC-Engine-JS.jar").exists()) file("./build/ScriptableMC-Engine-JS.jar").delete() - if(file("./build/ScriptableMC-Engine-JS-Bundled.jar").exists()) file("./build/ScriptableMC-Engine-JS-Bundled.jar").delete() + if(!file("./build/libs").exists()) file("./build/libs").mkdirs() } doLast { - file("./ScriptableMC-Engine-Core/build/libs/ScriptableMC-Engine-Core.jar").copyTo(file("./build/ScriptableMC-Engine-Core.jar"), overwrite = true) - file("./ScriptableMC-Engine-JS/build/libs/ScriptableMC-Engine-JS.jar").copyTo(file("./build/ScriptableMC-Engine-JS.jar"), overwrite = true) - file("./ScriptableMC-Engine-JS/build/libs/ScriptableMC-Engine-JS-Bundled.jar").copyTo(file("./build/ScriptableMC-Engine-JS-Bundled.jar"), overwrite = true) + file("./ScriptableMC-Engine-Core/build/libs/ScriptableMC-Engine-Core.jar").copyTo(file("./build/libs/ScriptableMC-Engine-Core.jar"), overwrite = true) + file("./ScriptableMC-Engine-JS/build/libs/ScriptableMC-Engine-JS.jar").copyTo(file("./build/libs/ScriptableMC-Engine-JS.jar"), overwrite = true) + file("./ScriptableMC-Engine-JS/build/libs/ScriptableMC-Engine-JS-Bundled.jar").copyTo(file("./build/libs/ScriptableMC-Engine-JS-Bundled.jar"), overwrite = true) } } diff --git a/gradle.properties b/gradle.properties index 9ab7e427..31a429a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ kotlin.code.style=official maven.group=com.pixlfox -plugin.version=1.19.0 -dependencies.graalvm.version=22.3.0 -dependencies.spigotmc.version=1.19.3-R0.1-SNAPSHOT \ No newline at end of file +plugin.version=2.0.1-dev +dependencies.graalvm.version=23.0.2 +dependencies.spigotmc.version=1.20.4-R0.1-SNAPSHOT \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a25..d0d403e2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index c53aefaa..1b6c7873 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: #