真正的从零基础学Bukkit开发!——三.Java的流程控制和Bukkit的API - 编程开发 - Minecraft(我的世界)中文论坛 -【】mcbbs5.3】.html

真正的从零基础学Bukkit开发!——三.Java的流程控制和Bukkit的API - 编程开发 - Minecraft(我的世界)中文论坛 -

Minecraft(我的世界)中文论坛

 找回密码
 注册(register)

!header_login!

只需一步,立刻登录

查看: 6680|回复: 29
打印 上一主题 下一主题

[插件开发教程] 真正的从零基础学Bukkit开发!——三.Java的流程控制和Bukkit的API

[复制链接]
贺兰兰 当前离线
积分
13350
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-1-18
查看详细资料

来自:江苏

跳转到指定楼层
楼主
 楼主| 发表于 2020-4-17 20:42:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 贺兰星辰 于 2020-7-20 11:59 编辑

上一章:https://www.mcbbs.net/thread-1014671-1-1.html
一如既往的前言:  我想升9级啊啊啊啊啊

氵了一早上hhhhhh,不想氵了,还是乖乖来更新吧
(所以如果有金粒和人气的话请一定务必要往我身上砸啊)
上期作业讲解:
写一个工厂方法

这很容易,你只需要写一个静态方法,返回一个对象就好,如:
  1. public static Object getOnjectInstance(){
  2.   return new Object();
  3. }
复制代码
Java的运算符  听起来挺高大上,但运算符的意思其实就是加减乘除号之类的....算数运算符:
  hey,你一定知道,数学是一切的基础,即使在编程中也是这样!因此,有以下的运算符可以使用:
  1. int a = 2; //还记得吗,在Java中,一个等于号的意思就是赋值,在这里意为把2赋值给a
  2. int b = 3;
  3. int c;
  4. c = a + b; //加号的意思就是两数相加,就像算数一样,因此c的值为5
  5. c = a - b; //减号的意思就是两数相减,因此c的值为-1
  6. c = a * b; //“星号”(在小键盘上有)的意思就是两数相乘,因此c的值为6
  7. c = a / b; //“左斜杠”的意思是两数[b]整除[/b],注意,是整除,只会返回整数,因此,在这里,2除以3返回的值为0
  8. c = a % b; //“百分号”的意思是取余数,因此c的值为2
  9. int d = a * (b + c) //显而易见,数学中的括号优先计算也是可以使用的
复制代码
hey,如果我们搞一些“数学悖论”,比如,让除数为0,会发生什么?
  1. int a = 0;
  2. int b = 2;
  3. int c = b/a;
复制代码
控制台报错:Exception in thread "main" java.lang.ArithmeticException: / by zero
可以看到,Java通过抛出(throw,即,报错)异常来提醒开发者,如果有人尝试这么做,或许我们应该使用“try"语句处理这个异常

特殊的自增/自减运算符
hey,看看这个代码
  1. int a = 1;
  2. a = a +1;
复制代码

乍一看貌似不太对,有人自己加自己?但事实上,这是正常的语法,其中,赋值后a的值为2。
还记得赋值是什么吗,把右边的值给左边,如果右边是个算式呢?那就先算,再赋值。因此, a = a + 1实际上是先计算了a+1,然后把这个值(即,2)赋值给a。
但是或许,有简单的方法让这个值加一
  1. int a = 1;
  2. int a1 = a++;
  3. int a2 = ++a;
  4. int a3 = a--;
  5. int a4 = --a;
复制代码
这里的++和--即为自增运算符,他们可以让变量增加或是减少1
但是等一下,++可以在变量前面,也可以在变量后面,有什么不同吗?
当我们运行这段代码并输出所有变量时,我们能够看到:

