贺兰兰
本帖最后由 贺兰兰 于 2020-11-30 22:45 编辑

前言

什么是 Kotlin

Kotlin是一种在Java虚拟机上运行的静态类型编程语言。它主要是由俄罗斯圣彼得堡的JetBrains开发团队所发展出来的编程语言,其名称来自于圣彼得堡附近的科特林岛。虽然与Java语法并不兼容,但在JVM环境中Kotlin被设计成可以和Java代码相互运作,并可以重复使用如Java集合框架等的现有Java引用的函数库。

为什么选择 Kotlin 进行 Java 应用程序开发

Kotlin是一门简洁,安全,互操作性强,工具友好的现代计算机程序语言,通过使用Kotlin进行程序开发,能够“大大减少样板代码的数量”,“避免空指针异常等整个类的错误”,“充分利用JVM的现有库”。

什么是 TabooLib

TabooLib是一款以内置依赖形式加载的轻量级Bukkit插件开发库,诞生于2017年,现其主要开发者为Bkm016和IzzelAliz

为什么选择TabooLib进行Bukkit插件开发

TabooLib内置了许多高效的工具,可以让你快速创建GUI/书本菜单,高效地创建指令监听,自动注册事件监听器,通过自带的Hikari连接池快速地连接到MySQL数据库,便捷地处理玩家数据,配置文件喝本地化文件......使用TabooLib,能够大幅度减少插件开发周期,提升插件代码质量。

Kotlin+TabooLib能爆出怎样的火花

TabooLib原生支持使用Kotlin作为其开发语言,前者可为后者自动提供JVM平台库,避免了插件自带Kotlin JVM平台库导致的依赖冲突和编译文件大小膨胀的问题。

本文定位

本文适合那些有一定Java和Bukkit开发基础的,希望学习使用Kotlin和TabooLib进行Bukkit插件开发的开发人员们阅读。而对于那些仍然希望使用Java的开发者,您可以通过阅读此文章获得一些有关TabooLib的使用帮助——TabooLib当然也原生支持Java

搭建环境

本教程使用的TabooLib版本为v5.36,TabooLib Loader版本为v2.6
TabooLib开发者和本文作者均推荐使用Jetbrains IntelliJ IDEA作为首选的集成开发环境进行开发

部署 TabooLib-SDK

TabooLib-SDK 是TabooLib官方推出的插件开发模板,内置预配置好的TabooLib所需的Gradle构建列表文件,通过使用TabooLib-SDK你可以快通过简单修改配置文件以快速开始TabooLib插件开发。当前,TabooLib不支持Maven构建

你可以通过以下方式下载并部署TabooLib-SDK

  • 前往Github下载TabooLib-SDK: 点击直接下载最新版本
  • 解压TabooLib-SDK文件夹,可选的,您可以先将文件夹名称改为您的项目名以方便记录
  • 编辑settings.gradle,将 ExamplePlugin 改为您的项目名称

  1. rootProject.name = 'ExamplePlugin'
复制代码

  • 编辑build.gradle,将 io.izzel.taboolib.example 改为您的主类所在包名,将 1.0.0 改为您的插件版本号

  1. group = 'io.izzel.taboolib.example'
  2. version = '1.0.0'
复制代码

可选的,您可通过以下配置内容修改TabooLib版本和TabooLib Loader版本

  1. taboolib {
  2.     tabooLibVersion = '5.36'
  3.     loaderVersion = '2.6'
  4.     classifier = null
  5. }
复制代码

可选的,您可以通过将文件后缀明为jar的文件放入项目根目录中的libs(如无请自行创建)以加载本地依赖文件;或直接在此处添加Maven/Gradle依赖

  1. dependencies {
  2.     compile 'ink.ptms.core:v11600:11600:all'
  3.     compile 'org.jetbrains.kotlin:kotlin-stdlib'
  4.     compileOnly fileTree(dir: 'libs', includes: ['*.jar'])
  5. }
复制代码

  • 编辑 ./src/main/resources/plugin.yml 文件,将 authors: ['坏黑'] 改成你自己的名字以免坏黑盗取你的插件(划掉)
  • 通过IDE重构项目包名为上方设置的group值,并重构项目主类名为上方设置的rootProject.name值(亦可直接前往./src/main/java文件夹内手动修改)
  • 导入项目至IDE,等待Gradle Sync完成

