Compare commits
6 Commits
master
...
03ddc4eee1
| Author | SHA1 | Date | |
|---|---|---|---|
| 03ddc4eee1 | |||
| d4ead15f4a | |||
| be643c3a49 | |||
| e90700264d | |||
| 3dddcd6665 | |||
| c431c21a8e |
@@ -0,0 +1,35 @@
|
|||||||
|
name: Build Plugin
|
||||||
|
run-name: Building Plugin 🚀
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'ver/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build with Maven
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Set up JDK 25 and enable Maven cache
|
||||||
|
uses: actions/setup-java@v5
|
||||||
|
with:
|
||||||
|
distribution: 'liberica'
|
||||||
|
java-version: '25'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
- name: Set up Maven
|
||||||
|
uses: stCarolas/setup-maven@v5
|
||||||
|
with:
|
||||||
|
maven-version: 3.9.16
|
||||||
|
|
||||||
|
- name: Build and package with Maven
|
||||||
|
run: mvn -B package
|
||||||
|
|
||||||
|
- name: Upload built artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: maven-artifacts
|
||||||
|
path: target/spigot/*.jar
|
||||||
@@ -6,17 +6,85 @@
|
|||||||
|
|
||||||
<groupId>xyz.fortern</groupId>
|
<groupId>xyz.fortern</groupId>
|
||||||
<artifactId>fortern-helper</artifactId>
|
<artifactId>fortern-helper</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.2</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>fortern-helper</name>
|
<name>fortern-helper</name>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spigotmc-repo</id>
|
||||||
|
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>placeholderapi</id>
|
||||||
|
<url>https://repo.helpch.at/releases/</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>codemc-repo</id>
|
||||||
|
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>25</java.version>
|
<java.version>25</java.version>
|
||||||
<kotlin.version>2.4.0</kotlin.version>
|
<kotlin.version>2.4.0</kotlin.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Spigot API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spigotmc</groupId>
|
||||||
|
<artifactId>spigot-api</artifactId>
|
||||||
|
<version>26.1-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Kotlin Stdlib https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-stdlib</artifactId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- JetBrains Java Annotations https://mvnrepository.com/artifact/org.jetbrains/annotations -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains</groupId>
|
||||||
|
<artifactId>annotations</artifactId>
|
||||||
|
<version>26.1.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Adventure API https://mvnrepository.com/artifact/net.kyori/adventure-api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.kyori</groupId>
|
||||||
|
<artifactId>adventure-api</artifactId>
|
||||||
|
<version>4.26.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Adventure Platform Bukkit https://mvnrepository.com/artifact/net.kyori/adventure-platform-bukkit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.kyori</groupId>
|
||||||
|
<artifactId>adventure-platform-bukkit</artifactId>
|
||||||
|
<version>4.4.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- PlaceholderAPI -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.clip</groupId>
|
||||||
|
<artifactId>placeholderapi</artifactId>
|
||||||
|
<version>2.12.2</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- NBT-API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.tr7zw</groupId>
|
||||||
|
<artifactId>item-nbt-api-plugin</artifactId>
|
||||||
|
<version>2.15.7</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<defaultGoal>clean package</defaultGoal>
|
<defaultGoal>clean package</defaultGoal>
|
||||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||||
@@ -50,6 +118,11 @@
|
|||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<finalName>${project.artifactId}-spigot-${project.version}</finalName>
|
||||||
|
<outputDirectory>${project.build.directory}/spigot</outputDirectory>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<resources>
|
<resources>
|
||||||
@@ -59,25 +132,4 @@
|
|||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>spigotmc-repo</id>
|
|
||||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot-api</artifactId>
|
|
||||||
<version>26.1-R0.1-SNAPSHOT</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,18 +1,39 @@
|
|||||||
package xyz.fortern.forternhelper
|
package xyz.fortern.forternhelper
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion
|
||||||
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import xyz.fortern.forternhelper.command.HelperCommand
|
||||||
import xyz.fortern.forternhelper.listener.ForternListener
|
import xyz.fortern.forternhelper.listener.ForternListener
|
||||||
|
import xyz.fortern.forternhelper.placeholder.ForternExpansion
|
||||||
|
|
||||||
class Helper : JavaPlugin() {
|
class Helper : JavaPlugin() {
|
||||||
|
private lateinit var adventure: BukkitAudiences
|
||||||
|
|
||||||
|
private lateinit var expansion: PlaceholderExpansion
|
||||||
|
|
||||||
override fun onEnable() {
|
override fun onEnable() {
|
||||||
// Plugin startup logic
|
// Plugin startup logic
|
||||||
|
this.adventure = BukkitAudiences.create(this)
|
||||||
logger.info("Registering listeners...")
|
logger.info("Registering listeners...")
|
||||||
|
// register listeners
|
||||||
Bukkit.getPluginManager().registerEvents(ForternListener(this), this)
|
Bukkit.getPluginManager().registerEvents(ForternListener(this), this)
|
||||||
|
logger.info("Registering commands...")
|
||||||
|
// register commands
|
||||||
|
Bukkit.getPluginCommand("helper")?.setExecutor(HelperCommand(this, adventure))
|
||||||
|
// register placeholders
|
||||||
|
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||||
|
expansion = ForternExpansion(this)
|
||||||
|
logger.info("Registering placeholders...")
|
||||||
|
expansion.register()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisable() {
|
override fun onDisable() {
|
||||||
// Plugin shutdown logic
|
// Plugin shutdown logic
|
||||||
|
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||||
|
expansion.unregister()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
package xyz.fortern.forternhelper.command
|
||||||
|
|
||||||
|
import de.tr7zw.nbtapi.NBT
|
||||||
|
import de.tr7zw.nbtapi.iface.ReadWriteNBT
|
||||||
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||||
|
import net.kyori.adventure.text.Component
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.command.TabExecutor
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileReader
|
||||||
|
|
||||||
|
class HelperCommand(
|
||||||
|
private val plugin: JavaPlugin,
|
||||||
|
private val adventure: BukkitAudiences,
|
||||||
|
|
||||||
|
) : TabExecutor {
|
||||||
|
private val subCommands: List<String> = listOf("loadlevel")
|
||||||
|
private val helpMessages = listOf(
|
||||||
|
Component.text("Minehunt v${plugin.description.version}", NamedTextColor.GREEN),
|
||||||
|
Component.text("/helper help ", NamedTextColor.GOLD)
|
||||||
|
.append(Component.text("帮助信息", NamedTextColor.WHITE)),
|
||||||
|
Component.text("/helper loadlevel <chunkPosX> <chunkPosZ> [world] ", NamedTextColor.GOLD)
|
||||||
|
.append(Component.text("查看区块的加载等级", NamedTextColor.WHITE)),
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<String>): Boolean {
|
||||||
|
// onCommand接受到的参数中没有空字符串
|
||||||
|
handlerCommand(sender, args.toList(), true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabComplete(sender: CommandSender, command: Command, label: String, args: Array<String>): List<String>? {
|
||||||
|
return handlerCommand(
|
||||||
|
sender,
|
||||||
|
args.filterIndexed { index, s -> s != "" || index == args.size - 1 },
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行命令或补全命令
|
||||||
|
*
|
||||||
|
* @param exe true 表示执行命令,false 表示补全命令
|
||||||
|
* @param args 命令的参数列表,除最后一条前面的每一条都应当是非空的
|
||||||
|
*/
|
||||||
|
private fun handlerCommand(sender: CommandSender, args: List<String>, exe: Boolean): List<String>? {
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
return if (exe) {
|
||||||
|
sendHelp(sender)
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
subCommands
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return when (args[0]) {
|
||||||
|
"help" -> {
|
||||||
|
onHelp(sender, exe)
|
||||||
|
}
|
||||||
|
|
||||||
|
"loadlevel" -> {
|
||||||
|
onLoadLevel(sender, args, exe)
|
||||||
|
}
|
||||||
|
|
||||||
|
"setblock" -> {
|
||||||
|
setBlockFromNbt(sender, args, exe)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
"getitem" -> {
|
||||||
|
getItemFromNbt(sender, args, exe)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
if (exe) {
|
||||||
|
adventure.sender(sender).sendMessage(Component.text("错误的子命令"))
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
// 补全已args[0]开头的子命令
|
||||||
|
if (args.size == 1) subCommands.filter { it.startsWith(args[0]) } else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getItemFromNbt(sender: CommandSender, args: List<String>, exe: Boolean) {
|
||||||
|
// args[0]:getitem | args[1]:0 | args[2]:txt
|
||||||
|
if (!exe) return
|
||||||
|
if (sender !is Player) return
|
||||||
|
if (!sender.isOp) return
|
||||||
|
if (args.size < 2) return
|
||||||
|
val i = args[1]
|
||||||
|
val isNbt = if (args.size > 2) args[2] == "nbt" else false
|
||||||
|
val itemNbtDir = File(plugin.dataFolder, "item-nbt")
|
||||||
|
val nbt = if (isNbt) {
|
||||||
|
val file = File(itemNbtDir, "${i}.nbt")
|
||||||
|
if (!file.exists()) return
|
||||||
|
NBT.readFile(file)
|
||||||
|
} else {
|
||||||
|
val file = File(itemNbtDir, "${i}.txt")
|
||||||
|
if (!file.exists()) return
|
||||||
|
NBT.parseNBT(FileReader(file).readAllAsString())
|
||||||
|
}
|
||||||
|
sender.inventory.addItem(NBT.itemStackFromNBT(nbt))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setBlockFromNbt(sender: CommandSender, args: List<String>, exe: Boolean) {
|
||||||
|
// args[0]:setblock | args[1]:0 | args[2]:txt
|
||||||
|
if (!exe) return
|
||||||
|
if (sender !is Player) return
|
||||||
|
if (!sender.isOp) return
|
||||||
|
if (args.size < 2) return
|
||||||
|
val i = args[1]
|
||||||
|
val isNbt = if (args.size > 2) args[2] == "nbt" else false
|
||||||
|
val world = sender.world
|
||||||
|
val blockState = world.getBlockState(0, 128, 0)
|
||||||
|
val itemNbtDir = File(plugin.dataFolder, "block-nbt")
|
||||||
|
val readWriteNBT = if (isNbt) {
|
||||||
|
val file = File(itemNbtDir, "${i}.nbt")
|
||||||
|
if (!file.exists()) return
|
||||||
|
NBT.readFile(file)
|
||||||
|
} else {
|
||||||
|
val file = File(itemNbtDir, "${i}.txt")
|
||||||
|
if (!file.exists()) return
|
||||||
|
NBT.parseNBT(FileReader(file).readAllAsString())
|
||||||
|
}
|
||||||
|
NBT.modify(blockState) { nbt: ReadWriteNBT ->
|
||||||
|
nbt.mergeCompound(readWriteNBT)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onHelp(sender: CommandSender, exe: Boolean): List<String>? {
|
||||||
|
if (exe) sendHelp(sender)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onLoadLevel(sender: CommandSender, args: List<String>, exe: Boolean): List<String>? {
|
||||||
|
// args[0]: loadlevel args[1]:15 args[2]:15 args[3]:world_the_end
|
||||||
|
if (args.size < 2) {
|
||||||
|
if (exe) {
|
||||||
|
adventure.sender(sender).sendMessage(Component.text("指定正确的区块坐标", NamedTextColor.RED))
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
var x = 0
|
||||||
|
var z = 0
|
||||||
|
if (exe) {
|
||||||
|
try {
|
||||||
|
x = args[1].toInt()
|
||||||
|
z = args[2].toInt()
|
||||||
|
} catch (_: NumberFormatException) {
|
||||||
|
adventure.sender(sender).sendMessage(Component.text("指定正确的区块坐标", NamedTextColor.RED))
|
||||||
|
}
|
||||||
|
val worldInArg = if (args.size == 4 && args[3].isNotBlank()) {
|
||||||
|
Bukkit.getWorld(args[3])
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
val world = worldInArg ?: if (sender !is Player) {
|
||||||
|
adventure.sender(sender).sendMessage(Component.text("世界名称不正确", NamedTextColor.RED))
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
sender.world
|
||||||
|
}
|
||||||
|
val chunk = world.getChunkAt(x, z)
|
||||||
|
val loadLevel = chunk.loadLevel
|
||||||
|
adventure.sender(sender).sendMessage(Component.text("ChunkPos(${args[1]}, ${args[2]}) loadLevel: $loadLevel"))
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
if (args.size == 4) {
|
||||||
|
val worldName = args[3]
|
||||||
|
return Bukkit.getWorlds().filter { it.name.startsWith(worldName) }.map { it.name }
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendHelp(sender: CommandSender) {
|
||||||
|
helpMessages.forEach { adventure.sender(sender).sendMessage(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,10 @@ import org.bukkit.entity.Villager
|
|||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.Listener
|
import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.player.PlayerInteractEntityEvent
|
import org.bukkit.event.player.PlayerInteractEntityEvent
|
||||||
import xyz.fortern.forternhelper.Helper
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
import xyz.fortern.forternhelper.reflection.NMSAdapter
|
import xyz.fortern.forternhelper.reflection.NMSAdapter
|
||||||
|
|
||||||
class ForternListener(val helper: Helper) : Listener {
|
class ForternListener(val plugin: JavaPlugin) : Listener {
|
||||||
@EventHandler
|
@EventHandler
|
||||||
fun onTrade(event: PlayerInteractEntityEvent) {
|
fun onTrade(event: PlayerInteractEntityEvent) {
|
||||||
val entity = event.rightClicked
|
val entity = event.rightClicked
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package xyz.fortern.forternhelper.placeholder
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.OfflinePlayer
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
|
||||||
|
|
||||||
|
class ForternExpansion(
|
||||||
|
val plugin: JavaPlugin
|
||||||
|
) : PlaceholderExpansion() {
|
||||||
|
override fun getIdentifier(): String {
|
||||||
|
return "fortern"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAuthor(): String {
|
||||||
|
return plugin.description.authors.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getVersion(): String {
|
||||||
|
return plugin.description.version
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun persist(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequest(player: OfflinePlayer, params: String): String {
|
||||||
|
return if (params.startsWith("loadlevel_")) {
|
||||||
|
// e.g. peace_the_nether_x,z
|
||||||
|
val first = params.indexOf('_')
|
||||||
|
if (first < 0) return "unknown"
|
||||||
|
val last = params.lastIndexOf('_')
|
||||||
|
if (last <= first) return "unknown"
|
||||||
|
val chunkPos = params.substring(last + 1)
|
||||||
|
val split = chunkPos.split(',')
|
||||||
|
if (split.size < 2) return "unknown"
|
||||||
|
val chunkX = split[0]
|
||||||
|
val chunkZ = split[1]
|
||||||
|
val worldName = params.substring(first + 1, last)
|
||||||
|
val world = Bukkit.getWorld(worldName) ?: return "unknown"
|
||||||
|
try {
|
||||||
|
val x = Integer.parseInt(chunkX)
|
||||||
|
val z = Integer.parseInt(chunkZ)
|
||||||
|
world.getChunkAt(x, z).loadLevel.toString()
|
||||||
|
} catch (_: NumberFormatException) {
|
||||||
|
"unknown"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,11 +3,21 @@ version: '${version}'
|
|||||||
authors: [ Fortern ]
|
authors: [ Fortern ]
|
||||||
api-version: '26.1'
|
api-version: '26.1'
|
||||||
main: xyz.fortern.forternhelper.Helper
|
main: xyz.fortern.forternhelper.Helper
|
||||||
|
softdepend:
|
||||||
|
- PlaceholderAPI
|
||||||
|
depend:
|
||||||
|
- NBTAPI
|
||||||
|
|
||||||
libraries:
|
libraries:
|
||||||
- org.jetbrains.kotlin:kotlin-stdlib:2.3.21
|
- org.jetbrains.kotlin:kotlin-stdlib:2.3.21
|
||||||
|
- net.kyori:adventure-api:4.26.1
|
||||||
|
- net.kyori:adventure-platform-bukkit:4.4.1
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
helper:
|
helper:
|
||||||
description: "游戏主命令"
|
description: "游戏主命令"
|
||||||
permission: op
|
permission: fortern.helper
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
fortern.helper:
|
||||||
|
default: op
|
||||||
|
|||||||
Reference in New Issue
Block a user