hey,貌似跟我们想的不一样,为什么结果是这些?
事实上,a++和a--这种形式,被称作后缀自增自减法,先计算表达式,再自增自减。因此a1中,先把a1赋值给a,然后使a自增为2;
++a和--a这种形式,被称作前缀自增自减法,先自增自减,再计算表达式。因此在a2中,先使已经在上一步自增为2的a自增为3,然后把a赋值给a2,故a2为3
其实还挺容易理解的,不是吗?
Tips:在上述代码中,变量被赋值了多次,最后的值取最终赋值结果,除非定义final关键词,否则任何变量都可以无限赋值(使用final后,则只能赋值一次)
小心,加号的作用不仅仅是两数相加!在String中,两个字符串可以使用加号来合并起来,如
  1. String a = "hello";
  2. String b = " world";
  3. String c = a + b;(因此c为hello world)
复制代码
关系运算符:
  关系运算符即运算两个数字(也可能是对象,但对象(比如String)一般会用equals方法)是否具有特定关系,运算均返回布尔值(即boolean,真或假)
  1. int a = 2;
  2. int b = 3;
  3. boolean c;
  4. c = a==b; // ==运算符意为判断==左右两边(即a和b)是否相等,很显然,a不等于b,所以c在这里值为false;
  5. c = a!=b //!=运算符恰恰相反,意为判断左右两边是否不等,所以这里c值为true;
复制代码
Tips:千万注意!别把=当作==,这俩很容易搞混!
为什么对象使用equals方法比较相同,而不是用==?
  ==做的工作其实是对比两个东西的内存地址是否相同,在基本数据类型中,当值相同时,他们的内存地址也是相同的原因很复杂,在这里不多赘述),因此才可以用==来比较;而String之前说过是特殊的对象,我们创建一个字符串时,实际上是new(初始化)了一个String对象,两个String对象的内存地址不可能相同,因此不能用==比较。大部分这样的对象都拥有equals方法,通过这个方法可以真正对比两个对象的内容而不是内存地址是否相同
  1. String a = "a";
  2. String b = "a";
  3. boolean c = a==b; //c应该为false
  4. c = a.equals(b); //c为true;
  5. //但是实际运行中,第一个对c的赋值也返回了true,这是因为Java针对String对象搞了一个专门的==号,使他可以对比String的内容了(在其他语言中这个叫做“运算符重载”,不幸的事,Java不支持开发者进行运算符重载.
复制代码

逻辑运算符:  在Java中有三种逻辑运算符,他们分别是逻辑与,逻辑或和逻辑非运算符(很显然,他们只适用于比较布尔值(boolean))
  1. boolean a = true;
  2. boolean b = false;
  3. boolean c;
  4. c = a&&b //&&为逻辑与运算符,当左右都为true是,返回true,否则返回false。此处为false
  5. c = a||b //||为逻辑或运算符,当左右有一个为true时,就可返回true,都不为true则返回false。此处c为true
  6. c = !(a&&b) //!为逻辑非运算符,如果后面的值为true则返回false;后面的值为false则返回true。此处a&&b为false,故c为true
  7. //当然,类似于a&&b&&c这样也是可以的,即abc都为true时才返回true
复制代码
括号的又一个特殊用法
  从上面的代码中,我们可以看到,括号起了一个包含的作用,它使逻辑非运算符指向a&&b这个式子而不是紧跟在他后面的a(即,运行!a&&b会发生的事情)

除此之外,还有位运算符,用于数字的二进制计算,此处略

Java的流程控制:
  什么是流程控制?流程控制可以干什么?
