forked from mirror/NitWikit
commit
e8c6123079
@ -11,7 +11,7 @@ sidebar_position: 3
|
||||
|
||||
### Events - 事件
|
||||
|
||||
什么是事件? 什么人在什么地方做了什么事情,最简单的三要素构成了事件。
|
||||
什么是事件? 谁在某地做了某事,最简单的三要素构成了事件。
|
||||
|
||||
在 Bukkit 服务器中,事件是系统或玩家行为触发的特定情况或变化。
|
||||
|
||||
@ -232,60 +232,78 @@ on join:
|
||||
|
||||
## "function"用法
|
||||
|
||||
## 如何编写脚本?
|
||||
## 脚本编写思路 (by TUCAOEVER)
|
||||
|
||||
可以看到 Skript 提供给我们一共 120 个监听。这么多的监听,我们究竟该怎么选择呢?选择完又该如何使用呢?
|
||||
|
||||
这里我们拿 "on command" 监听器为例(命令执行监听器)。
|
||||
|
||||
我们把我们对于事件的定义拿过来:谁在某地做了某事。
|
||||
|
||||
可以看到 Skript 提供给我们一共 120 个监听可供使用这么多的监听 我们究竟该怎么选择呢 选择完又该如何使用呢?
|
||||
这里我们拿 "on command" 监听器为例(命令执行监听器)
|
||||
我们把我们的定义拿过来 什么人在什么地方做了什么事情
|
||||
现在我们已知什么事情指的是执行命令 现在我们需要知道什么?
|
||||
我们需要知道的是 什么人? 什么地方?
|
||||
那么我们如何知道这些元素呢? 这时候我们需要下面这个网站
|
||||
https://skripthub.net/docs/
|
||||
现在我们已知要完成的事是“执行命令”,现在我们需要知道什么?
|
||||
|
||||
在侧边栏中选中(Skript Events)后 在搜索栏中输入 "on command"
|
||||
我们需要知道的是——“谁”和“某地”。
|
||||
|
||||
我们要重点关注的是 "Event Values" 这一标签下所对应的内容
|
||||
可以看到 "on command" 卡片上 "Event Values" 标签下共有三个字段
|
||||
分别为 "event-world" "event-commandsender" 以及 "event-player"
|
||||
翻译对应为 "事件-世界" "事件-指令发送者" "事件-玩家"
|
||||
利用这些 我们便可以获取到 事件中的 什么人 什么地方 这些具体的信息
|
||||
我们看一个 "on command" 相关示例
|
||||
那么我们如何知道这些元素呢? 这时候我们需要下面这个网站:https://skripthub.net/docs/
|
||||
|
||||
在侧边栏中选中(Skript Events)后,在搜索栏中输入 "on command"。
|
||||
|
||||
我们要重点关注的是 "Event Values" 这一标签下所对应的内容,我们可以看到 "on command" 卡片上 "Event Values" 标签下共有三个字段:
|
||||
1. "event-world"("事件-世界")
|
||||
2. "event-commandsender"("事件-指令发送者")
|
||||
3. "event-player"("事件-玩家")
|
||||
|
||||
利用这些,我们便可以获取到,事件中的,“谁”和“某地”之类具体的信息。
|
||||
|
||||
我们看一个 "on command" 相关示例:
|
||||
```skript
|
||||
on command "/op":
|
||||
send "%event-world%" to console
|
||||
send "%event-commandsender%" to console
|
||||
send "%event-player%" to console
|
||||
复制代码
|
||||
我调取了指令监听器 任何执行者执行 "/op" 指令都会触发此监听
|
||||
监听被触发后 将自动将三个元素 "event-world" "event-commandsender" "event-player" 输出到后台
|
||||
如果是一位玩家执行了 "/op" 命令 "event-world" 将会输出玩家在哪个世界执行了命令
|
||||
"event-commandsender" 将会输出为 "player" 因为监听器由玩家触发 而 "event-player" 则会输出为 "玩家的名字"
|
||||
那么如果是后台执行了 "/op" 命令呢? 因为后台并不存于任何一个世界 也没有名字
|
||||
上述三个元素只会有 "event-commandsender" 存在并正常输出为 "console" 而其余不存在元素将全部输出为 `"<none>"`
|
||||
相同的你可以利用这样的方法 输出任何一个监听器下 "Event Values" 的元素值
|
||||
这种获取元素值的方法将在你需要使用任何从来没有接触过得监听器的时候 快速让你掌握监听器的基本信息
|
||||
既然我们已经监听到了这个事件 除了获取一些与事件相关的信息之外 我们还能做一些什么呢?
|
||||
取消事件!
|
||||
事件发生的顺序是 事件准备发生 > 监听器监听到 > 事件正式发生
|
||||
如果我们在监听器监听到后 加入 取消事件 这一环节
|
||||
事件发生的顺序就变为了 事件准备发生 > 监听器监听到 > 取消事件 > 事件未发生
|
||||
我们就成功阻止了 "/op" 指令的发生 那在实际脚本中我们怎么实现这一流程呢?
|
||||
cancel event 譬如我们上面所说的这段指令 我们在结尾加入 cancel event
|
||||
```
|
||||
|
||||
***
|
||||
我调取了指令监听器,任何执行者执行 "/op" 指令都会触发此监听。
|
||||
|
||||
监听被触发后,将自动将三个元素 "event-world" "event-commandsender" "event-player" 输出到后台。
|
||||
|
||||
如果是一位玩家执行了 "/op" 命令,"event-world" 将会输出玩家在哪个世界执行了命令,"event-commandsender" 将会输出为 "player" 因为监听器由玩家触发 而 "event-player" 则会输出为 "玩家的名字"
|
||||
|
||||
那么如果是后台执行了 "/op" 命令呢?
|
||||
|
||||
因为后台并不存于任何一个世界,也没有名字。上述三个元素只会有 "event-commandsender" 存在并正常输出为 "console" 而其余不存在元素将全部输出为 `"<none>"`
|
||||
|
||||
相同地,你可以利用这样的方法,输出任何一个监听器下 "Event Values" 的元素值。这种获取元素值的方法将在你需要使用任何从来没有接触过的监听器的时候,快速让你掌握监听器的基本信息。
|
||||
|
||||
既然我们已经监听到了这个事件 除了获取一些与事件相关的信息之外 我们还能做一些什么呢?
|
||||
|
||||
取消事件!
|
||||
|
||||
事件发生的顺序是 事件准备发生 > 监听器监听到 > 事件正式发生。
|
||||
|
||||
如果我们在监听器监听到后,加入 `取消事件` 这一环节。
|
||||
|
||||
事件发生的顺序就变为了 事件准备发生 > 监听器监听到 > 取消事件 > 事件未发生。
|
||||
|
||||
我们就成功阻止了 "/op" 指令的发生,我们使用 `cancel event` 来达到这一点。
|
||||
|
||||
譬如我们上面所说的这段指令 我们在结尾加入 cancel event:
|
||||
|
||||
```skript
|
||||
on command "/op":
|
||||
send "%event-world%" to console
|
||||
send "%event-commandsender%" to console
|
||||
send "%event-player%" to console
|
||||
cancel event
|
||||
***
|
||||
```
|
||||
|
||||
通过测试我们发现 元素仍然能正常输出 但是 "/op" 指令不再生效
|
||||
即使取消了事件 事件的元素仍然会被传递至插件内 这个是需要注意的
|
||||
————————————————————————————————
|
||||
● Conditions(条件)
|
||||
通过测试我们发现,元素仍然能正常输出,但是 "/op" 指令不再生效。
|
||||
|
||||
即使取消了事件,事件的元素仍然会被传递至插件内,这个是需要注意的。
|
||||
|
||||
---
|
||||
|
||||
### Conditions(条件)
|
||||
条件用于判断句 有没有 是不是 都是条件的一种 基本格式为 "if" + 条件
|
||||
这里我们和学习 Events 一样 我们先通过官方 Doc 找到所有的条件
|
||||
这里我们拿最常用的一个条件作示例 判断玩家是否有权限
|
||||
@ -320,8 +338,10 @@ on command "/op":
|
||||
那么在玩家触发此监听器后 系统将会判断玩家是否有 "player.op" 权限
|
||||
如果有 指令将会正常进行 并发送 "true" 给玩家
|
||||
如果没有 指令执行事件将被强制取消 并发送 "false" 给玩家
|
||||
————————————————————————————————
|
||||
● Effects(效果)
|
||||
|
||||
---
|
||||
|
||||
### Effects(效果)
|
||||
与其说它是效果 不如称作行动
|
||||
我们把条件类的示例拿下来接着分析
|
||||
on command "/op":
|
||||
@ -387,8 +407,10 @@ send title "..." with subtitle "..." to player for ... seconds with fade-in ...
|
||||
|
||||
所有的用法问题迎刃而解 学会读 "Patterns" 是初学者必备的技能
|
||||
下文我将不会再提及如何使用 "Patterns" 查阅用法
|
||||
————————————————————————————————
|
||||
● Expressions(表达) & Types(类型)
|
||||
|
||||
---
|
||||
|
||||
### Expressions(表达) & Types(类型)
|
||||
假设你想要调整玩家的最大血量
|
||||
调整血量 之前我们提过 动词 + 名词形式 这是属于 Effects(效果) 类
|
||||
但是实际上是这样么?
|
||||
@ -421,7 +443,7 @@ https://skriptlang.github.io/Skript/classes.html#entity
|
||||
综合上面我们所获得的信息 我们获得了完整一行代码
|
||||
spawn zombie at location of player
|
||||
复制代码
|
||||
————————————————————————————————
|
||||
---
|
||||
Wow 恭喜你 看到这 你就可以开始尝试着写一些插件了
|
||||
这里刚好有一个例子 不妨动动手 试一试
|
||||
在玩家破坏方块时 检查玩家是否有 "fundamental.break" 这个权限
|
||||
@ -431,7 +453,7 @@ Wow 恭喜你 看到这 你就可以开始尝试着写一些插件了
|
||||
|
||||
当然仅仅学这些并不够 为了做到能更快更灵活的使用各类语法
|
||||
在闲暇的时候 把官方 Doc 提供的所有语法的注释都认真的看一遍是快速上手 Skript 的一种好办法
|
||||
————————————————————————————————
|
||||
---
|
||||
"loop"用法
|
||||
你开始尝试着写一些有一些小功能的脚本了 但是难免的你会出现这样的问题
|
||||
你为玩家创建了很多变量 很多都是属于一个类型的
|
||||
@ -445,7 +467,7 @@ Wow 恭喜你 看到这 你就可以开始尝试着写一些插件了
|
||||
你遇到了新的问题 如何存储并快速操作一类变量?
|
||||
这时候你需要两样东西 "数组" "loop"
|
||||
|
||||
● 数组
|
||||
### 数组
|
||||
数组的基本格式为 `{变量名::变量名::变量名......}`
|
||||
我们带入实景 将用 `{(玩家的名称)的游戏币数}` 存储转为用 `{金币::(玩家的名称)}` 存储玩家的游戏币数量
|
||||
我现在服务器有 10000 个玩家
|
||||
@ -462,7 +484,7 @@ Wow 恭喜你 看到这 你就可以开始尝试着写一些插件了
|
||||
``{金币::*}`` 将包含 所有 ``{金币::(玩家的名称)}`` 变量
|
||||
而这个 却是 ``{(玩家的名称)的游戏币数量}`` 怎么改也做不到的
|
||||
|
||||
● Loop
|
||||
### Loop
|
||||
利用数组我们知道了如何快速获取一类数据
|
||||
但是我们又该如何快速操作这一类数据呢? 这时候就需要引入我们的 Loop 结构
|
||||
|
||||
@ -470,16 +492,16 @@ Loop 即 循环结构 是 Skript 里非常常用的结构语句 主要用于操
|
||||
Loop 共有几大标准配合
|
||||
Loop + 数组 / Loop + 次数 / Loop + Types(类型)
|
||||
|
||||
● Loop + 数组 结构
|
||||
### Loop + 数组 结构
|
||||
|
||||
|
||||
● Loop + 次数 结构
|
||||
### Loop + 次数 结构
|
||||
|
||||
|
||||
● Loop + Types(类型) 结构
|
||||
### Loop + Types(类型) 结构
|
||||
|
||||
————————————————————————————————
|
||||
● 注册指令
|
||||
---
|
||||
### 注册指令
|
||||
说到现在 我们所有的代码 似乎都是基于监听器进行编写的
|
||||
我们都需要去触发监听器 才能执行我们的代码 那有没有什么办法可以主动触发我们的代码?
|
||||
这时候我们就需要引入 MineCraft 插件最核心的功能 指令功能而在 Java 里你可能需要这样注册一个指令
|
||||
@ -542,7 +564,7 @@ command /hello [<player>]:
|
||||
比如像是上面这个指令 它只有一个可以填参数的位置 那么在代码段内 它就是 arg-1 即 第一个参数的意思
|
||||
我们只需要记住核心规则 它排在第几位 在代码段内 它就是 "arg-几"
|
||||
当然我在这块的了解并不是很深入 为了不把大家带上歪路 这里引用国外 Skript 作者更为详细的指令注册的教程
|
||||
————————————————————————————————
|
||||
---
|
||||
|
||||
```
|
||||
command /<指令名称> <参数>:
|
||||
@ -599,13 +621,15 @@ Cooldown Bypass
|
||||
Cooldown Storage
|
||||
存储冷却时间全局变量名称
|
||||
|
||||
————————————————————————————————
|
||||
---
|
||||
|
||||
● Function 第一类结构
|
||||
### Function 第一类结构
|
||||
|
||||
众所周知 一个复杂的插件 不免出现相似的代码段
|
||||
有时候你看着不舒服 想要缩减段落 却又无从下手 这时你就需要 Function 来帮忙了
|
||||
这里取本人的SUPERGUILDS的一段代码做讲解
|
||||
众所周知,一个复杂的插件,不免出现相似的代码段。
|
||||
|
||||
有时候你看着不舒服,想要缩减段落,却又无从下手。这时你就需要 Function 来帮忙了。
|
||||
|
||||
这里取 SUPERGUILDS 的一段代码做讲解。
|
||||
|
||||
```
|
||||
file "plugins/SUPERGUILDS/%{_fileDir}%.yml" does not exists:
|
||||
@ -616,19 +640,23 @@ file "plugins/SUPERGUILDS/%{_fileDir}%.yml" does not exists:
|
||||
save yaml "plugins/SUPERGUILDS/%{_fileDir}%.yml"
|
||||
```
|
||||
|
||||
可能不知道这段代码的意思 我现在告诉你
|
||||
这段代码的功能是存储数据至yaml文件内 对于一个非常复杂的脚本 数据的存储是必不可少的
|
||||
同样也会频繁出现在我们的代码中的 难道真的每一次需要存储数据的时候 都需要再去复制粘贴么?
|
||||
对于一个初学者来说 无可厚非 就是多几行而已 但是对于一个老手来说 复制粘贴不可取
|
||||
首先对于一个 5000+ 以上的插件来说 你需要关注的东西很多 一个是代码优化 一个是代码可读性
|
||||
就拿 SUPERGUILDS 来说 7000+ 行 我所有的数据读取和存储都是通过方法完成 单一个数据写入方法
|
||||
我就使用了 100+ 次(也就是上面我提到的这段代码) 如果我们把它都像上面一样全部展开 我的脚本将立即增加 600+ 行
|
||||
但是我们在写脚本的时候真正需要的是这些么? 不 我们需要的是效果 是功能 不是数据处理的流程
|
||||
每次写入数据都需要白白多占 6 行 既不方便后期维护 同时因为要兼顾路径正确与否 浪费很多时间在查错上面 不划算
|
||||
Function 为你解决了这些难题 方法的注册和指令的注册有共同的地方 比如它们同样需要参数 结构一般为
|
||||
可能你不知道这段代码的意思,简而言之,这段代码的功能是存储一些数据至一个 YAML 文件内。对于一个相对复杂的脚本,数据的存储是必不可少的,同样也会频繁出现在我们的代码中的。难道真的每一次需要存储数据的时候,都需要再去复制粘贴么?
|
||||
|
||||
对于一个初学者来说,无可厚非,就是多几行而已。但是对于一个老手来说,**复制粘贴不可取**。
|
||||
|
||||
首先对于一个 5000+ 以上的插件来说,你需要关注的东西很多:一个是代码优化,一个是代码可读性。
|
||||
|
||||
就拿 SUPERGUILDS 来说,它有 7000 多行。我所有的数据读取和存储都是通过方法完成,单一个数据写入方法我就使用了 100 多次,(也就是以上的代码)。如果我们把它都像上面一样全部展开,我的脚本将立即增加 600+ 行。但是我们在写脚本的时候真正需要的是这些么? 不,我们需要的是效果,是功能,不是数据处理的流程。
|
||||
|
||||
每次写入数据都需要白白多占 6 行,既不方便后期维护,又要因为要兼顾路径正确与否,浪费很多时间在查错上面,不划算。
|
||||
|
||||
Function 为你解决了这些难题,方法的注册和指令的注册有共同的地方,比如它们同样需要参数,结构一般为:
|
||||
|
||||
```skript
|
||||
function 方法名(参数名:参数类型, 参数名:参数类型, ...):
|
||||
代码段落
|
||||
复制代码
|
||||
```
|
||||
|
||||
(关于参数名以及参数类型的定义 可以在 "Command" 栏目下找到 此处不再赘述)
|
||||
套用公式 我们可以把上面的代码段转换成方法段
|
||||
|
||||
@ -659,24 +687,37 @@ file "plugins/SUPERGUILDS/playerdata/%uuid of player%.yml" does not exists:
|
||||
SG_writeFile("Datas.Username", "**EVER", "playerdata/%uuid of player%")
|
||||
```
|
||||
|
||||
使用方法的时候请勿画蛇添足在前面另加 "function"
|
||||
通过这样的方法我们大大减少了代码量 提高了开发效率你以为 Function 就结束了?其实不然 作为方法 很多的时候它并没有 "操作" 功能
|
||||
更多的是 "整理/查找/判断" 功能 那遇到这样的情况我们又该如何灵活使用 Function 以供我们使用呢?
|
||||
**使用**方法的时候请勿画蛇添足在前面另加 "function"。
|
||||
|
||||
通过这样的方法我们大大减少了代码量,提高了开发效率。你以为 Function 就结束了?
|
||||
|
||||
其实不然,作为方法,很多的时候它并没有 "操作" 功能,更多的是 "整理/查找/判断" 功能。
|
||||
|
||||
上面我提到了使用 Function 写入了数据 那么有写入肯定需要读取 我们又该如何利用 Function 来缩短我们读取的代码呢?
|
||||
————————————————————————————————
|
||||
● Function 的第二类结构
|
||||
|
||||
---
|
||||
|
||||
### Function 的第二类结构
|
||||
|
||||
```skript
|
||||
function 方法名(参数名:参数类型, 参数名:参数类型, ...) :: 输出参数类型:
|
||||
代码段落
|
||||
return 返回值
|
||||
复制代码
|
||||
与我们之前提到的写入不同 此时在方法的第一行的末尾我们新增了 "输出参数类型"
|
||||
什么叫输出? 就是代码执行完 得到的一个数值 让这个数值回到主代码段 即 返回一个值
|
||||
什么叫参数类型 这里举一个例子 我们知道 1+1=2 因为 1 是一个数字 2 也是一个数字 所以才有 数字+数字=数字
|
||||
那如果我这样写 ①+一 那么又等于什么呢? "①" 和 "一" 在你的思维中 很可能会认为它们仍然是数字 你会觉得答案还是 2
|
||||
但是执行我们代码的是计算机 并不是 我们 计算机所能识别的数字 只有 阿拉伯数字 "1,2,3..."
|
||||
而 "①,一..." 计算机只能识别它们一些字符 并不能利用这些字符进行加减运算 就像是现在问你 水 + 苹果 = ?
|
||||
你或许也没有一个准确的答案. 计算机更是这样
|
||||
所以这时候就需要参数类型来规范我们运算中的这些值 拿一段来自 SUPERISLANDS 的代码做示例
|
||||
```
|
||||
|
||||
与我们之前提到的写入不同,此时在方法的第一行的末尾我们新增了 "输出参数类型"。
|
||||
|
||||
什么是输出? 就是代码执行完,我们会得到一个值,而输出即返回这个值。
|
||||
|
||||
什么是参数类型?这里举一个例子,我们知道 1+1=2,这是因为 1 是一个数字,2 也是一个数字,所以才有数字+数字=数字。
|
||||
|
||||
那“①+一”又等于什么呢? 在你的思维中,很可能会认为它们仍然是数字,你会觉得答案还是 2。
|
||||
|
||||
但是执行我们代码的是计算机,并不是“我们”。在大部分情况下,计算机所能识别的数字,只有阿拉伯数字 "1,2,3..."
|
||||
|
||||
而对于 "①,一...",计算机只能识别它们中的一些字符,并不能利用这些字符进行加减运算。如果有个人突然问你一句水 + 苹果 = ? 你或许也没有一个准确的答案。
|
||||
|
||||
计算机更是这样。所以这时候就需要参数类型来规范我们运算中的这些值,以下是一份示例。
|
||||
|
||||
```
|
||||
function SI_isSlotAvaliable(s: integer, z: integer) :: boolean:
|
||||
@ -687,11 +728,12 @@ function SI_isSlotAvaliable(s: integer, z: integer) :: boolean:
|
||||
|
||||
```
|
||||
|
||||
通过第一类 Function 的学习我们知道这个方法可以放进去两个参数
|
||||
最终会返回一个参数类型为 boolean("布尔")的值 即 "false/true"
|
||||
那么实际操作中我们就可以通过这样一段代码对给定的数值进行判断 是否满足条件
|
||||
如果满足那么返回 "true" 如果不满足 那么就将返回 "false"
|
||||
需要知道的是 在 Skript 编程里 如果代码已经成功获得的最终值 那么方法代码将立即终止
|
||||
从返回成功的一行开始 后面所有代码将不再执行 切记
|
||||
通过第一类 Function 的学习我们知道,这个方法可以放入两个参数,最终会返回一个参数类型为 boolean("布尔") 的值 即 "false/true"。
|
||||
|
||||
到此 所有基础教程已结束 谢谢大家赏脸看完 全文 11111 字 都是自己的一些干货 点个收藏 给点人气便是对我最大的支持
|
||||
那么实际操作中我们就可以通过这样一段代码,判断给定的数值是否满足条件。满足将返回 "true" ,不满足将返回 "false"。
|
||||
|
||||
切记,对于 Skript,如果代码已经成功获得的最终值,那么方法代码将立即终止,也就是说,从返回成功的一行开始,后面所有代码将不再执行。
|
||||
|
||||
到此,所有基础教程已结束,谢谢大家赏脸看完。全文 11111 字,都是自己的一些干货,点个收藏,给点人气便是对我最大的支持。
|
||||
|
||||
(请支持原作者 TUCAOEVER。)
|
||||
|
@ -30,7 +30,7 @@ Skript 是一个脚本插件,取名来自 "script"。是一个面向 Bukkit
|
||||
举一个简单的例子,为了实现玩家每次进入服务器就给有 "xxx" 权限的玩家 64 钻石的功能。
|
||||
|
||||
使用 Java 时的代码:
|
||||
```
|
||||
```java
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent evt) {
|
||||
Player player = evt.getPlayer(); // 玩家加入
|
||||
@ -63,7 +63,7 @@ on join:
|
||||
|
||||
相较使用 Java 编写的插件,进行相同的操作时, Skript 的性能会略低于 Java。
|
||||
|
||||
但大多数情况下性能和代码有巨大的关系。代码质量差对于性能的影响远大于使用 Skript 对性能的影响。
|
||||
但大多数情况下性能和代码本身的质量有巨大的关系。代码质量差对于性能的影响远大于使用 Skript 对性能的影响。
|
||||
|
||||
## 下载及安装
|
||||
|
||||
@ -79,4 +79,8 @@ on join:
|
||||
|
||||
## 基础教程
|
||||
|
||||
## 进阶教程
|
||||
见[“基础教程”](https://yizhan.wiki/NitWikit/process/plugin/other/Skript/%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B)。
|
||||
|
||||
## 进阶教程
|
||||
|
||||
(To be added.)
|
||||
|
Loading…
Reference in New Issue
Block a user