• 欢迎来到Minecraft插件百科!
  • 对百科编辑一脸懵逼?帮助:快速入门带您快速熟悉百科编辑!
  • 因近日遭受攻击,百科现已限制编辑,有意编辑请加入插件百科企鹅群:223812289

LuckPerms:修订间差异

来自Minecraft插件百科
跳转到导航 跳转到搜索
无编辑摘要
(有待进一步简化)
 
(未显示5个用户的41个中间版本)
第1行: 第1行:
欢迎来到 LuckPerms wiki。这里你将会找到本插件的完整的使用文档,包括了安装、设置、配置和如何高效的使用 LuckPerms。
{{急需改进|页面冗长,需要拆分子页面}}
{{Plugin Infobox
|外文名    = LuckPerms
|图片      = [[File:LuckPerm banner.png]]
|作者      = Luck
|插件类型  = Spigot / CraftBukkit / Sponge
|最新版本  = 4.0.18(Bukkit) / 4.0.60(Sponge)
|兼容服务端 = 1.7, 1.8, 1.9, 1.10, 1.11, 1.12,1.13,1.14,1.15,1.16,1.17,1.18,1.19,1.20
|前置插件  =
|源地址    = [https://www.spigotmc.org/resources/luckperms-an-advanced-permissions-plugin.28140/ SpigotMC]<br>[https://ore.spongepowered.org/Luck/LuckPerms SpongePowered]
}}


'''从何开始?'''
'''LuckPerms'''是Minecraft服务端(Bukkit / Spigot,BungeeCord等)的权限插件。它允许服务器管理员通过创建组和分配权限来控制玩家可以使用的功能,由Luck开发。


如果您从未使用过任意权限插件,我推荐你从头开始看。
==为什么选择LuckPerms?==
LuckPerm是一款先进、高等的权限插件,仅仅以'''快速'''、'''稳定可靠'''、'''灵活多变'''的特点,


基础都在[[https://github.com/PluginsCDTribe/LuckPerms/wiki/Usage 使用教程]]页面。
便可以替代现有的许多权限插件,例如PermissionsEX、GroupManagerX、z/bPermissions、BungeePerms等主流权限插件。


完整的命令使用在[[https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage 命令使用]]页面。
LuckPerms这个插件的计划,本来是围绕着两个主要特点来制作的:高性能、强大且广泛的功能,


'''什么也没找到?'''
填补其他同类插件的功能缺陷、并且建立在同类现有功能上更进一步的优化功能。


如果你有更多的问题是这篇Wiki没有解决的,你可以通过以下几种方式联系我。
LuckPerms还包括了非常广泛的API支持,这是为开发人员的添加的,


* [[https://discord.gg/W3FzxHA Discord 服务器]] (就算我不在,也有很多人帮助你!)
并且,luckperms还兼容各式各类Minecraft服务器软件&支持多种数据存储的选择。
* 在 irc.esper.net 我是 "Luck",我也在 irc.spi.gt 和 chat.freenode.net
 
* 在 SpigotMC 和 Sponge 论坛我是 "Luck"
'''来吧兄弟,告诉我,我为什么要使用LuckPerm?'''
* 在[[https://github.com/lucko/LuckPerms/issues GitHub]]提交一个 issue (如果你要提交一个BUG,这是最好的方式)
 
LuckPerm能做很多事情,至少单在技术层面,LuckPerm就胜过大部分同类插件。
 
我认为这不取决于我制作插件的水平,而是取决于我在LuckPerm上面花费的精力与时间。
 
LuckPerm是我在2016年开始准备编写的插件,但因为Bukkit变得流行起来,许多同一时期的插件都变成了老牌稳定插件,
 
不过,这也为我编写LuckPerm提供的很好的参考帮助,因为我可以避免其它同类插件的缺陷,
 
并且明白它们哪些地方做的特别出色,我可以在其基础之上进一步优化,使那部分功能变得更加引人瞩目。
 
记着,如果你对LuckPerm技术性方面的内容感兴趣,我推荐你从[[https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage 命令使用]]部分开始阅读
 
或者看看wiki列出的其他部分内容,在本节的其余部分,我会将阅读重点放到LuckPerm一些全新的特色功能上面。
 
这些内容是你不太可能从其他插件中找到的,专属luckPerm的特色功能!
 
'''Verbose(权限查看系统)'''
Verbose是Luckperms一套完整的权限查看系统。
 
他可以实时监视并检测其他插件所需的权限
 
你也可以把录像上传到网上,方便查看、分析和阅读:
 
[[https://git.io/vQitM https://git.io/vQitM]]
 
'''权限树系统'''
 
LuckPerm允许你在服务器所有已知权限上建立编写"权限树"
 
权限树上的数据是由你所有的插件在服务器注册的权限构成的。
 
随着你服务器运营时间的增长,因为服务器添加了许多插件,它们都会注册权限,这些数据都会被纳入权限树中。
 
这是个清真的例子 [[https://git.io/vQiti https://git.io/vQiti]]。
你看到的权限树的颜色,代表了你的玩家是否拥有对应的权限,这一机制很方便的让你查阅到服务器的相应权限。
 
这还是那个清真的例子 [[https://git.io/vQitihttps://git.io/vQiti]]
 
'''指令界面&TAB补全'''
 
LuckPerm的指令系统被我设计的尽可能便捷、易用、人性化,
 
这样一来,你除了查阅LuckPerm的[[https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage 大量相关帮助文档]],还可以在游戏中查看指令用法、以及指令列表。
 
[[文件:Luck-1.png]]
 
LuckPerm的所有指令皆可使用TAB补全功能,这就意味着,你可以通过输入更少的指令来完成你的工作!
 
这是不是在一定程度极大地提高了你的工作效率呢?就像下面那样:
 
[[文件:AnnualYoungKoi-size restricted.gif]]
 
'''网站编辑器'''
 
除了使用指令来编辑服务器权限相关,LuckPerm还提供了更加便捷的编辑方式,
 
你可以使用Web网站编辑器来对服务器的权限数据进行快速更改,
 
任何人都能够使用网站编辑器,不论你使用了哪种存储方式!
 
网站编辑功能非常容易使用,且易于上手
 
【图片过大 请去wiki页面查看】
 
'''行为记录仪'''
 
为了防止服务器中出现心存不轨的管理员,想要私自给自己添加权限,
 
LuckPerm详细的记录了服务器各类权限的微小变化,
 
你可以通过行为记录仪来搜索每个人的详细操作。
 
[[文件:Luck-2.png]]


'''一些有用的链接'''
你也可以查看所有东西的详细历史。
* [[https://ci.lucko.me/job/LuckPerms 开发构建]]
* [[https://luckperms.lucko.me/javadocs/ Javadocs]]


==安装==
==安装==
===安装===
'''初始设置'''
1. 下载适合你平台的 `LuckPerms-???-x.x.x.jar` 文件。你可以点[https://ci.lucko.me/job/LuckPerms/ 这里]查看最新的版本。
2. 打开你的 Mod 或插件所在路径,这路径通常要么是 `/server/plugins/` ,要么是 `/server/mods/`。
然后把 LuckPerms 的 jar 文件放入文件夹中。
3. 请完全关闭你的服务器,然后再打开,这会生成默认配置。
4. 完全关闭你的服务器,打开配置文件。配置文件的位置在 `/plugins/LuckPerms/config.yml` 或 `/config/luckperms/luckperms.conf`。
5. 请浏览配置文件,然后根据你的服务器修改设置,尤其是请注意存储相关设置。
6. 再次开启你的服务器。
你可以更改配置文件中的很多内容,文件有很细节化的注释,每个设置的作用注释中都解释的很清楚。
'''需求'''
LuckPerms 插件只有一个环境需求。
* '''Java 8'''
没错,唯一需求就是你必须使用 Java 8,LuckPerms 插件在旧版本的Java上不会工作。
到目前为止很多服务器提供商都已经升级到Java 8了,但是如果你的服务器提供商没有升级的话,请温和地和他们谈谈,让他们去升级。
如果你是自己租主机开服的话,你应该对你还没有升级Java感到羞愧!
升级的过程是很简单的,如果你想升级的话网上也有大量的教程。
使用过期的软件肯定不是好的:)
'''Bukkit版本过旧'''
如果你收到了类似于 "NoSuchMethod" 或 "ClassNotFound" 这类错误的话,十有八九就是你在使用较旧的Bukkit版本。
在将它作为错误报告给我之前,请尝试使用"Development Builds"(构建版本)下载页面的"Bukkit-Legacy"(Bukkit-旧版)版本。
'''切换存储类型'''
LuckPerms 插件所使用的默认数据存储类型是 '''H2 数据库'''。
所有的数据都会储存在LuckPerms插件目录下的 `luckperms.db.mv.db` 文件之中。
(插件目录为 `/plugins/LuckPerms/` 或 `/luckperms/`)
这个数据格式普通的文本编辑器是**不能读取**的。
如果你想要手动阅读/编辑LuckPerms插件的数据的话,你就需要切换到**YAML或JSON**存储格式,更改 `config.yml` 文件中的配置选项就好了。
更多相关于存储类型的有关信息请阅读[[https://github.com/PluginsCDTribe/LuckPerms/wiki/Choosing-a-Storage-type 下一节]]
===选择存储类型===
LuckPerms 插件带有很多存储数据的方式,你可以从中选择。
存储类型选项可以在 `config.yml` 或 `luckperms.conf` 文件中修改。
<pre>
# Which storage method the plugin should use.
# Currently supported: mysql, postgresql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
storage-method: h2
</pre>
请记住如果你想改变存储类型的话,你的数据不会自动转移到新的存储库中。
要想手动在数据存储方式间转移数据的话,请查看[https://github.com/PluginsCDTribe/LuckPerms/wiki/Switching-storage-types 这里]来获得更多信息。
可用的选项都列在了下面。
 
'''H2 / SQLite'''
默认的存储类型是 '''H2'''。
这两种文件类型都是以SQL数据库为基础的。
所有的数据都会存储在LuckPerms插件目录下的一个文件之中。
和YAML和JSON方式的不同之处在于,这个文件不能用文本编辑器打开。
你必须使用插件提供的命令才能编辑或查看数据。
如果你选择使用 H2 数据库的话(默认设置),所有的数据都会储存在 `luckperms-h2.mv.db` 文件中。
SQLite 类型所提供的存储文件是 `luckperms-sqlite.db`。
要想使用这两种类型中的一种,请将配置设置为:
<pre>
storage-method: h2
# or
storage-method: sqlite
</pre>
'''JSON / YAML'''
JSON 和 YAML 存储类型会将数据存储在可读可编辑的文本文件中。YAML 类型所提供的文件扩展名为 `.yml` ,JSON类型所提供的文件扩展名为 `.json`。
这两种类型的存储格式很相似,只是在一些句法上不同。
'''''示例 YAML 文件'''''
<pre>
uuid: c1d60c50-70b5-4722-8057-87767557e50d
name: Luck
primary-group: default
permissions:
- group.default:
    value: true
- test.permission:
    value: true
    server: factions
- other.test.permission:
    value: false
</pre>
'''''示例 JSON 文件'''''
<pre>
{
  "uuid": "c1d60c50-70b5-4722-8057-87767557e50d",
  "name": "Luck",
  "primaryGroup": "default",
  "permissions": [
    {
      "group.default": {
        "value": true
      }
    },
    {
      "test.permission": {
        "value": true,
        "server": "factions"
      }
    },
    {
      "other.test.permission": {
        "value": false,
        "server": "test"
      }
    }
  ]
}
</pre>
要想使用这两种类型中的一种,请将配置设置为:
<pre>
storage-method: yaml
# or
storage-method: json
</pre>
'''MySQL / PostgreSQL'''
储存在 MySQL 类型和 PostgreSQL 类型中的数据格式上与上文提及的 H2/SQLite 类型相同,但是数据是储存在远程服务器上的。
这意味着你可以跨服分享相同的数据。
你需要在配置文件中输入你数据库服务器的地址,端口,数据库名,用户名和密码。
这种类型推荐要存储大量数据的用户,或是想要搭建群组服务器的用户所使用。
如果你已经在运行群组服务器,并且想要在子服务器之间同步数据的话,你就必须选择这种类型了。
格式布局示例在[https://github.com/PluginsCDTribe/LuckPerms/tree/master/common/src/main/resources 这里]。
要想使用这两种选项中的一种,请将配置设置为:
<pre>
storage-method: mysql
# or
storage-method: postgresql
</pre>
'''MongoDB'''
LuckPerms 也支持 MongoDB 类型的存储,它也是一种远程数据库,在有些方面上和 MySQL 相似。
这种类型也只会被一小部分的用户所使用。
要想使用这种类型的存储,请将配置设置为:
<pre>
storage-method: mongodb
</pre>
===使用教程===
这篇教程是为之前从来没有使用过权限管理插件的人所准备的。
如果你已经很熟悉权限管理等相关概念了的话,我认为你应该就能够理解命令中的东西了。
这样我就推荐你去阅读[https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage 命令和权限]页面,这样更加“直奔主题”,你也能够更容易理解插件的工作方法。
如果你正在努力想弄明白权限管理相关概念的话,这篇教程就是你起步的最佳地方:)
====关键术语====
'''权限'''
在你的服务器上会有大量的**特性,命令和一些新功能**。
这其中的一些特性是服务器自带的,另一些是由“插件”所添加的。
与这些特性相联系的大多数行为都是由权限所控制的,因此你可以控制哪些用户可以使用你指定的特性或权限。
**权限仅仅是个字符串**,并且使用英文的句号(半角 → . ←)分成几部分。
举个例子, “minecraft.command.ban” 就是原版 /ban 命令所使用的权限。
显然我们不想让所有用户都能执行这个命令,所以我们只给我们信任的玩家这个权限。
代表特定行为的使用许可的字符串,我们就称之为权限,它又名“权限节点”,简称“权限”。
'''权限组'''
代替单独为每个用户设置权限,我们可以将**权限捆绑为一组**,然后直接将这一组**给予玩家**。
举个例子,在我设置的“admin”权限组中,我可能会添加使用ban和unban指令的权限,然后将玩家加入admin权限组中。
这意味着他们能够获得“admin”权限组所设置的所有权限和他们自身被设置的权限。
'''继承'''
用户和权限组能够**互相继承权限**。
举个例子,默认地,所有的用户都会从“default”权限组继承权限。
你可以为你自己的服务器设置你自己的权限组与继承方式,或是制作你自己独特的系统。
举个例子,我设置了三个权限组, “default”, “moderator” 和 “admin”。
我想让“moderator”权限组从“default”权限组继承所有权限,“admin”权限组从“moderator”权限组继承所有权限。
====起步====
如果你还没有将LuckPerms插件安装在你的服务器上的话,我们推荐你先阅读[https://github.com/PluginsCDTribe/LuckPerms/wiki/Setup 安装]有关的教程。
然后,请确保你在继续之前已经阅读了[https://github.com/PluginsCDTribe/LuckPerms/wiki/Choosing-a-Storage-type 选择数据存储类型]的有关章节。
虽然你在后期也能实现数据之间的转移,但第一次就将他们弄对位置是更好的。
'''给予修改权限的全部权限'''
你想做的第一件事情就是给你本插件的所有权限。
当本插件首次安装后,没有人能够使用LuckPerms插件的有关命令。
要想做到这个的话,你需要在服务器控制台输入 `/luckperms user Luck permission set luckperms.* true` 。
当然,请把我的名字换成你自己的(不用担心,这条命令的使用方法之后会详细讲解)
这应该就是运行的结果:
[[文件:LPUsage1.png]]
实际上,这条命令起的效果,就是给了 `Luck` 用户 `luckperms.*` 权限。(或者说,为用户设置权限为 true)
你可能已经注意到了我们刚才在权限字符串的末端使用的 `*` 字符了。
这个字符叫做通配符,它会给玩家**所有**以 "luckperms" 为开头的权限。
'''创建第一个权限组'''
我们可以使用创建权限组命令来创建一个新的权限组。
让我们创建一个叫做“admin”的权限组,然后给它附加一条权限吧。
首先,运行 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-creategroup `/luckperms creategroup admin`] 命令。
这会创建一个叫做“admin”的空权限组。
[[文件:LPUsage2.png]]
接下来,我们想为“admin”权限组增加一条权限。
用来修改权限组的命令是 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#group---lp-group-group- `/luckperms group <group>`]。
如果你执行这条命令的话,它会为你显示所有可用的子命令。
[[文件:LPUsage3.png]]
你可能注意到了第一个子命令是“info”命令。它只会列举出一些权限组相关的信息。
我们可以运行 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-group-group-info `/luckperms group admin info`] 来查看新建立的“admin”权限组的一些信息。
[[文件:LPUsage4.png]]
接下来就是“permission”命令。这能够帮助你修改权限组的权限。
再一次,使用 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#permission---lp-user-user-permission---lp-group-group-permission- `/luckperms group admin permission`] 命令会列出所有可用的子命令。
[[文件:LPUsage5.png]]
再一次,我们看到了更多我们可以执行的命令。
第一个就是另一个 "info" 子命令。
因为它是“permission”子命令下的又一子命令,它就会显示某一权限组所拥有的所有权限。
下面的命令是“set”子命令。
你还记得吗,之前我们使用相似的指令来给玩家 "luckperms.*" 权限。这里它也相同
只需要不加参数运行该命令就可以返回该命令的使用方法。举个例子:
[[文件:LPUsage6.png]]
举个例子,我想给我的“admin”用户组 "minecraft.command.ban" 权限。
因此我可以输入 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-usergroup-usergroup-permission-set `/luckperms group admin permission set minecraft.command.ban true`] 。
[[文件:LPUsage7.png]]
这条命令就会给予 `admin` 用户组 `minecraft.command.ban permission` 权限。
末端的true控制我们设置的权限的启用与否。
你可以将权限的启用与否设置为 `true` 或 `false` 。
为用户或权限组将权限设置为 true 能够让他们拥有该权限,设置为 false 即该权限无效。(指定他们没有该权限)
如果晚些时候我决定不再让“admin”用户组拥有这个权限了,我可以使用 unset 命令来移除该权限的设定。
输入 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-usergroup-usergroup-permission-unset `/luckperms group admin permission unset minecraft.command.ban`] 。
[[文件:LPUsage8.png]]
'''将玩家加入到权限组中'''
将用户加入到权限组中需要使用 "parent" 命令。(在我们的命令使用页我们经常用“permission”替换“parent”)
举个例子,把我自己加入“admin”权限组中,我需要使用 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-usergroup-usergroup-parent-add `/luckperms user Luck parent add admin`] 。
[[文件:LPUsage9.png]]
这条命令会将用户 `Luck` 加入到 `admin` 权限组中。
这意味着任何“admin”权限组所拥有的权限我现在也继承下来了。
'''让一个权限组继承另一个权限组'''
就像用户能够继承一样,权限组也能够继承另一个权限组。
举个例子,想想下面这种情况的设置方法。(有些权限仅仅是为了演示而编造出来的)
{| class="wikitable"
|-
! Admin !! Mod !! Default
|-
|-------|-----|---------
|-
| minecraft.command.ban || minecraft.command.mute || minecraft.command.say
|-
| minecraft.command.pardon || minecraft.command.unmute|| minecraft.command.me
|-
| some.cool.admin.perm || some.cool.mod.perm || 
|-
| someplugin.vanish || chatcolor.bold | |
|}
我想让“admin”权限组中的用户拥有“mod”和“default”权限组的权限,同时“mod”权限组中的用户拥有“default”权限组中的权限。要想实现这个的话,我可以设置用户组之间的相互继承。
[https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-usergroup-usergroup-parent-add `/luckperms group admin parent add mod`] 命令会让“admin”权限组继承所有“mod”权限组中的权限。
然后要想让“mod”继承“default”,同样的道理,我可以输入 `/luckperms group mod parent add default`。
[[文件:LPUsage10.png]]
继承是可递归的,所以这样以后“admin”权限组就不仅仅继承了“mod”权限组,还继承了“default”权限组。
这意味着“admin”权限组中的玩家拥有“mod”**和**“default”两权限组中的权限了。
在“admin”组的一位用户因此拥有 `minecraft.command.ban`,`minecraft.command.mute` *和* `minecraft.command.say` 权限。
'''移除继承权限组'''
要想移除权限组间的继承关系只需要输入一个类似的命令就好了。
要想让我自己不再继承“admin”权限组,我只要输入 [https://github.com/PluginsCDTribe/LuckPerms/wiki/Command-Usage#lp-usergroup-usergroup-parent-remove `/luckperms user Luck parent remove admin`] 就好了。
[[文件:LPUsage11.png]]
==配置==
请见子页面:[[LuckPerms/配置]]
==特性==
请见子页面:[[Luckperms/特性]]
== 开发者 ==
=== 开发者 API ===
==== 简介 ====
LuckPerms API 允许你更改大量的插件内部编程,并且能够轻松地将 LuckPerms 深度集成到你的插件和系统里。
大多数的其他的权限要么没有 API,要么有很差的 API,或者是有很差的文档的 API,而且里面的方法和类可能随机在不同版本里消失或是移动。Vault 项目就是一个很好的接口,并且是将大量插件一次性集成的很好的方法,可惜他的功能实在是太少了。
LuckPerms 遵循 Semantic 版本控制,也就是意味着一个不向后兼容的新的 API 出现时,主版本会增加这个 API,你可以放心你的集成不会因为版本的不同而崩溃,主要的版本是保持不变的。
==== 如何在项目里使用 API ====
LuckPerms 的 API 包是 [https://github.com/lucko/LuckPerms/tree/master/api/src/main/java/me/lucko/luckperms <code>me.lucko.luckperms.api</code>]
我的 Nexus 服务器可以在这里找到 https://nexus.lucko.me/,你在你的构建脚本里需要的仓库在 https://repo.lucko.me/
==== 其他有用的链接 ====
* [https://luckperms.lucko.me/javadocs/ JavaDocs]
* [https://ci.lucko.me/job/LuckPerms/ CI Server]
==== Maven ====
<source lang="xml"><repositories>
    <repository>
        <id>luck-repo</id>
        <url>https://repo.lucko.me/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>me.lucko.luckperms</groupId>
        <artifactId>luckperms-api</artifactId>
        <version>3.2</version>
        <scope>provided</scope>
    </dependency>
</dependencies></source>
==== Gradle ====
<pre class="gradle">repositories {
    maven {
        name &quot;luck-repo&quot;
        url &quot;https://repo.lucko.me/&quot;
    }
}
dependencies {
    compile (&quot;me.lucko.luckperms:luckperms-api:3.2&quot;)
}</pre>
==== 使用指南 ====
使用 API,你需要获得 LuckPermsApi 接口的实例,这可以通过几个方法完成。
<source lang="java">// 所有平台 (抛出 IllegalStateException 如果 API 没有被加载)
final LuckPermsApi api = LuckPerms.getApi();
// 或者可选的
Optional<LuckPermsApi> provider = LuckPerms.getApiSafe();
if (provider.isPresent()) {
    final LuckPermsApi api = provider.get();
}
// Bukkit/Spigot
ServicesManager manager = Bukkit.getServicesManager();
if (manager.isProvidedFor(LuckPermsApi.class)) {
    final LuckPermsApi api = manager.getRegistration(LuckPermsApi.class).getProvider();
}
// Sponge
Optional<LuckPermsApi> provider = Sponge.getServiceManager().provide(LuckPermsApi.class);
if (provider.isPresent()) {
    final LuckPermsApi api = provider.get();
}</source>
===== 线程安全的警告 =====
所有 LuckPerms 内部,包括 API 都是线程安全的,你可以在异步线程任意调用 API 而不用担心发生错误。
但是,请注意一些操作,(尤其是存储类)是阻塞的。[https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html CompletableFuture] 就是用于这种情况:防止由于较差的处理导致的增加的错误,当出现 IO 时主线程等待处理完成。注意在添加 Callback 时指定正确的处理器。
===== 我想将 LuckPerms 作为依赖项 =====
在 Bukkit/Bungee,你需要在你的 plugin.yml 添加以下信息
<pre class="yml">depend: [LuckPerms]</pre>
在 Sponge, 在你的插件声明添加这些。
<source lang="java">@Plugin(
        id = "myplugin",
        dependencies = {
                @Dependency(id = "luckperms")
        }
)
public class MyPlugin {
    ...
}</source>
===== 事件 =====
LuckPerms 有一个完整的读写API,也有一个事件监听系统。由于插件的多平台的原因,我们使用了内部的事件系统,而不是每个平台已经使用的事件系统(举个例子,Bukkit Event API)。这意味着简单的注册你的平台的监听器将不会生效。
所有的事件都是'''异步触发'''的。这意味着不应该在监听器里交互或者调用任何不是线程安全的方法。
值得注意的是,大多数的 Bukkit/Sponge 都不是线程安全的,并且只应该使用主服务器线程来交互。你应该使用调度器来访问 LuckPerms 的监听器。
===== 我怎样才能监听一个事件 =====
所有的事件接口都可以在 [https://github.com/lucko/LuckPerms/tree/master/api/src/main/java/me/lucko/luckperms/api/event me.lucko.luckperms.api.event] 包里找到,它们都继承了 [https://github.com/lucko/LuckPerms/blob/master/api/src/main/java/me/lucko/luckperms/api/event/LuckPermsEvent.java LuckPermsEvent] 类。
监听事件应该获得 [https://github.com/lucko/LuckPerms/blob/master/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java EventBus] 实例,使用 [https://github.com/lucko/LuckPerms/blob/master/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java#L68 LuckPermsApi#getEventBus]即可。
为你的监听器创建另一个类常常是个好想法,这是一个你可以用来参考的类。
<source lang="java">package me.lucko.test;
import me.lucko.luckperms.api.event.EventBus;
import me.lucko.luckperms.api.event.log.LogPublishEvent;
import me.lucko.luckperms.api.event.user.UserLoadEvent;
import me.lucko.luckperms.api.event.user.track.UserPromoteEvent;
public class TestListener {
    private final MyPlugin plugin;
    public TestListener(MyPlugin plugin, LuckPermsApi api) {
        this.plugin = plugin;
        EventBus eventBus = api.getEventBus();
        // use a lambda
        eventBus.subscribe(LogPublishEvent.class, e -> e.getCancellationState().set(true));
        eventBus.subscribe(UserLoadEvent.class, e -> {
            System.out.println("User " + e.getUser().getName() + " was loaded!");
            if (e.getUser().hasPermission("some.perm", true)) {
                // Do something
            }
        });
        // use a method reference
        eventBus.subscribe(UserPromoteEvent.class, this::onUserPromote);
    }
    private void onUserPromote(UserPromoteEvent event) {
        Bukkit.getScheduler().runTask(plugin, () -> {
            Bukkit.broadcastMessage(event.getUser().getName() + " was promoted to" + event.getGroupTo().get() + "!");
            Player player = Bukkit.getPlayer(event.getUser().getUuid());
            if (player != null) {
                player.sendMessage("Congrats!");
            }
        });
    }
}</source>
[https://github.com/lucko/LuckPerms/blob/master/api/src/main/java/me/lucko/luckperms/api/event/EventBus.java#L43 EventBus#subscribe] 返回一个 [https://github.com/lucko/LuckPerms/blob/master/api/src/main/java/me/lucko/luckperms/api/event/EventHandler.java EventHander] 实例,可以用来在插件停止的时候取消注册监听器。
==== 示例用法 ====
下面就是一些简短的实例,使用了一些基本的 API 功能。
===== 获得玩家的组 =====
如果你只是想找到一个玩家的组,我非常建议你使用以下的方法(你甚至不需要使用 API)。
<source lang="java">public static String getPlayerGroup(Player player, List<String> possibleGroups) {
    for (String group : possibleGroups) {
        if (player.hasPermission("group." + group)) {
            return group;
        }
    }
    return null;
}</source>
记住将你的组排列为优先级的顺序(比如组长在前,成员在后)。
===== 为一个玩家添加权限 =====
<source lang="java">LuckPermsApi api = null; // See above for how to get the API instance.
Optional<User> user = api.getUserSafe(uuid);
if (!user.isPresent()) {
    return false; // The user isn't loaded in memory.
}
// Build the permission node we want to set
Node node = api.getNodeFactory().newBuilder(permission).setValue(true).build();
// Set the permission, and return true if the user didn't already have it set.
try {
    user.get().setPermission(node);
    // Now we need to save the user back to the storage
    api.getStorage().saveUser(u);
    return true;
} catch (ObjectAlreadyHasException e) {
    return false;
}</source>
===== 为(可能的)离线玩家添加权限 =====
CompletionStage API 可以用来轻松交互插件的存储,查看[https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html 这里] 和 [https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html 这里] 来查看这两个类的详细信息。
<source lang="java">LuckPermsApi api = null; // See above for how to get the API instance.
// load the user in from storage. we can specify "null" for their username,
// since it's unknown to us.
api.getStorage().loadUser(uuid, "null").thenComposeAsync(success -> {
    // loading the user failed, return straight away
    if (!success) {
        return CompletableFuture.completedFuture(false);
    }
   
    // get the user instance, they're now loaded in memory.
    User user = api.getUser(uuid);
    // Build the permission node we want to set
    Node node = api.getNodeFactory().newBuilder(permission).setValue(true).build();
    // Set the permission, and return true if the user didn't already have it set.
    try {
        user.setPermission(node);
       
        // now we've set the permission, but still need to save the user data
        // back to the storage.
       
        // first save the user
        return api.getStorage().saveUser(user)
                .thenCompose(b -> {
                    // then cleanup their user instance so we don't create
                    // a memory leak.
                    api.cleanupUser(user);
                    return CompletableFuture.completedFuture(b);
                });
       
    } catch (ObjectAlreadyHasException e) {
        return CompletableFuture.completedFuture(false);
    }
   
}, api.getStorage().getAsyncExecutor());</source>
===== 获得玩家的前缀 =====
LuckPerms 有一个(复杂的)缓存系统,用于非常快速的权限/信息查询。这些类都在 API 里,并且可以在可能的地方使用。
<source lang="java">LuckPermsApi api = null; // See above for how to get the API instance.
// Get the user, or null if they're not loaded.
User user = api.getUserSafe(uuid).orElse(null);
if (user == null) {
    return Optional.empty(); // The user isn't loaded. :(
}
// Now get the users "Contexts". This is basically just data about the players current state.
// Don't worry about it too much, just know we need it to get their cached data.
Contexts contexts = api.getContextForUser(user).orElse(null);
if (contexts == null) {
    return Optional.empty();
}
// Ah, now we're making progress. We can use the Contexts to get the users "MetaData". This is their cached meta data.
MetaData metaData = user.getCachedData().getMetaData(contexts);
// MetaData#getPrefix returns null if they have no prefix.
return metaData.getPrefix();</source>
===== 获得玩家请求的权限 =====
我们也可以使用这个缓存系统来获得一个包含用户权限的 Map 实例,包含了基础的权限查询。
<source lang="java">// All retrieved in the same way as shown above.
User user;
Contexts contexts;
PermissionData permissionData = user.getCachedData().getPermissionData(contexts);
Map<String, Boolean> data = permissionData.getImmutableBacking();</source>
===== 寻找权限 =====
你可以使用 Java 8 的流轻松过滤并返回一个用户请求的权限
<source lang="java">public boolean hasPermissionStartingWith(UUID uuid, String startingWith) {
    // Get the user, if they're online.
    Optional<User> user = api.getUserSafe(uuid);
    // If they're online, perform the check, otherwise, return false.
    return user.map(u -> u.getPermissions().stream()
            .filter(Node::getValue)
            .filter(Node::isPermanent)
            .filter(n -> !n.isServerSpecific())
            .filter(n -> !n.isWorldSpecific())
            .anyMatch(n -> n.getPermission().startsWith(startingWith))
    ).orElse(false);
}</source>
===== 创建新的组并分配权限 =====
这个方法不是阻塞的,所以可以安全的在主线程调用,一旦操作完成,回调会异步运行。
<source lang="java">api.getStorage().createAndLoadGroup("my-new-group").thenAcceptAsync(success -> {
    if (!success) {
        return;
    }
    Group group = api.getGroup("my-new-group");
    if (group == null) {
        return;
    }
    Node permission = api.buildNode("test.permission").build();
    try {
        group.setPermission(permission);
    } catch (ObjectAlreadyHasException ignored) {}
    // Now save the group back to storage
    api.getStorage().saveGroup(group);
}, api.getStorage().getAsyncExecutor());</source>
==== 版本控制 ====
在 2.0 版本里,LuckPerms 遵循了 Semantic 版本控制。
唯一不同的是 patch 号不包含在任何地方,除了 pom,并且每次构建都会计算,基于上次提交后的提交数量。(每个新的小版本都会创建新的标签)
这意味着 API 版本不再有 patch 号(在 patch 里没有 API 的变化),API 版本会是 x.y,每个不同的 LuckPerms 构建都会遵循 x.y.z。
===== 变更日志 =====
* 版本 2.x 保持了几个月的稳定,没有任何向后不兼容的变更,但是在之后的版本里很多的方法变为弃用状态,并且事件 API 的确应该重写一遍。
* 版本 3.x 包含了以下的向后不兼容的变化。 https://gist.github.com/PluginsCDTribe/fdf6ae4b2d9e466d8103dd9c68e5db9e
== 其他 ==
=== 语言文件 ===
LuckPerms 插件中所有的消息(包括颜色和格式代码)都能够修改。(似乎合情合理)
将下面的文件之一下载然后存储到LuckPerms的文件夹中,然后命名为 '''&quot;lang.yml&quot;'''。
将文件中的消息文本改成你喜欢的样子,然后重启你的服务器就好了。
* [https://github.com/lucko/LuckPerms/blob/master/.locale/en_US.yml '''en_US''' - 英语]
* [https://github.com/lucko/LuckPerms/blob/master/.locale/es_ES.yml '''es_ES''' - 西班牙语]
* [https://github.com/lucko/LuckPerms/blob/master/.locale/ru_RU.yml '''ru_RU''' - 俄语]
* [https://github.com/lucko/LuckPerms/blob/master/.locale/zh-CN.yml '''zh-CN''' - 简体中文]
* [https://github.com/lucko/LuckPerms/blob/master/.locale/pl_PL.yml '''pl_PL''' - 波兰语]
=== PlaceholderAPI ===
在 extended_clip 的 [https://www.spigotmc.org/resources/placeholderapi.6245/ PlaceholderAPI] 插件中,LuckPerms 也注册了一些变量(Placeholders)。
LuckPerms 插件所使用的标识符是 '''luckperms'''。
==== 使用 ====
要想使用变量的话,你需要运行下列命令。 这些命令的作用就是安装 LuckPerms 的变量扩展,安装后你就可以使用下面列举出的变量了。
<code>/papi ecloud download LuckPerms</code>
<code>/papi reload</code>
请记住使用这些指令你需要OP权限(或者你也可以选择在控制台中运行这些指令)
同时请注意,如果你想得到玩家的前缀或后缀数据,——如果你在服务器上安装了Vault插件和Vault的变量扩展的话,你也可以使用 Vault 插件所提供的变量。
==== Placeholders ====
<code>%luckperms_group_name%</code>
'''使用说明:''' 返回玩家当前所在组的名字<br />
'''使用示例:''' n/a
-----
<code>%luckperms_context_&lt;context key&gt;%</code>
'''使用说明:''' 返回给定内容关键字的值,如果内容没有值的话会返回空 '''使用示例:''' %luckperms_context_server%
-----
<code>%luckperms_groups%</code>
'''使用说明:''' 返回服务器上的权限组列表,用逗号分割 '''使用示例:''' n/a
-----
<code>%luckperms_has_permission_&lt;permission&gt;%</code>
'''使用说明:''' 检查玩家是否直接拥有该权限,不会检查通配符或继承的权限 '''使用示例:''' %luckperms_has_permission_essentials.ban%
-----
<code>%luckperms_check_permission_&lt;permission&gt;%</code>
'''使用说明:''' 检查玩家是否拥有指定权限,这个变量工作的方式和正常插件的检查方式没有区别 '''使用示例:''' %luckperms_check_permission_some.cool.permission%
-----
<code>%luckperms_in_group_&lt;group&gt;%</code>
'''使用说明:''' 返回玩家是否为给定组的成员,不包括继承组 '''使用示例:''' %luckperms_in_group_admin%
-----
<code>%luckperms_inherits_group_&lt;group&gt;%</code>
'''使用说明:''' 返回玩家是否在给定组或继承给定组 '''使用示例:''' %luckperms_inherits_group_vip%
-----
<code>%luckperms_on_track_&lt;track&gt;%</code>
'''使用说明:''' 返回玩家的权限组是否在给定权限组树上 '''使用示例:''' %luckperms_on_track_staff%
-----
<code>%luckperms_has_groups_on_track_&lt;track&gt;%</code>
'''使用说明:''' 检查玩家是否继承给定权限组树中的任何一个组 '''使用示例:''' %luckperms_on_track_donor%
-----
<code>%luckperms_highest_group_by_weight%</code>
'''使用说明:''' 返回玩家所在权限组树种的最高级权限组 '''使用示例:''' n/a
-----
<code>%luckperms_lowest_group_by_weight%</code>
'''使用说明:''' 返回玩家所在权限组树种的最低级权限组 '''使用示例:''' n/a
-----
<code>%luckperms_first_group_on_tracks_&lt;tracks&gt;%</code>
'''使用说明:''' 返回玩家在给定权限组树上所在的第一个组,权限组树会返回一组用逗号分隔的权限组名,权限组树中的每一个权限组都正序排列。 '''使用示例:''' %luckperms_first_group_on_tracks_staff,donor%
-----
<code>%luckperms_last_group_on_tracks_&lt;tracks&gt;%</code>
'''使用说明:''' 返回玩家在给定权限组树上所在的最后一个组,权限组树会返回一组用逗号分隔的权限组名,权限组树中的每一个权限组都倒序排列。 '''使用示例:''' %luckperms_last_group_on_tracks_staff,donor%
-----
<code>%luckperms_expiry_time_&lt;permission&gt;%</code>
'''使用说明:''' 获得玩家拥有的临时权限剩余的时间,如果玩家没有该权限的话会返回空 '''使用示例:''' %luckperms_expiry_time_essentials.fly%
-----
<code>%luckperms_group_expiry_time_&lt;group name&gt;%</code>
'''使用说明:''' 获得玩家拥有的临时权限组所剩余的时间,如果玩家不在该权限组的话会返回空 '''使用示例:''' %luckperms_group_expiry_time_vip%
-----
<code>%luckperms_prefix%</code>
'''使用说明:''' 返回玩家的前缀,使用Vault所提供的变量所输出的结果可能会更精确,这一项不会被Vault的配置设置影响 '''使用示例:''' n/a
-----
<code>%luckperms_suffix%</code>
'''使用说明:''' 返回玩家的后缀,使用Vault所提供的变量所输出的结果可能会更精确,这一项不会被Vault的配置设置影响 '''使用示例:''' n/a
-----
<code>%luckperms_meta_&lt;meta key&gt;%</code>
'''使用说明:''' 返回与指定Meta关键字联系的值 '''使用示例:''' %luckperms_meta_some-key%
-----
== Link ==
* [https://discord.gg/W3FzxHA Discord 服务器]
* 在 irc.esper.net 我是 "Luck",我也在 irc.spi.gt 和 chat.freenode.net
* SpigotMC 和 Sponge 论坛: "Luck"
* [https://github.com/lucko/LuckPerms/issues GitHub]
[[分类:Spigot插件]][[分类:CraftBukkit插件]][[分类:Sponge插件]]
[[Category:管理]][[Category:安全]]

2024年3月30日 (六) 10:23的最新版本

Minecraft插件百科提醒您,此条目或需要大幅度整改,建议新用户不要模仿此条目格式建立新条目。

原因在于:

  • 页面冗长,需要拆分子页面
若您清楚改善现状的方法,可以尝试帮忙改进
LuckPerms
外文名LuckPerms
作者Luck
插件类型Spigot / CraftBukkit / Sponge
最新版本4.0.18(Bukkit) / 4.0.60(Sponge)
兼容服务端1.7, 1.8, 1.9, 1.10, 1.11, 1.12,1.13,1.14,1.15,1.16,1.17,1.18,1.19,1.20
源地址SpigotMC
SpongePowered

LuckPerms是Minecraft服务端(Bukkit / Spigot,BungeeCord等)的权限插件。它允许服务器管理员通过创建组和分配权限来控制玩家可以使用的功能,由Luck开发。

为什么选择LuckPerms?

LuckPerm是一款先进、高等的权限插件,仅仅以快速稳定可靠灵活多变的特点,

便可以替代现有的许多权限插件,例如PermissionsEX、GroupManagerX、z/bPermissions、BungeePerms等主流权限插件。

LuckPerms这个插件的计划,本来是围绕着两个主要特点来制作的:高性能、强大且广泛的功能,

填补其他同类插件的功能缺陷、并且建立在同类现有功能上更进一步的优化功能。

LuckPerms还包括了非常广泛的API支持,这是为开发人员的添加的,

并且,luckperms还兼容各式各类Minecraft服务器软件&支持多种数据存储的选择。

来吧兄弟,告诉我,我为什么要使用LuckPerm?

LuckPerm能做很多事情,至少单在技术层面,LuckPerm就胜过大部分同类插件。

我认为这不取决于我制作插件的水平,而是取决于我在LuckPerm上面花费的精力与时间。

LuckPerm是我在2016年开始准备编写的插件,但因为Bukkit变得流行起来,许多同一时期的插件都变成了老牌稳定插件,

不过,这也为我编写LuckPerm提供的很好的参考帮助,因为我可以避免其它同类插件的缺陷,

并且明白它们哪些地方做的特别出色,我可以在其基础之上进一步优化,使那部分功能变得更加引人瞩目。

记着,如果你对LuckPerm技术性方面的内容感兴趣,我推荐你从[命令使用]部分开始阅读

或者看看wiki列出的其他部分内容,在本节的其余部分,我会将阅读重点放到LuckPerm一些全新的特色功能上面。

这些内容是你不太可能从其他插件中找到的,专属luckPerm的特色功能!

Verbose(权限查看系统) Verbose是Luckperms一套完整的权限查看系统。

他可以实时监视并检测其他插件所需的权限

你也可以把录像上传到网上,方便查看、分析和阅读:

[https://git.io/vQitM]

权限树系统

LuckPerm允许你在服务器所有已知权限上建立编写"权限树"。

权限树上的数据是由你所有的插件在服务器注册的权限构成的。

随着你服务器运营时间的增长,因为服务器添加了许多插件,它们都会注册权限,这些数据都会被纳入权限树中。

这是个清真的例子 [https://git.io/vQiti]。 你看到的权限树的颜色,代表了你的玩家是否拥有对应的权限,这一机制很方便的让你查阅到服务器的相应权限。

这还是那个清真的例子 [[1]]

指令界面&TAB补全

LuckPerm的指令系统被我设计的尽可能便捷、易用、人性化,

这样一来,你除了查阅LuckPerm的[大量相关帮助文档],还可以在游戏中查看指令用法、以及指令列表。

LuckPerm的所有指令皆可使用TAB补全功能,这就意味着,你可以通过输入更少的指令来完成你的工作!

这是不是在一定程度极大地提高了你的工作效率呢?就像下面那样:

网站编辑器

除了使用指令来编辑服务器权限相关,LuckPerm还提供了更加便捷的编辑方式,

你可以使用Web网站编辑器来对服务器的权限数据进行快速更改,

任何人都能够使用网站编辑器,不论你使用了哪种存储方式!

网站编辑功能非常容易使用,且易于上手

【图片过大 请去wiki页面查看】

行为记录仪

为了防止服务器中出现心存不轨的管理员,想要私自给自己添加权限,

LuckPerm详细的记录了服务器各类权限的微小变化,

你可以通过行为记录仪来搜索每个人的详细操作。

你也可以查看所有东西的详细历史。

安装

安装

初始设置

1. 下载适合你平台的 `LuckPerms-???-x.x.x.jar` 文件。你可以点这里查看最新的版本。

2. 打开你的 Mod 或插件所在路径,这路径通常要么是 `/server/plugins/` ,要么是 `/server/mods/`。

然后把 LuckPerms 的 jar 文件放入文件夹中。

3. 请完全关闭你的服务器,然后再打开,这会生成默认配置。

4. 完全关闭你的服务器,打开配置文件。配置文件的位置在 `/plugins/LuckPerms/config.yml` 或 `/config/luckperms/luckperms.conf`。

5. 请浏览配置文件,然后根据你的服务器修改设置,尤其是请注意存储相关设置。

6. 再次开启你的服务器。

你可以更改配置文件中的很多内容,文件有很细节化的注释,每个设置的作用注释中都解释的很清楚。

需求

LuckPerms 插件只有一个环境需求。

  • Java 8

没错,唯一需求就是你必须使用 Java 8,LuckPerms 插件在旧版本的Java上不会工作。

到目前为止很多服务器提供商都已经升级到Java 8了,但是如果你的服务器提供商没有升级的话,请温和地和他们谈谈,让他们去升级。

如果你是自己租主机开服的话,你应该对你还没有升级Java感到羞愧!

升级的过程是很简单的,如果你想升级的话网上也有大量的教程。

使用过期的软件肯定不是好的:)

Bukkit版本过旧

如果你收到了类似于 "NoSuchMethod" 或 "ClassNotFound" 这类错误的话,十有八九就是你在使用较旧的Bukkit版本。

在将它作为错误报告给我之前,请尝试使用"Development Builds"(构建版本)下载页面的"Bukkit-Legacy"(Bukkit-旧版)版本。

切换存储类型

LuckPerms 插件所使用的默认数据存储类型是 H2 数据库

所有的数据都会储存在LuckPerms插件目录下的 `luckperms.db.mv.db` 文件之中。

(插件目录为 `/plugins/LuckPerms/` 或 `/luckperms/`)

这个数据格式普通的文本编辑器是**不能读取**的。

如果你想要手动阅读/编辑LuckPerms插件的数据的话,你就需要切换到**YAML或JSON**存储格式,更改 `config.yml` 文件中的配置选项就好了。

更多相关于存储类型的有关信息请阅读[下一节]

选择存储类型

LuckPerms 插件带有很多存储数据的方式,你可以从中选择。

存储类型选项可以在 `config.yml` 或 `luckperms.conf` 文件中修改。

# Which storage method the plugin should use.
# Currently supported: mysql, postgresql, sqlite, h2, json, yaml, mongodb
# Fill out connection info below if you're using MySQL, PostgreSQL or MongoDB
storage-method: h2

请记住如果你想改变存储类型的话,你的数据不会自动转移到新的存储库中。

要想手动在数据存储方式间转移数据的话,请查看这里来获得更多信息。

可用的选项都列在了下面。

H2 / SQLite

默认的存储类型是 H2

这两种文件类型都是以SQL数据库为基础的。

所有的数据都会存储在LuckPerms插件目录下的一个文件之中。

和YAML和JSON方式的不同之处在于,这个文件不能用文本编辑器打开。

你必须使用插件提供的命令才能编辑或查看数据。

如果你选择使用 H2 数据库的话(默认设置),所有的数据都会储存在 `luckperms-h2.mv.db` 文件中。

SQLite 类型所提供的存储文件是 `luckperms-sqlite.db`。

要想使用这两种类型中的一种,请将配置设置为:

storage-method: h2
# or
storage-method: sqlite

JSON / YAML

JSON 和 YAML 存储类型会将数据存储在可读可编辑的文本文件中。YAML 类型所提供的文件扩展名为 `.yml` ,JSON类型所提供的文件扩展名为 `.json`。

这两种类型的存储格式很相似,只是在一些句法上不同。

示例 YAML 文件

uuid: c1d60c50-70b5-4722-8057-87767557e50d
name: Luck
primary-group: default
permissions:
- group.default:
    value: true
- test.permission:
    value: true
    server: factions
- other.test.permission:
    value: false

示例 JSON 文件

{
  "uuid": "c1d60c50-70b5-4722-8057-87767557e50d",
  "name": "Luck",
  "primaryGroup": "default",
  "permissions": [
    {
      "group.default": {
        "value": true
      }
    },
    {
      "test.permission": {
        "value": true,
        "server": "factions"
      }
    },
    {
      "other.test.permission": {
        "value": false,
        "server": "test"
      }
    }
  ]
}

要想使用这两种类型中的一种,请将配置设置为:

storage-method: yaml
# or
storage-method: json

MySQL / PostgreSQL

储存在 MySQL 类型和 PostgreSQL 类型中的数据格式上与上文提及的 H2/SQLite 类型相同,但是数据是储存在远程服务器上的。

这意味着你可以跨服分享相同的数据。

你需要在配置文件中输入你数据库服务器的地址,端口,数据库名,用户名和密码。

这种类型推荐要存储大量数据的用户,或是想要搭建群组服务器的用户所使用。

如果你已经在运行群组服务器,并且想要在子服务器之间同步数据的话,你就必须选择这种类型了。

格式布局示例在这里

要想使用这两种选项中的一种,请将配置设置为:

storage-method: mysql
# or
storage-method: postgresql

MongoDB

LuckPerms 也支持 MongoDB 类型的存储,它也是一种远程数据库,在有些方面上和 MySQL 相似。

这种类型也只会被一小部分的用户所使用。

要想使用这种类型的存储,请将配置设置为:

storage-method: mongodb

使用教程

这篇教程是为之前从来没有使用过权限管理插件的人所准备的。

如果你已经很熟悉权限管理等相关概念了的话,我认为你应该就能够理解命令中的东西了。

这样我就推荐你去阅读命令和权限页面,这样更加“直奔主题”,你也能够更容易理解插件的工作方法。

如果你正在努力想弄明白权限管理相关概念的话,这篇教程就是你起步的最佳地方:)


关键术语

权限

在你的服务器上会有大量的**特性,命令和一些新功能**。

这其中的一些特性是服务器自带的,另一些是由“插件”所添加的。

与这些特性相联系的大多数行为都是由权限所控制的,因此你可以控制哪些用户可以使用你指定的特性或权限。

    • 权限仅仅是个字符串**,并且使用英文的句号(半角 → . ←)分成几部分。

举个例子, “minecraft.command.ban” 就是原版 /ban 命令所使用的权限。

显然我们不想让所有用户都能执行这个命令,所以我们只给我们信任的玩家这个权限。

代表特定行为的使用许可的字符串,我们就称之为权限,它又名“权限节点”,简称“权限”。

权限组

代替单独为每个用户设置权限,我们可以将**权限捆绑为一组**,然后直接将这一组**给予玩家**。

举个例子,在我设置的“admin”权限组中,我可能会添加使用ban和unban指令的权限,然后将玩家加入admin权限组中。

这意味着他们能够获得“admin”权限组所设置的所有权限和他们自身被设置的权限。

继承

用户和权限组能够**互相继承权限**。

举个例子,默认地,所有的用户都会从“default”权限组继承权限。

你可以为你自己的服务器设置你自己的权限组与继承方式,或是制作你自己独特的系统。

举个例子,我设置了三个权限组, “default”, “moderator” 和 “admin”。

我想让“moderator”权限组从“default”权限组继承所有权限,“admin”权限组从“moderator”权限组继承所有权限。

起步

如果你还没有将LuckPerms插件安装在你的服务器上的话,我们推荐你先阅读安装有关的教程。

然后,请确保你在继续之前已经阅读了选择数据存储类型的有关章节。

虽然你在后期也能实现数据之间的转移,但第一次就将他们弄对位置是更好的。

给予修改权限的全部权限

你想做的第一件事情就是给你本插件的所有权限。

当本插件首次安装后,没有人能够使用LuckPerms插件的有关命令。

要想做到这个的话,你需要在服务器控制台输入 `/luckperms user Luck permission set luckperms.* true` 。

当然,请把我的名字换成你自己的(不用担心,这条命令的使用方法之后会详细讲解)

这应该就是运行的结果:

实际上,这条命令起的效果,就是给了 `Luck` 用户 `luckperms.*` 权限。(或者说,为用户设置权限为 true)

你可能已经注意到了我们刚才在权限字符串的末端使用的 `*` 字符了。

这个字符叫做通配符,它会给玩家**所有**以 "luckperms" 为开头的权限。

创建第一个权限组

我们可以使用创建权限组命令来创建一个新的权限组。

让我们创建一个叫做“admin”的权限组,然后给它附加一条权限吧。

首先,运行 `/luckperms creategroup admin` 命令。

这会创建一个叫做“admin”的空权限组。

接下来,我们想为“admin”权限组增加一条权限。

用来修改权限组的命令是 `/luckperms group <group>`

如果你执行这条命令的话,它会为你显示所有可用的子命令。

你可能注意到了第一个子命令是“info”命令。它只会列举出一些权限组相关的信息。

我们可以运行 `/luckperms group admin info` 来查看新建立的“admin”权限组的一些信息。

接下来就是“permission”命令。这能够帮助你修改权限组的权限。

再一次,使用 `/luckperms group admin permission` 命令会列出所有可用的子命令。

再一次,我们看到了更多我们可以执行的命令。

第一个就是另一个 "info" 子命令。

因为它是“permission”子命令下的又一子命令,它就会显示某一权限组所拥有的所有权限。

下面的命令是“set”子命令。

你还记得吗,之前我们使用相似的指令来给玩家 "luckperms.*" 权限。这里它也相同

只需要不加参数运行该命令就可以返回该命令的使用方法。举个例子:

举个例子,我想给我的“admin”用户组 "minecraft.command.ban" 权限。

因此我可以输入 `/luckperms group admin permission set minecraft.command.ban true`

这条命令就会给予 `admin` 用户组 `minecraft.command.ban permission` 权限。

末端的true控制我们设置的权限的启用与否。

你可以将权限的启用与否设置为 `true` 或 `false` 。

为用户或权限组将权限设置为 true 能够让他们拥有该权限,设置为 false 即该权限无效。(指定他们没有该权限)

如果晚些时候我决定不再让“admin”用户组拥有这个权限了,我可以使用 unset 命令来移除该权限的设定。

输入 `/luckperms group admin permission unset minecraft.command.ban`

将玩家加入到权限组中

将用户加入到权限组中需要使用 "parent" 命令。(在我们的命令使用页我们经常用“permission”替换“parent”)

举个例子,把我自己加入“admin”权限组中,我需要使用 `/luckperms user Luck parent add admin`

这条命令会将用户 `Luck` 加入到 `admin` 权限组中。

这意味着任何“admin”权限组所拥有的权限我现在也继承下来了。

让一个权限组继承另一个权限组

就像用户能够继承一样,权限组也能够继承另一个权限组。

举个例子,想想下面这种情况的设置方法。(有些权限仅仅是为了演示而编造出来的)

Admin Mod Default
minecraft.command.ban minecraft.command.mute minecraft.command.say
minecraft.command.pardon minecraft.command.unmute minecraft.command.me
some.cool.admin.perm some.cool.mod.perm
someplugin.vanish |

我想让“admin”权限组中的用户拥有“mod”和“default”权限组的权限,同时“mod”权限组中的用户拥有“default”权限组中的权限。要想实现这个的话,我可以设置用户组之间的相互继承。

`/luckperms group admin parent add mod` 命令会让“admin”权限组继承所有“mod”权限组中的权限。

然后要想让“mod”继承“default”,同样的道理,我可以输入 `/luckperms group mod parent add default`。

继承是可递归的,所以这样以后“admin”权限组就不仅仅继承了“mod”权限组,还继承了“default”权限组。

这意味着“admin”权限组中的玩家拥有“mod”**和**“default”两权限组中的权限了。

在“admin”组的一位用户因此拥有 `minecraft.command.ban`,`minecraft.command.mute` *和* `minecraft.command.say` 权限。

移除继承权限组

要想移除权限组间的继承关系只需要输入一个类似的命令就好了。

要想让我自己不再继承“admin”权限组,我只要输入 `/luckperms user Luck parent remove admin` 就好了。

配置

请见子页面:LuckPerms/配置

特性

请见子页面:Luckperms/特性

开发者

开发者 API

简介

LuckPerms API 允许你更改大量的插件内部编程,并且能够轻松地将 LuckPerms 深度集成到你的插件和系统里。

大多数的其他的权限要么没有 API,要么有很差的 API,或者是有很差的文档的 API,而且里面的方法和类可能随机在不同版本里消失或是移动。Vault 项目就是一个很好的接口,并且是将大量插件一次性集成的很好的方法,可惜他的功能实在是太少了。

LuckPerms 遵循 Semantic 版本控制,也就是意味着一个不向后兼容的新的 API 出现时,主版本会增加这个 API,你可以放心你的集成不会因为版本的不同而崩溃,主要的版本是保持不变的。

如何在项目里使用 API

LuckPerms 的 API 包是 me.lucko.luckperms.api

我的 Nexus 服务器可以在这里找到 https://nexus.lucko.me/,你在你的构建脚本里需要的仓库在 https://repo.lucko.me/

其他有用的链接

Maven

<repositories>
    <repository>
        <id>luck-repo</id>
        <url>https://repo.lucko.me/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>me.lucko.luckperms</groupId>
        <artifactId>luckperms-api</artifactId>
        <version>3.2</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

Gradle

repositories {
    maven {
        name "luck-repo"
        url "https://repo.lucko.me/"
    }
}

dependencies {
    compile ("me.lucko.luckperms:luckperms-api:3.2")
}

使用指南

使用 API,你需要获得 LuckPermsApi 接口的实例,这可以通过几个方法完成。

// 所有平台 (抛出 IllegalStateException 如果 API 没有被加载)
final LuckPermsApi api = LuckPerms.getApi();

// 或者可选的
Optional<LuckPermsApi> provider = LuckPerms.getApiSafe();
if (provider.isPresent()) {
    final LuckPermsApi api = provider.get();
}

// Bukkit/Spigot
ServicesManager manager = Bukkit.getServicesManager();
if (manager.isProvidedFor(LuckPermsApi.class)) {
    final LuckPermsApi api = manager.getRegistration(LuckPermsApi.class).getProvider();
}

// Sponge
Optional<LuckPermsApi> provider = Sponge.getServiceManager().provide(LuckPermsApi.class);
if (provider.isPresent()) {
    final LuckPermsApi api = provider.get();
}
线程安全的警告

所有 LuckPerms 内部,包括 API 都是线程安全的,你可以在异步线程任意调用 API 而不用担心发生错误。

但是,请注意一些操作,(尤其是存储类)是阻塞的。CompletableFuture 就是用于这种情况:防止由于较差的处理导致的增加的错误,当出现 IO 时主线程等待处理完成。注意在添加 Callback 时指定正确的处理器。

我想将 LuckPerms 作为依赖项

在 Bukkit/Bungee,你需要在你的 plugin.yml 添加以下信息

depend: [LuckPerms]

在 Sponge, 在你的插件声明添加这些。

@Plugin(
        id = "myplugin",
        dependencies = {
                @Dependency(id = "luckperms")
        }
)
public class MyPlugin {
    ...
}
事件

LuckPerms 有一个完整的读写API,也有一个事件监听系统。由于插件的多平台的原因,我们使用了内部的事件系统,而不是每个平台已经使用的事件系统(举个例子,Bukkit Event API)。这意味着简单的注册你的平台的监听器将不会生效。

所有的事件都是异步触发的。这意味着不应该在监听器里交互或者调用任何不是线程安全的方法。

值得注意的是,大多数的 Bukkit/Sponge 都不是线程安全的,并且只应该使用主服务器线程来交互。你应该使用调度器来访问 LuckPerms 的监听器。

我怎样才能监听一个事件

所有的事件接口都可以在 me.lucko.luckperms.api.event 包里找到,它们都继承了 LuckPermsEvent 类。

监听事件应该获得 EventBus 实例,使用 LuckPermsApi#getEventBus即可。

为你的监听器创建另一个类常常是个好想法,这是一个你可以用来参考的类。

package me.lucko.test;

import me.lucko.luckperms.api.event.EventBus;
import me.lucko.luckperms.api.event.log.LogPublishEvent;
import me.lucko.luckperms.api.event.user.UserLoadEvent;
import me.lucko.luckperms.api.event.user.track.UserPromoteEvent;

public class TestListener {
    private final MyPlugin plugin;

    public TestListener(MyPlugin plugin, LuckPermsApi api) {
        this.plugin = plugin;

        EventBus eventBus = api.getEventBus();

        // use a lambda
        eventBus.subscribe(LogPublishEvent.class, e -> e.getCancellationState().set(true));
        eventBus.subscribe(UserLoadEvent.class, e -> {
            System.out.println("User " + e.getUser().getName() + " was loaded!");
            if (e.getUser().hasPermission("some.perm", true)) {
                // Do something
            }
        });

        // use a method reference
        eventBus.subscribe(UserPromoteEvent.class, this::onUserPromote);
    }

    private void onUserPromote(UserPromoteEvent event) {
        Bukkit.getScheduler().runTask(plugin, () -> {
            Bukkit.broadcastMessage(event.getUser().getName() + " was promoted to" + event.getGroupTo().get() + "!");

            Player player = Bukkit.getPlayer(event.getUser().getUuid());
            if (player != null) {
                player.sendMessage("Congrats!");
            }
        });
    }

}

EventBus#subscribe 返回一个 EventHander 实例,可以用来在插件停止的时候取消注册监听器。

示例用法

下面就是一些简短的实例,使用了一些基本的 API 功能。

获得玩家的组

如果你只是想找到一个玩家的组,我非常建议你使用以下的方法(你甚至不需要使用 API)。

public static String getPlayerGroup(Player player, List<String> possibleGroups) {
    for (String group : possibleGroups) {
        if (player.hasPermission("group." + group)) {
            return group;
        }
    }
    return null;
}

记住将你的组排列为优先级的顺序(比如组长在前,成员在后)。

为一个玩家添加权限
LuckPermsApi api = null; // See above for how to get the API instance.

Optional<User> user = api.getUserSafe(uuid);
if (!user.isPresent()) {
    return false; // The user isn't loaded in memory.
}

// Build the permission node we want to set
Node node = api.getNodeFactory().newBuilder(permission).setValue(true).build();

// Set the permission, and return true if the user didn't already have it set.
try {
    user.get().setPermission(node);

    // Now we need to save the user back to the storage
    api.getStorage().saveUser(u);

    return true;
} catch (ObjectAlreadyHasException e) {
    return false;
}
为(可能的)离线玩家添加权限

CompletionStage API 可以用来轻松交互插件的存储,查看这里这里 来查看这两个类的详细信息。

LuckPermsApi api = null; // See above for how to get the API instance.

// load the user in from storage. we can specify "null" for their username,
// since it's unknown to us.
api.getStorage().loadUser(uuid, "null").thenComposeAsync(success -> {
    // loading the user failed, return straight away
    if (!success) {
        return CompletableFuture.completedFuture(false);
    }
    
    // get the user instance, they're now loaded in memory.
    User user = api.getUser(uuid);

    // Build the permission node we want to set
    Node node = api.getNodeFactory().newBuilder(permission).setValue(true).build();

    // Set the permission, and return true if the user didn't already have it set.
    try {
        user.setPermission(node);
        
        // now we've set the permission, but still need to save the user data
        // back to the storage.
        
        // first save the user
        return api.getStorage().saveUser(user)
                .thenCompose(b -> {
                    // then cleanup their user instance so we don't create
                    // a memory leak.
                    api.cleanupUser(user);
                    return CompletableFuture.completedFuture(b);
                });
        
    } catch (ObjectAlreadyHasException e) {
        return CompletableFuture.completedFuture(false);
    }
    
}, api.getStorage().getAsyncExecutor());
获得玩家的前缀

LuckPerms 有一个(复杂的)缓存系统,用于非常快速的权限/信息查询。这些类都在 API 里,并且可以在可能的地方使用。

LuckPermsApi api = null; // See above for how to get the API instance.

// Get the user, or null if they're not loaded.
User user = api.getUserSafe(uuid).orElse(null);
if (user == null) {
    return Optional.empty(); // The user isn't loaded. :(
}

// Now get the users "Contexts". This is basically just data about the players current state.
// Don't worry about it too much, just know we need it to get their cached data.
Contexts contexts = api.getContextForUser(user).orElse(null);
if (contexts == null) {
    return Optional.empty();
}

// Ah, now we're making progress. We can use the Contexts to get the users "MetaData". This is their cached meta data.
MetaData metaData = user.getCachedData().getMetaData(contexts);

// MetaData#getPrefix returns null if they have no prefix.
return metaData.getPrefix();
获得玩家请求的权限

我们也可以使用这个缓存系统来获得一个包含用户权限的 Map 实例,包含了基础的权限查询。

// All retrieved in the same way as shown above.
User user;
Contexts contexts;

PermissionData permissionData = user.getCachedData().getPermissionData(contexts);
Map<String, Boolean> data = permissionData.getImmutableBacking();
寻找权限

你可以使用 Java 8 的流轻松过滤并返回一个用户请求的权限

public boolean hasPermissionStartingWith(UUID uuid, String startingWith) {
    // Get the user, if they're online.
    Optional<User> user = api.getUserSafe(uuid);

    // If they're online, perform the check, otherwise, return false.
    return user.map(u -> u.getPermissions().stream()
            .filter(Node::getValue)
            .filter(Node::isPermanent)
            .filter(n -> !n.isServerSpecific())
            .filter(n -> !n.isWorldSpecific())
            .anyMatch(n -> n.getPermission().startsWith(startingWith))
    ).orElse(false);
}
创建新的组并分配权限

这个方法不是阻塞的,所以可以安全的在主线程调用,一旦操作完成,回调会异步运行。

api.getStorage().createAndLoadGroup("my-new-group").thenAcceptAsync(success -> {
    if (!success) {
        return;
    }

    Group group = api.getGroup("my-new-group");
    if (group == null) {
        return;
    }

    Node permission = api.buildNode("test.permission").build();

    try {
        group.setPermission(permission);
    } catch (ObjectAlreadyHasException ignored) {}

    // Now save the group back to storage
    api.getStorage().saveGroup(group);
}, api.getStorage().getAsyncExecutor());

版本控制

在 2.0 版本里,LuckPerms 遵循了 Semantic 版本控制。

唯一不同的是 patch 号不包含在任何地方,除了 pom,并且每次构建都会计算,基于上次提交后的提交数量。(每个新的小版本都会创建新的标签)

这意味着 API 版本不再有 patch 号(在 patch 里没有 API 的变化),API 版本会是 x.y,每个不同的 LuckPerms 构建都会遵循 x.y.z。

变更日志

其他

语言文件

LuckPerms 插件中所有的消息(包括颜色和格式代码)都能够修改。(似乎合情合理)

将下面的文件之一下载然后存储到LuckPerms的文件夹中,然后命名为 "lang.yml"

将文件中的消息文本改成你喜欢的样子,然后重启你的服务器就好了。

PlaceholderAPI

在 extended_clip 的 PlaceholderAPI 插件中,LuckPerms 也注册了一些变量(Placeholders)。

LuckPerms 插件所使用的标识符是 luckperms

使用

要想使用变量的话,你需要运行下列命令。 这些命令的作用就是安装 LuckPerms 的变量扩展,安装后你就可以使用下面列举出的变量了。

/papi ecloud download LuckPerms 
/papi reload 

请记住使用这些指令你需要OP权限(或者你也可以选择在控制台中运行这些指令)

同时请注意,如果你想得到玩家的前缀或后缀数据,——如果你在服务器上安装了Vault插件和Vault的变量扩展的话,你也可以使用 Vault 插件所提供的变量。

Placeholders

%luckperms_group_name%

使用说明: 返回玩家当前所在组的名字
使用示例: n/a



%luckperms_context_<context key>%

使用说明: 返回给定内容关键字的值,如果内容没有值的话会返回空 使用示例: %luckperms_context_server%



%luckperms_groups%

使用说明: 返回服务器上的权限组列表,用逗号分割 使用示例: n/a



%luckperms_has_permission_<permission>%

使用说明: 检查玩家是否直接拥有该权限,不会检查通配符或继承的权限 使用示例: %luckperms_has_permission_essentials.ban%



%luckperms_check_permission_<permission>%

使用说明: 检查玩家是否拥有指定权限,这个变量工作的方式和正常插件的检查方式没有区别 使用示例: %luckperms_check_permission_some.cool.permission%



%luckperms_in_group_<group>%

使用说明: 返回玩家是否为给定组的成员,不包括继承组 使用示例: %luckperms_in_group_admin%



%luckperms_inherits_group_<group>%

使用说明: 返回玩家是否在给定组或继承给定组 使用示例: %luckperms_inherits_group_vip%



%luckperms_on_track_<track>%

使用说明: 返回玩家的权限组是否在给定权限组树上 使用示例: %luckperms_on_track_staff%



%luckperms_has_groups_on_track_<track>%

使用说明: 检查玩家是否继承给定权限组树中的任何一个组 使用示例: %luckperms_on_track_donor%



%luckperms_highest_group_by_weight%

使用说明: 返回玩家所在权限组树种的最高级权限组 使用示例: n/a



%luckperms_lowest_group_by_weight%

使用说明: 返回玩家所在权限组树种的最低级权限组 使用示例: n/a



%luckperms_first_group_on_tracks_<tracks>%

使用说明: 返回玩家在给定权限组树上所在的第一个组,权限组树会返回一组用逗号分隔的权限组名,权限组树中的每一个权限组都正序排列。 使用示例: %luckperms_first_group_on_tracks_staff,donor%



%luckperms_last_group_on_tracks_<tracks>%

使用说明: 返回玩家在给定权限组树上所在的最后一个组,权限组树会返回一组用逗号分隔的权限组名,权限组树中的每一个权限组都倒序排列。 使用示例: %luckperms_last_group_on_tracks_staff,donor%



%luckperms_expiry_time_<permission>%

使用说明: 获得玩家拥有的临时权限剩余的时间,如果玩家没有该权限的话会返回空 使用示例: %luckperms_expiry_time_essentials.fly%



%luckperms_group_expiry_time_<group name>%

使用说明: 获得玩家拥有的临时权限组所剩余的时间,如果玩家不在该权限组的话会返回空 使用示例: %luckperms_group_expiry_time_vip%



%luckperms_prefix%

使用说明: 返回玩家的前缀,使用Vault所提供的变量所输出的结果可能会更精确,这一项不会被Vault的配置设置影响 使用示例: n/a



%luckperms_suffix%

使用说明: 返回玩家的后缀,使用Vault所提供的变量所输出的结果可能会更精确,这一项不会被Vault的配置设置影响 使用示例: n/a



%luckperms_meta_<meta key>%

使用说明: 返回与指定Meta关键字联系的值 使用示例: %luckperms_meta_some-key%



Link

  • Discord 服务器
  • 在 irc.esper.net 我是 "Luck",我也在 irc.spi.gt 和 chat.freenode.net
  • SpigotMC 和 Sponge 论坛: "Luck"
  • GitHub