zh

基本知识

本章将带您梳理开发PNX插件的最基本的一些知识。

ES、JS、ECMA、ECMAScript、JavaScript?

很多新人都听说过上面的这些名字却又不清楚,这里对它们做一些澄清。

JS、JavaScript

你可能猜到了,JS就是JavaScript的简称,JavaScript跟Java关系不大,仅仅是因为当年开发JS的人与开发Java的人 有商业互吹合作,当时Java大火,初出茅庐的JS才“借用”了Java的大名。

ES、ECMA、ECMAScript

首先来说ECMAScript,ECMAScript和JS一样,也是JavaScript的另一种称呼,也是JavaScript的官方正式称呼。
JavaScript后来被ECMA(欧洲计算机制造商协会)控制,这门脚本语言就自然而然地叫做ECMAScript了。

现在,我们通常说到ES的时候,有两种意思:

  1. ES就是ECMAScript,或者说JavaScript的简称
  2. 因为ECMA每次修订JS语言的时候都会发布一个新标准,以ES+版本号来命名,所以也可以指代JS的某个特殊版本

JS语法

PNX-JS中使用的是ES13的JS语法,即2022年新修订的JS语法。
有一点值得注意,JavaScript是向前兼容的,这意味着所有老版本的代码可以在新版中使用。

当然,我们的开发主要还是使用ES6(2015年修订的JS语法),您只需要了解ES6就可以开始开发JS插件了。

如果您还不了解JS语法,我们推荐您在此处查看简单的 ECMAScript教程 ,您 不必全部看完或记忆,只需要看完基础章节,跟着PNX-JS教程在实践中边做边学即可,遇到不会的回过头去看ES教程就行了。

ESM模块

PNX插件使用ESM(ECMA Script Module)模块系统组织代码,这确保了代码有良好的耦合和高复用性。关于ESM的具体内容 您可以 在此处 学习,这里结合PNX-JS实际进行简单的说明:

每个PNX-JS插件都是由多个模块构成的,而每个JS插件就是一个单独的模块。每个模块中默认情况下所有的函数和变量在 其他模块中都是不可见的(不可以在这个js文件之外使用),如果我们要使用的话,需要先将它标注导出,每个模块中需 要导出的函数或变量我们只需要在声明时加上export关键字即可,例如这个lib.js

function myFunc1() {
    // 这个函数
}

export function myFunc2() {
    // 这个函数被导出了,可以在外部使用
}

// 这个变量没有被导出,只能在这个文件内部使用
var a;

// 这个变量被导出了,可以在外部使用
var b;

其中,一个JS插件的入口模块会在plugin.yml中指定,PNX服务器认为这个模块肯定导出了一个main函数和一个close函数, PNX服务器会在特定的时机调用它们,具体已经在 上一章 中描述了。

要使用其他模块导出的内容,单单是标注为导出还不够,还需要在要使用它的模块中添加导入声明,例如我们有一个index.js文件 它在上面提到的lib.js的相同目录中:

// 从lib.js中导入myFunc2函数和b变量
import { myFunc2, b } from "lib.js";

//现在我们可以使用导入了的函数和变量了
myFunc2();
console.log(b);

当然,PNX还提供了一些内置模块,这些内置模块通常以:开头,你可以直接导入,例如:

import { PowerNukkitX } from ":powernukkitx";

PNX还提供了直接导入Java类的功能,一个Java类就是一个模块,例如:

import { Player } from "cn.nukkit.Player";

导入Java类将会是日后开发中用到最多的导入,Java中任何的Java类都可以被导入,包括Java自带的,PNX中的和其他Jar包插件中的。

在上面的例子中,我们导入了Player类,每个Java类都有一个直接类名和完整类名,直接类名就是类本身的名字,比如上面 我们提到的Player,而完整类名是这个类的包名加上直接类名,对于Player而言,其包名为cn.nukkit,所以完整 类名即为cn.nukkit.Player,包名类似于文件夹,只不过它是一个Jar包内部的类似于文件夹的文件分类方式。

在导入Java包的时候,导入的模块名直接写完整类名即可。

您可以在JavaDoc中查看相关Java类的内容。如果还有更多不明白的地方,可以查看 模块详解章节

理解名称

PNX的API都尽量以见名知义的方式命名,看到一个函数或变量就立即可以大概知道它的作用。

比如有一个函数的名字是getAndKillEntity,我们就可以将这个函数的名字以大写字母来分割拆解为get、and、kill、entity 四个单词,逐词翻译为 获取、并且、杀死、实体,连起来就是获取一个实体并把它杀死,这样就解读出了这个函数的作用。

再比如有一个事件的名字为PlayerJoinEvent,拆解为 player、join、event,逐词翻译为 玩家 进入 事件,连起来 就是玩家进服事件,那么你就可以知道这个事件会在玩家进入服务器的时候被触发了。

关于事件的具体内容,我们会在以后的章节讲述,这里不必理解透彻

MC中基本概念

游戏刻

MC,包括PNX中,游戏是以游戏刻为单位运行的,每个游戏刻中PNX会完成一次整个游戏的运算。游戏刻又称GT或者tick。

tps(Tick per second)指每秒有多少游戏刻,通常情况下tps的值为20,这也意味着每个tick的时长为0.05秒,即50毫秒。 但是,在性能不足的情况下,tps会下降,此时tick的时长会变长,玩家会感到卡顿。

实体

实体的完整类名是cn.nukkit.entity.Entity

实体指一个游戏中可自由运动的独立单元,通常意义上包括载具(矿车、船等)、生物、玩家、掉落物、弹射物(箭、鸡蛋、雪球等) 和经验球。

每个实体都具有自己的实体网络ID(数字ID),字符串ID,实体名称,血量,位置(坐标)和NBT,部分实体还具有物品栏和AI等。

每个实体每tick都会进行一次完整的运算处理,包括计算运动,坐标,AI和其他一些行为等。

物品

物品的完整类名是cn.nukkit.item.Item

物品指以物品堆形式存在的物品,通常指物品栏中(背包,箱子等)那种状态的物品,扔出去掉到地上的物品是掉落物实体而非 我们这里说的物品。

每个物品都有自己的数字ID、字符串ID、数量和特殊值,部分物品具有NBT。数字ID已经不被推荐使用,请尽量使用字符串ID。

方块

方块的完整类名是cn.nukkit.block.Block

方块指存在于世界中的,能够破坏、放置或使用的一个世界的组成部分。
物品栏中的方块是物品,掉落物形式的方块是实体。

物品栏

物品栏的完整类名是cn.nukkit.inventory.Inventory

物品栏是能够存放物品的虚拟容器,可以跟真实的容器方块关联,如箱子物品栏,熔炉物品栏等,也可以跟能够持有物品的 实体关联,如玩家物品栏(背包空间)。

世界

一个世界就是一个通常所说的地图或者存档,PNX自带多世界,一个服务器上最多可以有21亿个世界。

世界的完整的类名是cn.nukkit.level.Level

世界的概念与维度的概念不同,维度是世界的一种种类,每个世界都有一个维度属性,多个世界可能拥有完全相同的维度属性, 同样地,每个维度属性可以对应多个世界。简而言之,一个PNX服务器中可以有多个主世界,下界或者末路之地。


© PowerNukkitX 开发组