很显然,生活中充满了流程控制:如果我不氵贴了,我就去写开发教程。这个“如果”就是一个流程控制
流程控制可以分为“循环”和“条件”
条件:
  1. int a = 20;
  2. //if语句:如果括号内为true,则运行大括号内语句。对应人类语言:如果...就
  3. if(a==20){
  4.   a=10; //因为a确实等于20,因此此处会被执行,a值为10;
  5. }

  6. //if...else语句:如果括号内为true,则执行大括号内语句,否则执行else后的大括号语句。对应人类语言:如果...就...否则...就...
  7. if(a==20){
  8. a=10; //因为上面a被赋值为10了,所以这里的代码不会被执行,因为a不等于20
  9. }else{
  10.   a=15; //因为a==20为false,故此处会被执行,a值为15
  11. }

  12. //if...else if...else语句:对应人类语言:如果,否则如果,否则如果,否则
  13. if(a==1){
  14.   //此处代码块不会被执行,因为a为15,不等于1
  15. }else if(a==2){
  16.   //此处代码块不会被执行,因为a为15,不等于2
  17. }else if(a==15){
  18.   //此处代码块会被执行,因为a确实等于15
  19. }else{
  20.   //此处代码块不会被执行,因为a不是一个即不等于1,又不等于2,又不等于15的其他数
  21. }
  22. //注意,最后面的else不是必须的,如果你不需要否则的话;else if可以无限套娃,写一堆else if.

  23. //新活:套娃
  24. int num1 = 1;
  25. int num2 = 2;
  26. if(num1==1){
  27. if(num2==2){
  28.   //即当num1为1且num2为2时执行此处代码
  29.   }
  30. }
  31. //然而以上代码完全可以简化为if(num1==1&&num2==2){}

  32. //事实上你会发现如果要判断一个数是否为指定值,那么用else if会很麻烦,要一直套娃,因此我们可以使用switch语句
  33. //switch...case语句
  34. int number = 200;
  35. switch(number) //这个括号里的值曾经不能是String,但现在可以了
  36. {
  37.   case 10:
  38.     //当number为10时执行此处代码块,此例中不会执行
  39.     break; //必须在每一个case末尾标注break(在接下来的循环流程中,你也可以使用break,意为跳出循环)
  40.   case 20:
  41.     //do something
  42.     break;
  43.   case 200:
  44.     //此处代码会被执行
  45.     break;
  46.   default:
  47.     //default的作用同if...else if..else中的else一样,同时也不是必要的
复制代码

循环:
  1. int a = 10;
  2. //while
  3. while(a<10){
  4.   a++; //while循环,当括号内boolean表达式被满足时便开始循环,直到不满足表达式
  5. }
  6. while(true){
  7.   //while true会使一个循环一直持续下去,不会停止(除非在循环中break)
  8. }

  9. //do...while
  10. do{
  11. a++;//于上面不同的是,do...while会先执行一次循环体内的代码,然后再按照while的表达式判断循环(也就是说,do while中代码至少会被执行一次)
  12. }while(a<10);

  13. int b = 1;
  14. //for
  15. for(int i=1;i<10;i++){//千万注意,这里是两个分号,不是逗号
  16.   /* for循环的流程是这样的:
  17.   首先,int i=1是初始化,初始化一个值用来计数(当然,在循环体(即,for下面大括号里的那些代码)中也可被调用),此处初始化了一个值为1,名为i的int值
  18.   然后,i<10是判断表达式,当此处判断满足(即,为true)时,执行循环体,否则跳出循环
  19.   每一次执行完循环体后,调用i++对计数的值(别的也行)进行更新
  20.   直至不满足表达式,跳出循环
  21.   因此,上面的for意为,一个数为i,如果i<10循环一次,每次循环完令i加1
  22. */
  23. }
  24. for(;;){
  25.   //同while(true)
  26. }
  27. //foreach(增强式for循环)略,用到List,Map,数组的时候再讲
复制代码

continue和break关键字
  有时候,我们可能需要提前跳出循环,这时,我们可以使用break和continue关键词(所以他俩只能用在循环和switch语句里头用)
  break代表跳出循环:遇到break时,直接跳出整个循环体,忽略循环体内,break下方的代码
  1. int a =1;
  2. //以下while代码效果同上方的那个for循环代码
  3. while(true){
  4.   if(a>=10);{
  5.     break;
  6. }
  7.   a++;
  8. }
复制代码

  continue则不一样,他代表跳过当前循环:遇到continue时,跳过本次循环,跳过循环体内的其他代码,然后进入下一次循环
为什么我们要在case下面用break?
  如果你break,那么执行完这个case后,会继续检索下面的case(包括default),这不是我们需要的(在本例中没啥用,但如果是判断a是否大于指定数呢?)

BukkitAPI:
  我们已经提了很久API这个玩意,但是API到底是啥?
  API意为“应用程序接口”,是应用程序留给开发者对其应用程序进行拓展的便捷工具。对于我们来说BukkitAPI就是Bukkit给一个封闭箱子留的一个开口,籍此开口,我们可以进入到服务端的内部,对服务器进行高级的修改。
  在Java中,为了了解API,我们可以查询“Javadoc”,Javadoc是由Java为程序自动生成的注释文档,写明了应用开发者的API参数用途等
BukkitAPI(英文原版): https://hub.spigotmc.org/javadocs/bukkit/index.html?overview-summary.html
BukkitAPI(第三方汉化版): https://bukkit.windit.net/javadoc/
  为了确保满足大部分新手理解BukkitAPI,在下面的实战中,我们会选择第三方汉化版的BukkitAPI

BukkitAPI中的监听器:
  监听器即Listener,他可以对一些特定的事件(即,Event)进行监听,对事件进行处理(如,玩家加入服务器事件,PlayerJoinEvent)
  1. //一个玩家加入事件监听器类的结构
  2. package cn.lingyuncraft.hellominecraftplugin;

  3. import org.bukkit.event.EventHandler;
  4. import org.bukkit.event.player.PlayerJoinEvent;

  5. public class Listener implements org.bukkit.event.Listener {
  6.     @EventHandler
  7.     public void onPlayerJoin(PlayerJoinEvent e){
  8.             }
  9. }
复制代码

  在Bukkit中,只有同时满足以下三步,才能成功的注册监听器:
    1.监听器方法所在类必须实现(implements)org.bukkit.event.Listener接口
    2.监听器方法必须具有@org.bukkit.event.EventHandler注解
    3.必须使用Bukkit.getPluginManager().registerEvents(Listener listener,Plugin plugin);注册监听器类
  Tips:对于implements,你可以近似理解为他是让一个类实现了一个抽象的,没有意义的,只有要求的“类”的所有要求,因此它也就变成了这个类的一种

实战:当玩家shaokeyibb第三次加入游戏的时候给他op(什么鬼)
BukkitAPI版本:1.15.2(1.13+API改动很大,请以自己版本的API为准)
1.首先,我们要进行数据存储,这样才有可能为“第三次”计数,因为只需要为固定数量的玩家记一个整数,因此我们选择使用静态的int值来存储玩家进服次数。
  1. public static int count = 0; //初始化int值
复制代码
2.然后,我们需要编写监听器,前往Javadoc,在概览界面下,我们可以看到org.bukkit.event包存储了各种各样的事件监听器

其中,我们可以看到org.bukkit.event.player存储的是与玩家相关的事件
打开,我们可以发现“PlayerJoinEvent"代表着玩家进入服务器事件,这正是我们所需要的

打开,我们可以从“方法概要”看到这个事件和其所继承(extend)于其父监听器对象中的方法

还记得吗,我们想要做的应当是:判定进服的玩家的ID是否为shaokeyibb,是的话就+1,当为3时给他OP.
所以我们可以发现PlayerJoinEvent继承了来自PlayerEvent(代表所有和玩家有关系的事件)的getPlayer方法
可以看到,这个方**返回一个Player对象
但是我们不能把对象和一个玩家ID(即,String字符串)直接对比,我们得想办法获取这个Player对象的玩家ID?
点击Player,我们可以查询到Player类包含的所有方法,如没有static,他们都是非静态的
经过一番查阅,我们找到了getDisplayName()方法


但根据描述,返回的玩家ID可能会包含有颜色代码什么的,这很显然不安全,所以你应该使用继承于HumanEntity的getName()方法
然后,我们得知道怎么给玩家Op
于是我们找到了继承于ServerOperator类的setOp(boolean value)方法


3.东西都找齐了,那我们就可以开始写代码了!
Listener类
  1. package cn.lingyuncraft.hellominecraftplugin;

  2. import org.bukkit.entity.Player;
  3. import org.bukkit.event.EventHandler;
  4. import org.bukkit.event.player.PlayerJoinEvent;

  5. public class Listener implements org.bukkit.event.Listener {

  6.     private static int count = 0;

  7.     @EventHandler
  8.     public void onPlayerJoin(PlayerJoinEvent e){
  9.         Player player = e.getPlayer();
  10.         if(player.getName().equals("shaokeyibb")){
  11.             count++;
  12.         }
  13.         if (count==3){
  14.             player.setOp(true);
  15.         }
  16.     }
  17. }

复制代码

插件主类
  1. package cn.lingyuncraft.hellominecraftplugin;

  2. import org.bukkit.Bukkit;
  3. import org.bukkit.plugin.java.JavaPlugin;

  4. public final class Hellominecraftplugin extends JavaPlugin {

  5.     @Override
  6.     public void onEnable() {
  7.         // Plugin startup logic
  8.         Bukkit.getPluginManager().registerEvents(new Listener(),this);
  9.     }

  10.     @Override
  11.     public void onDisable() {
  12.         // Plugin shutdown logic
  13.     }
  14. }


复制代码
运行maven install编译插件,安装到服务器内,即可看到效果
Q&A
1.count变量我能写到别的地方吗?
  可以,本例中,count变量因为只在Listener类中使用因此是private的,你可以在插件主类上声明,但这样就需要设置为protected或者public;注意不要把变量声明到onPlayerJoin方法中,这会使每次触发监听器时都将count设置为0.

2.Bukkit.getPluginManager().registerEvents(new Listener(),this);是怎么回事?
  Bukkit.getPluginManager().registerEvents(Listener listener,Plugin plugin);用来注册监听器对象,使该类中的监听器真正有效被调用(没错,被调用,我们写方法,触发事件时服务器调用我们的方法).传入的两个参数分别是监听器对象和插件对象.
  那为什么本例中传入了new Listener()和this,而不是new Listener()和new 插件主类名()?
  我们需要传入一个Listener对象,但很显然这个对象未被实例化过,所以这里我们应该new一个出来传入在Bukkit中,但是插件主类对象只能实例化一个,而这一个已经在插件开启的时候由服务器实例化过了,我们不能实例化两次主类对象,因此我们在主类,使用this关键字表示主类对象。
  我可以在别的类获取主类对象实例吗?
  当然可以,你需要在主类声明一个静态的主类对象类型的变量(没有赋值,所以值为null,还不能用),然后在插件开启(即onEnable方法)时将this赋予给这个变量,然后写一个静态的Getter来获取这个实例。此后,你便可以使用这个Getter当作在主类的那个this用了。

作业:
1.尝试给上面的插件加一个当玩家得到op时发送消息的功能

2.尝试获取主类实例

这个帖子内容量很大,写了我一整个下午,所以大家一定要评分支持啊!(最好是人气


下一章可能会讲:数据存储(数组,List,Map),导入其他插件依赖(pom.xml),forEach


下一章(NEW!):https://www.mcbbs.net/forum.php?mod=viewthread&tid=1070801
↑Markdown排版警告

评分

参与人数 21人气 +32金粒 +110收起 理由
981867644+ 2辛苦了
1597918756+ 2高呼666!
ESs4Cg6M+ 2+ 20高呼666!
Kaito_1007+ 1高呼666!
1234qwerasdf@@@+ 1神乎其技!6的飞起!
MATRIX060+ 1催更!!
上杉夏相+ 1催更XD
小天吖~+ 2催更~~~
1357637651+ 2催过
纯小黑同学+ 1MCBBS有你更精彩~
Nice2Mtu+ 3+ 20催更
寒雨_Moro+ 1MCBBS有你更精彩~
ishland+ 1MCBBS有你更精彩~
缘生+ 1+ 30催更永无止境
帕帕武+ 2加油加油
千雪佳奈+ 2+ 10MCBBS有你更精彩~
CyghTor+ 1贺兰加油!
RINNDA+ 2你掉的是这个金人气,还是这个银人气呢.
重载+ 1助攻一下
MiaoLio+ 1????

查看全部评分

帖子永久链接: 

Minecraft中文论坛 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站所有主题由该帖子作者发表,该帖子作者享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖若有内容转载自其它媒体,不代表本站赞同其观点和对其真实性负责
6、若本帖涉及任何版权问题,请立即告知本站,本站将及时予以删除并致以最深的歉意
7、Minecraft(我的世界)中文论坛管理员和版主有权不事先通知发贴者而删除本文

AdvancedMical 当前离线
积分
546
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-4-7
查看详细资料
头像被屏蔽

来自:共享地址共享地址

沙发
发表于 2020-4-17 20:44:24 | 只看该作者
支持贺兰,很好的教程
回复

使用道具 举报

寒雨_Moro 当前离线
积分
1947
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-4-27
查看详细资料

来自:重庆

板凳
发表于 2020-4-17 20:55:43 | 只看该作者
前排围观,很牛逼的教程!
回复

使用道具 举报

CyghTor 当前离线
积分
141
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-2-26
查看详细资料

来自:陕西

地板
发表于 2020-4-17 20:59:30 | 只看该作者
屑贺兰今天整的活挺好,看着没啥要补充的
回复

使用道具 举报

java30433 当前离线
积分
2168
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-4-8
查看详细资料

来自:广西

5#
发表于 2020-4-17 21:03:16 | 只看该作者
为什么不a += 1呢
资瓷贺兰,我还在你服玩过,就是丢马赛克那家伙
回复

使用道具 举报

William_Shi 当前离线
积分
4386
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2017-10-8
查看详细资料

来自:上海

6#
发表于 2020-4-17 21:10:13 | 只看该作者
default:
    //default的作用同if...else if..else中的else一样,同时也不是必要的

我再说一遍
根据阿里巴巴java开发规范华山版
任何switch必须加上default
即使是default块没有任何代码


为什么没人听我???
回复

使用道具 举报

帕帕武 当前离线
积分
8046
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2017-6-24
查看详细资料

来自:重庆

7#
发表于 2020-4-17 21:19:13 | 只看该作者
太详细了!太好了,精华预定
先给你收藏了来
回复

使用道具 举报

kuangshijs 当前离线
积分
2223
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2018-1-28
查看详细资料

来自:广东

8#
发表于 2020-4-17 22:43:53 来自手机 | 只看该作者
感谢大佬的干货(PS: 整挺好)
回复

使用道具 举报

_XuanFsant_ 当前离线
积分
292
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-3-14
查看详细资料

来自:江苏

9#
发表于 2020-4-20 00:19:11 | 只看该作者
来支持啦,这次的内容可以消化好一会
回复

使用道具 举报

_XuanFsant_ 当前离线
积分
292
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-3-14
查看详细资料

来自:江苏

10#
发表于 2020-4-20 01:07:50 | 只看该作者
本帖最后由 _XuanFsant_ 于 2020-4-20 04:32 编辑

顺便一问,大佬可以简单讲解一下Listener类里语句这么写的原因吗,在public void PlayerJoin(PlayerJoinEvent e){Player player = e.getPlayer();这两句中的e和Player player看不懂了(是我没好好听课吗qaq)
回复

使用道具 举报

贺兰兰 当前离线
积分
13350
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-1-18
查看详细资料

来自:陕西

11#
 楼主| 发表于 2020-4-20 22:22:25 来自手机 | 只看该作者
本帖最后由 贺兰星辰 于 2020-4-20 22:24 编辑
_XuanFsant_ 发表于 2020-4-20 01:07
顺便一问,大佬可以简单讲解一下Listener类里语句这么写的原因吗,在public void PlayerJoin(PlayerJoinEve ...


首先提一个小意见,当然无伤大雅,只是一个代码风格问题,就是方法应该使用小驼峰的格式,即首个单词首字母小写,其后每个单词首字母大写,所以你的方法名最好应该写成playerJoin或者onPlayerJoin好看一点。
然后,此处我们声明了一个玩家加入事件PlayerJoinEvent,其本质是一个PlayerJoinEvent对象,当玩家加入服务器一次,服务器就会自动调用一次我们声明的方法(即你的“PlayerJoin”方法,然后我们就可以进行相关操作
还记得上一次讲的吗,方法声明中,括号里代表需要传入的参数名称,等于要求服务器向我们传入一个名为e的PlayerJoinEvent对象,这个对象具体能使用什么方法可以查询bukkit的javadoc
在Player player = e.getPlayer();中,根据PlayerJoinEvent对象的概览,getPlayer()方法可以返回一个Player对象,代表加入服务器的玩家,因此,我们声明了一个叫做player的Player对象,把这个getPlayer()方法返回的Player对象值存到player这个Player对象变量内,以便我们接下来直接使用player这个变量代表加入服务器的玩家,而不用每次都写一个e.getPlayer()(反过来说,如果你不希望存起来,那你也可以每一步需要处理/使用Player对象的时候使用e.getPlayer()方法获取玩家对象

所以说,e就代表了前面的PlayerJoinEvent,Player player中,Player代表声明的变量类型为Player对象,player代表变量名称叫player
回复

使用道具 举报

_XuanFsant_ 当前离线
积分
292
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-3-14
查看详细资料

来自:江苏

12#
发表于 2020-4-20 22:38:20 | 只看该作者
贺兰星辰 发表于 2020-4-20 22:22
首先提一个小意见,当然无伤大雅,只是一个代码风格问题,就是方法应该使用小驼峰的格式,即首个单词首字 ...

理解了!感谢!
回复

使用道具 举报

党靖皓1234 当前离线
积分
1013
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2014-12-18
查看详细资料

来自:河南

13#
发表于 2020-4-22 15:39:44 | 只看该作者
后排表示支持
回复

使用道具 举报

克鲁鲁殿下 当前离线
积分
3730
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2020-2-21
查看详细资料

来自:广东

14#
发表于 2020-5-15 13:14:03 | 只看该作者
过来吃瓜。


虽然我已经往后学了一点点,不过看看贺兰的教程就回想起刚开始苦苦挣扎没人具体讲解的悲催
回复

使用道具 举报

甲甲 当前离线
积分
1955
帖子
主题
精华
贡献
爱心
钻石
人气
下界之星
最后登录
1970-1-1
注册时间
2016-5-8
查看详细资料
头像被屏蔽

来自:江苏

15#
发表于 2020-5-15 23:32:49 | 只看该作者
日常催更XD
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 京公网安备 11010502037624号 | 手机版

GMT+8, 2022-10-16 08:14 , Processed in 0.947868 second(s), Total 28, Slave 27 queries, Release: Build.2022.10.14 1014, Gzip On, Redis On.

"Minecraft"以及"我的世界"为美国微软公司的商标 本站与微软公司没有从属关系

© 2010-2022 我的世界中文论坛 版权所有 本站内原创内容版权属于其原创作者,除作者或版规特别声明外未经许可不得转载