至此,您已完成TabooLib-SDK的部署,不出意外的话,您的主类应当呈现出以下内容:

  1. package kim.minecraft.example

  2. import io.izzel.taboolib.TabooLib
  3. import io.izzel.taboolib.loader.Plugin

  4. object MyExamplePlugin : Plugin() {

  5.     override fun onLoad() {
  6.         // override onLoad()
  7.     }

  8.     override fun onEnable() {
  9.         // override onEnable()
  10.     }

  11.     override fun onDisable() {
  12.         // override onDisable()
  13.     }
  14. }
复制代码

开始了解插件主类代码结构

可选的分号

  1. package kim.minecraft.example

  2. import io.izzel.taboolib.TabooLib
  3. import io.izzel.taboolib.loader.Plugin
复制代码

在插件主类中,首先映入我们眼帘的应当是包声明和类导入声明,这些在Java中再常见不过的东西放到Kotlin中却体现了Kotlin之于Java一个重大的不同点: 句尾分号可选,所谓可选,并不是说向Python等语言一样不存在分号作为每行代码的分割,而是代表着当代码仅占一行,没有必要通过分号表示分割关系时,可以不添加分号,这意味着:

  1. import io.izzel.taboolib.TabooLib;
  2. import io.izzel.taboolib.loader.Plugin;
复制代码

是完全可被接受(但在Kotlin中并不倡导)的语法。当然,当一行代码希望表示多个语句时,分号就是必要的了,如:

  1. import io.izzel.taboolib.TabooLib;import io.izzel.taboolib.loader.Plugin;
复制代码

区别于“类”声明的“对象”声明

  1. object MyExamplePlugin {} //为方便分条说明暂时去除了部分元素,仅保留基本声明
复制代码

对于一个Java Coder来说,包生命和导入声明下面大部分情况下应该就是类声明了,但是,为什么我没有看到class关键字,是看到了一个从未看过的object关键字?

Kotlin是有class关键字的,你完全可以尝试将object改为class,编译器并不会报错,事实上,你也不会看到任何问题。

我们都知道,“Object”指的是对象,由此我们可以猜测出object关键字描述的应当是一个“对象”——事实上,它是一个单例对象。

在Java中,我们往往需要为类单独应用单例模式,以确保该类不会被初始化超过一次,并且希望通过相应操作得到唯一一个对象实例。在Kotlin中,这种繁琐的设计流程被直接简化到了“对象”声明上,只需使用object声明,我们便可以快速得到一个单例对象及其实例。

在主类使用单例对象有何好处

如果你刚刚上手Bukkit开发,那么你可能曾犯过这样一个致命的错误: 当某方法需要提供一个Plugin对象时,你试图直接new一个主类传进去,自以为这样就可以满足方法的要求了——编译时没有报错,但当运行时你却收到了一个错误:插件主类实例只能有一个——很显然,Bukkit的插件主类对象也是一个单例。因此,将主类设计为object的,可以避免让我们设计一个getInstance方法获取主类实例,继而直接传入一个object对象给方法(事实上,在Kotlin中方法被称作函数),如:

  1.         object : BukkitRunnable() {
  2.             override fun run() {
  3.                 MyExamplePlugin.plugin.logger.info("test")
  4.             }
  5.         }.runTaskAsynchronously(MyExamplePlugin.plugin)
复制代码

通过以上方式快速设计一个继承BukkitRunnable的匿名内部类,并像调用静态方法一样调用主类的非静态方法。

需要注意的是,MyExamplePlugin.plugin是由TabooLib提供的Getter,用于获取一个org.bukkit.plugin.java.JavaPlugin(即Bukkit插件主类)实例

Java互操作

Kotlin和Java代码时可以互操作的,在Java中试图获取一个object对象实例,只需调用自动生成的INSTANCE字段,即可获得一个Kotlin对象实例。这意味着,当你正在使用一个TabooLib的Kotlin主类实例,但又希望使用Java编写BukkitRunnable时,写法是这样的:

  1. new BukkitRunnable() {
  2.             @Override
  3.             public void run() {
  4.                 MyExamplePlugin.INSTANCE.getPlugin().getLogger().info("test");
  5.             }
  6.         }.runTaskAsynchronously(MyExamplePlugin.INSTANCE.getPlugin());
复制代码

小心!没有static

Kotlin给我们带来了方便的对象,但同时也夺走了一个Java中重要的东西: 静态方法。这意味着,通常情况下,你不能(实际上也不推荐)创建一个静态方法。取而代之的,你可以创建一个对象,在其中声明函数以调用。

当然,如果你一定需要使用静态方法,那么你可以通过向Kotlin函数声明'@JvmStstic'注解以静态调用,如:

  1. @JvmStatic
  2. fun staticFunction() {
  3. }
复制代码

Kotlin的类继承语法

  1. object MyExamplePlugin : Plugin() {}
复制代码

此处表示对象MyExamplePlugin继承了Plugin类,并调用其空构造函数。

可以发现,Kotlin的构造器并非在类内单独声明,而是直接在类声明上表示。往后我们将会接触更多有关Kotlin的构造器的使用方法。

Kotlin的函数声明语法

  1.     override fun onLoad() {
  2.         // override onLoad()
  3.     }
复制代码

与Java的方法声明语法不同,Kotlin采用fun关键字以声明一个函数,其声明格式大致为

  1. fun 函数名称(参数1 : 参数类型,参数2: 参数类型,...): 返回值类型
复制代码

其中,当不希望返回任何值时,返回值处和其前的冒号可省略不写。

override修饰符

是的,Kotlin将Java的@Override注解的职能直接搬到了修饰符层面上:开发者通过使用override修饰符来声明函数覆盖自其超类。

嘿,不是void

你可能认为空返回值意味着void,但实际上,在Kotlin,空返回值实际上是Unit,也就是说,上述函数声明等同于

  1.     override fun onLoad(): Unit {
  2.         // override onLoad()
  3.     }
复制代码

类型后置语法

你可能已经发现了,在Kotlin中,变量类型是后置的,而不是Java那样的类型前置。

这也就是说,Java中的

  1. public Location getLocation(Location loc) {}
复制代码

在Kotlin中应当写作

  1. fun getLocation(loc: Location): Location {}
复制代码

由于在Kotlin中,函数默认的可见度为public,因此无需显式声明函数公开。

至此,你已经了解了Kotlin得主类结构及相关Kotlin语言语法。

编译插件

当插件编写完成,我们需要编译插件时,可直接运行gradle jar指令,或通过IDE运行Gradle指令编译。



编译后的jar文件会被存放在./build/libs文件夹内

插件太大了吗

你可能会发现,编译后的插件文件远大于它正常情况下的大小,这是因为编译后的插件文件除了我们自己编写的内容外,还包含了TabooLib Loader,用于自动下载和管理TabooLib本体和库文件(包括Kotlin运行时库)。这么做的好处是我们不需要自己在插件内包含Kotlin运行时库,TabooLib会在第一次运行是帮我们自动下载至服务端,极大的缩减了插件大小。

至此,你已经完成了本章的所有内容,下一章中,我们会继续深入Kotlin语法,同时开始接触TabooLib提供给我们的便携功能。


45gfg9
贺兰tql
海螺yyds


Kt好难 爬了

狡诈师

kt不难,用得挺香
如果你有java基础,通过对比学习或许学的更快
而且,java源码 cv 到idea kotlin会自动转化(不一定完全正确)

寒雨_Moro
是taboolib教程!爷青结

RE_OVO
个人感觉kt简化过头了,写起来不是很舒服。
Java虽然有些地方略微繁琐,但最近几个Java版本都做了改进,感觉都不错,有协程就更好了

SmallL_U
贺兰太强惹ummm  [水ummmm]

mz55006987
666666666666666

834068673
66666666666666

逍遥先生.
我竟然看到了错别字,两个

YAO11111
尽量客观解开了回家看了该回家看了

YAO11111
古holy发了一个i李玉刚

YAO11111
ui偶一哦噗i哦怕

YAO11111
hklhklkl;l'lll

YAO11111
速度放缓的法国海军的复古怀旧风格

Lanscarlos
写的太棒了,想问问还有第二篇吗呜呜呜