编写我的世界区块加载插件bukkit基础插件发现插件完全不能加载的问题,不知道哪里出错了

当前位置:
插件控制合成 我的世界的插件很好用,那么插件控制怎么合成,怎么取消合成事件呢?感兴趣的来看看小编为大家带来的我的世界插件控制合成和取消合成教程吧。 目地: 用插件添加新的合成 并且限制合成材料必须是用特殊数据值的 因为Bukkit的合成只检测物品ID
编辑:亮亮发布时间: 10:50
本文导航第1页: 插件控制合成
  的插件很好用,那么插件控制怎么合成,怎么取消合成事件呢?感兴趣的来看看小编为大家带来的插件控制合成和取消合成教程吧。
  目地: 用插件添加新的合成 并且限制合成材料必须是用特殊数据值的
  因为Bukkit的合成只检测物品ID不检测物品的数据值
  本教程说明: 类 包 方法
  添加合成:
  方法 Bukkit.addRecipe(Recipe) 可以将一个Recipe进行注册是玩家能在服务器中合成
  注意 这个注册在插件被卸载的时候不会被注销 必须手动注销
  Recipe有3个子类 它们位于 org.bukkit.inventory 下 分别是: FurnaceRecipe 熔炉合成
  ShapedRecipe 有型合成
  ShapelessRecipe 无形合成
  FurnaceRecipe : 通过查询API可知,熔炉的合成在构建的时候使用参数来设定目标物品 &不是本教程重点ShapedRecipe : 在构建的时候通过参数ItemStack设置合成结果
  ShapelessRecipe : 在构建的时候通过参数ItemStack设置合成结果
  ShapedRecipe与ShapelessRecipe 的区别:
  ShapelessRecip 只需要通过 .addIngredient() 来设置原料 无需设置形状
  ShapedRecipe 必须通过 .shape(String[] shape) 来设置形状
  ShapedRecipe sr = new ShapedRecipe(item);
  sr.shape(new String[]{
  &A C&,
  &CBA&,
  那么 这个合成就必须按照这个形状来合成 不需要物品的地方使用空格
  在指定形状后还需要指定每个字符代表的物品 空格不用指定
  通过 .setIngredient(char key, Material ingredient) 来设置每个字符所代表的物品 因为这个方法不能使用ItemStack 所以原料是无数据值的
  sr.setIngredient('A', Material.PAPER);
  sr.setIngredient('B', Material.VINE);
  sr.setIngredient('C', Material.BROWN_MUSHROOM);
  最后将这个合成进行注册就可以使用了
  getServer().addRecipe(sr);
  无形合成例子:
  ShapelessRecipe sr = new ShapelessRecipe(item);
  sr.addIngredient(9, Material.VINE);
  就是这么简单 上面是9个藤蔓合成物品 可以重复调用方法来设置多种物品.
经营许可证:皖ICP备号-1,QQ:1104747 、5633249【教程】【汉化】如何制作CraftBukkit插件 - 基础插件教程【minecraft吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:1,582,370贴子:
【教程】【汉化】如何制作CraftBukkit插件 - 基础插件教程
插件教程原帖地址:**注意:虽然本教程内容不多,但是由于译者时间不多效率较低并且有其他教程与本文关联,因此看到仍是英文的篇章请不要奇怪~**本教程首发位置:。新的汉化内容将在那里更新。
minecraft服务器,企业询价批量采购更优惠,一对一客户经理服务,一站式采购,就在苏宁企业购!minecraft服务器,正品低价,品质保障,一站式本地化采购服务平台,为企业提供多样..
目录? 1 介绍? 2 学习 Javao
2.1 Java 视频教材o
2.2 Java 书面教程? 3 开发环境? 4 开始一个插件项目o
4.1 创建项目o
4.2 查阅 Bukkit APIo
4.3 Bukkit的Java注释文档o
4.4 创建一个包o
4.5 创建插件的类o
4.6 创建 plugin.yml 文件? 5 onEnable() 和 onDisable() 方法o
5.1 onEnable()和onDisable() 的介绍o
5.2 记录信息? 6 监 听器? 7 命令o
7.1 onCommand() 方法§
7.1.1 创建指令o
7.2 将你的指令添加到 Plugin.yml 中o
7.3 控制台指令 和 玩家指令o
7.4 创建单独的 CommandExecutor(命令执行) 类o
7.5 编写安全的 onCommand 方法§
7.5.1 在执行指令前确保发送者为玩家§
7.5.2 检查参数数量§
7.5.3 确保指定的玩家在线? 8 插件配置/设置? 9 权限o
9.1 配置你的权限§
9.1.1 默认权限§
9.1.2 子权限o
9.2 创建属于你自己的权限? 10 调度任务和后台任务? 11 编辑方块? 12 编辑(玩家) 包裹? 13 编辑物品o
13.1 附魔? 14 图, 设置, 列表, 老天!o
14.1 图和使用方法§
14.1.1 定义图§
14.1.2 图的更多创意§
查阅物品ID§
14.1.3 存储/载入图? 15 元数据o
15.1 为什么要用元数据o
15.2 为什么不用元数据o
15.3 使用与配置元数据? 16 数据库o
16.1 SQLiteo
16.2 MySQL?
17 配置你的插件?
18 小技巧o
18.1 点燃玩家o
18.2 杀死玩家o
18.3 创造爆炸o
18.4 让某人从其他人眼中消失o
18.5 玩家点击触发闪电? 19 请求来源? 20 范例与模板
介绍本教程旨在帮助你开始Bukkit插件开发之路。它没法揭示Bukkit所有的可能玩法,只能讲述基础用法的概要。教材从保证你掌握开始,到使用IDE创建工作空间,再到介绍大部分Bukkit插件的必备功能。学习Java本教程需要对Java这门高级编程语言有一定的掌握. 如果你对它一无所知或了解甚少,那你就得看看下面的内容了。他们会帮你不少忙!(很遗憾都是英文的,可能还得翻墙)Java视频教程§
iTechRemix 非常基础的 Bukkit 插件教程,作者:iTechRemix。§
Thenewboston -有很多精彩的视频。§
VideoTutes.com -各方面内容都有。Java书面教程§
Oracle Documentation (目前拥有
2s.com -几乎所有有关Java的内容都在这里§
101 -深入的书面教程开发环境在编写插件(或学习)之前,你需要先建立起一个开发环境,它包括但不仅限于IDE(集成开发环境)。IDE是一个帮助你编译和检测你的插件的软件。Java有三个著名的IDE:Eclipse,,和 IntelliJ IDEA。Eclipse在Bukkit开发者中最受欢迎,而IntelliJ 在各行业领域广泛使用。如果你是Java新手,推荐你使用 Eclipse 作为IDE,因为接下来的教程里都以Eclipse 作为工具。更详细的介绍,请查阅创建你的工作空间
开始一个插件项目创建项目在开始之前,你需要在 Eclipse
里建立你的工作空间和文件。运行 Eclipse ,然后点击 File(文件)& New(新建)& Java Project(Java项目)创建一个新项目:
给你的项目取个名字,然后运行这个新的项目,根据屏幕上的介绍进行配置。左边的Package Explorer(包浏览栏)里会出现一个文件夹,左键点击它旁边的小箭头会显示你的项目的内容。查阅Bukkit API在编写插件前,你需要向你的项目里以外部JAR的形式添加Bukkit API。你也可以添加其他你可能会用到的API。最新版已编译的Bukkit API 可在这里找到: Bukkit API - 开发快照点击左边Package Explorer(包浏览栏)内有着你的项目名称的文件夹并选择 Properties(选项). 在左边的方框内选择Java Build Path(Java生成路径) ,之后里面的内容就会变化。点击 Add External JARs(添加外部JAR) 并载入你下载的 Bukkit API.
Bukkit的Java注释文档如果你已经有Eclipse和Java的使用经验,你就会知道当鼠标放在类或者方法上面时,一个***的包含其说明文档的小盒子就会出现。这就是Javadoc(Java文档注释),在Oracle 官网 上也可以查阅到其资料。Bukkit也有包含了每个方法和类的有用描述的注释文档,你可以在这里查看它。为了让Ecilpse能载入注释信息以便我们能方便的查看Bukkit中类和方法的注释,你需要首先左键点击项目浏览器中"Referenced Libraries(参考库)"内的Bukkit jar,点击"Properties(选项)",选择左边的"Javadoc Location(Java注释文档位置)" ,然后复制到"Javadoc URL(Java注释文档地址)"中。效果如下:
点击validate(生效),然后点击OK。这样 Bukkit的Java注释文档就连接上了Bukkit源,在 Eclipse 内就能方便的查看注释了。创建一个包现在你需要创建一个包来储存所有我们会用到的Java类文件。右键点击src文件夹,选择New(新建) & Package(包):命名规则如下:§
如果你有一个域名,包的名称就是域名反过来。§
例如:i-am-a-bukkit-developer.com 那你的包名就会是com.i_am_a_bukkit_developer 源§
不要使用你不拥有的域名§
没有域名?看看这些:1.
在github 或 sourceforge 这类存放源文件的网站上注册一个帐号§
对github,根据 这里面 的教材注册就能得到一个子域名,这样你的包名就是com.github.&username&2.
使用你的邮箱,如:&username&@gmail.com -& com.gmail.&username&3.
这是最不推荐的方法:使用任意独有的包名。你的包名绝对不能是:§
org.bukkit§
net.bukkit§
com.bukkit§
net.minecraft下一步就是加上插件名称。让我们再以github为例:如果你的插件名字叫"TestPlugin",你的完整包名就是 "com.github.&username&.testplugin"。
创建插件的类创建完项目或,我们就可以添加类并编写插件了。插件的主类(main class)必须要继承 JavaPlugin 类。你的插件里需要有且只能有一个类直接或间接继承 JavaPlugin 类。强烈建议先创建你的主类,并将其命名与插件名称一致。右键点击你之前创建的包,选择 New(新建)& Class(类)。你的类格式应如下:package {$TopLevelDomain}.{$Domain}.{$PluginName};import org.bukkit.plugin.java.JavaPpublic final class {$PluginName} extends JavaPlugin {}创建plugin.yml你现在已经创建了你的项目和主文件。为了让bukkit能看到它,我们需要添加 plugin.yml 文件。它包含了插件的必备信息,离开它插件就无法工作。这次我们要右键点击项目文件夹,选择 New(新建)& File(文件),命名为 "plugin.yml"后点击确定。 Eclipse 会在默认文档编辑器中打开一个空白的 plugin.yml 文件。 (提示:如果你想让你的工作空间井井有条,关闭文本编辑器并把plugin.yml拖动到主工作空间右边,就能在eclipse中直接编辑了。) 该文件中有三条信息必不可少:插件名称,插件主文件的完全限定名称,和插件的版本。最简单的 plugin.yml 文件如下图所示:name:{$PluginName}main:{$PackageName}.{$MainClass}version:{$VersionNumber}注意:插件的包的名字常常会包含插件的名字,因此在第二行末尾看到 &pluginname&.&pluginname& 字样时不必感到惊讶。注意:你的主类是否要与插件名称一致取决于你之前的命名,注意其区分大小写。现在你的插件可以被 Bukkit载入了,并且也会被记录下来。但它什么也干不了!
onEnable()和 onDisable() 方法当插件被启用和禁用时分别会调用这两个方法。默认情况下,插件被载入时会启用自身,这样你就能注册你的事件,并在这输出一些调试信息。 onEnable() 方法会在插件启用时被调用,其中应该含有建立插件的内容。 onDisable() 方法会在插件启用时被调用,其中应该含有清除插件和相关状态的内容。有些插件会重写 onLoad() 方法,以在载入时发挥作用。onEnable()和onDisable()方法的介绍在上文中创建的主类内创建 onEnable() 和 onDisable() 方法。形式如下:package {$TopLevelDomain}.{$Domain}.{$PluginName};import org.bukkit.plugin.java.JavaPpublic final class {$PluginName} extends JavaPlugin {
public void onEnable(){
//在这里添加插件被启用时需要做的事情
public void onDisable() {
//在这里添加插件被禁用时需要做的事情
}}现在这两个方法被创建了,但是什么都没干。记录信息插件能通过正确调用其记录器方法来实现向控制台和服务器日志发送信息。我们需要调用 getLogger() 方法来触发与插件关联的记录器。然后我们就能开始记录了。当 onEnable() 方法被调用时就会开始记录。将以下内容加入到 theonEnable() 方法中就能实现我们想干的事情:getLogger().info("onEnable被调用!");你还可以对 onDisable()做相同的工作。记得确保信息已经改变。现在你的主类应该看起来是这个样子:package {$TopLevelDomain}.{$Domain}.{$PluginName};import java.util.logging.Limport org.bukkit.plugin.java.JavaPpublic final class {$PluginName} extends JavaPlugin {
public void onEnable(){
getLogger().info("onEnable被调用!");
public void onDisable(){
getLogger().info("onDisable被调用!");
}}***器*** 器是使用了org.bukkit.event.Listener接口,并且有回应相应事件的方法的类。更多细节,请查阅:事件的API 资料指令onCommand()方法现在你已经能注册事件,并在他们发生的时候做点小动作。但如果你只想让事件被指令激发呢?看看 onCommand 事件吧。当有人输入指令的时候,就会调用 onCommand 方法。现在什么事情也不会发生,因为我们没有编写出任何行为。避免使用与Bukkit自带命令相同名称的指令,同时也要好好想想你的指令是否足够独特。例如,"give" 指令在许多插件中都有出现,如果你想编写另外一个"give" 指令,你的插件就会和其他插件不兼容。你需要在插件的 plugin.yml 文件里注册你的指令,不然它们无法触发这个方法。
热销好货「天猫618」大牌尖货,限量特惠折上折,购物满就返红包,多买多得,不可错过!「天猫618」理想生活狂欢季,&嗨&购大品牌!
onCommand 方法需要有至少一个布尔型返回值----不论具体值。如果返回值为真,就不会有任何明显的效果;而如果返回值为假,插件就会向用户显示出自plugin.yml中的命令使用方法的信息。使用 onCommand 方法时需要四个参数:§
CommandSendersender - 命令发送者§
Commandcmd - 具体命令§
StringcommandLabel - 所使用的命令缩写§
String[]args - 一组附加参数,例如:输入 /hello abc def ,则 abc 会被保存到 args[0] 中,def 保存到 args[1] 中创建指令
public boolean onCommand(CommandSender sender,Command cmd, String label, String[] args){
if(cmd.getName().equalsIgnoreCase("basic")){ //如果玩家输入/basic就会发生以下事情...
return true;
} //如果事件发生就会返回true
//没发生就会返回false
return false;
}编辑 onCommand 函数时,在函数末尾返回 false 值是一个好的举措。这样的话如果某一步出错了就能出现帮助信息。当返回一个值的时候函数就会结束,因此之后的语句都不会再执行,除非返回指令被包含在一个 if 之类的复合结构中。语句 .equalsIgnoreCase("basic") 的意思是忽略大小写,如将"BAsIc" 和 "BasiC" 都视为basic而执行指令。向Plugin.yml加入我们的指令你需要把你的指令添加到 plugin.yml 文件中。在 plugin.yml 的末尾处加入以下内容:commands:
description:这是一个测试用指令。
usage:/&指令& [玩家]
permission:&插件名称&.basic
permission-message:你没有&permission& 权限。§
basic - 指令名称。§
description - 指令描述。§
usage - 当 onCommand
方法返回false 时会出现的帮助信息。请描述清楚,以便其他人了解该指令的功能及使用方法。§
permission - 用于一些权限插件,以决定将哪些指令展示给玩家。§
permission-message - 当玩家输入指令却没有权限时就会得到该提示注意:yml文件中以 2 个空格代替制表符(即/tab),注意区分以避免问题。控制台指令和玩家指令你可能已经注意到上文中的 CommandSender sender 这一参数。 CommandSender是Bukkit的一个借口,它有两个有用的(对插件开发者而言)子类: Player 和 ConsoleCommandSender。当你在编写插件时,保证能从控制台运行的指令能同时在玩家身上切实工作,以及玩家专用的指令仅能被登陆后的玩家使用,十分重要。有些插件仅简单地判断发送者是不是玩家(用于有人想在控制台上运行指令的情况),即使那些指令在控制台上一样能正常运行(比如改变服务器里的天气)。一种判断的方法是:
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (cmd.getName().equalsIgnoreCase("basic")){ //如果玩家输入/basic就会发生以下事情...
//做某事...
return true;
} else if (cmd.getName().equalsIgnoreCase("basic2")){
if (!(sender instanceof Player)) {
sender.sendMessage("该指令仅能由玩家执行。");
Playerplayer =(Player)
return true;
return false;}在这个例子中, basic 命令可以被任何人使用----不论是登陆的玩家还是控制台上的管理员。但 basic2 只能由玩家使用。通常来说,命令应该都能被两者正常使用。仅能被玩家使用的命令可以使用上文所述检查 CommandSender 是否为玩家的机制来进行校验。这类指令通常只能对玩家生效,如传送玩家的指令,给予某玩家物品的指令等。如果你想让它功能更强大,可以加入对命令参数的额外检测,例如:在给定玩家名称的情况下也可以从控制台使用传送指令。使用单独的CommandExecutor(命令执行)类上文的范例仅在插件的主类中使用了 onCommand() 方法。对于小型插件来说问题不大,但如果你编写的是更具拓展性的插件,将 onCommand() 方法放到独立的类中是个好主意。实现起来并不困难:§
在插件的包中插件一个新的类,取个 MyPluginCommandExecutor 之类的名称(你不会真的把MyPlugin 保留下来吧?)。该类必须使用BukkitCommandExecutor 接口。§
在 onEnable() 方法中,需要创建一个你的新命令执行类的实例并调用它,如 getCommand("basic").setExecutor(myExecutor);,其中 ”basic” 是我们的指令的名称。 myExecutor 就是我们创建的实例。空口无凭:MyPlugin.java (the main plugin class):@Overridepublic void onEnable() {
//如果你没在plugin.yml
中定义指令,就会抛出一个NullPointException的错误!
getCommand("basic").setExecutor(new MyPluginCommandExecutor(this));
// ...}MyPluginCommandExecutor.java:public class MyPluginCommandExecutor implements CommandExecutor {
private MyP //指向你的主类,如果你不需要主类中的方法可以不写
public MyPluginCommandExecutor(MyPlugin plugin) {
this.plugin =
public boolean onCommand(CommandSendersender, Command cmd, String label, String[] args) {
//和前面一样的内容...
}}注意到我们从主插件文件中传递了一个实例到 MyPluginCommandExecutor 中。这能让我们更方便地访问主类中的方法。通过以上方法,我们能更好的组织起我们的代码----如果主 onCommand() 方法太长且复杂,我们就能将其分为多个子方法而不用担心撕裂主类。注意:如果你的插件里有很多指令,你需要为每个指令编写独立的命令执行方法。编写安全的onCommand方法编写 onCommand 方法时,要考虑到方方面面。例如:在执行指令前确保发送者为玩家public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
if (sender instanceof Player) {
Player player = (Player)
//执行事件
sender.sendMessage("该指令只能由玩家执行!");
return false;
//执行事件
return false;}检查参数数量不能总指望指令发送者能正确的使用指令。public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
if (args.length & 4) {
sender.sendMessage("参数过多!");
return false;
if (args.length & 2) {
sender.sendMessage("参数过少!");
return false;
}}确保指定玩家在线有时候你想取得某玩家输入的另一名玩家的名称。记得确保那名玩家在线!public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
Playertarget = (Bukkit.getServer().getPlayer(args[0]));
if (target == null) {
sender.sendMessage(args[0] + " 未在线!");
return false;
return false;}如果你需要对离线玩家进行操作, OfflinePlayer 类能给你提供基本操作方法。
插件配置/设置BukkitAPI 为插件提供了一套方便的用户配置文件管理方案,同时其也可作为一种简易的数据储存方式。请查阅:配置文件 API 资料权限自从新版本Bukkit API 提供了对权限的支持,一切变得再简单不过。想确认某玩家是否有指定权限,只需:if(player.hasPermission("some.pointless.permission")){
//执行事件}else{
//执行其他事件}你也可以用以下函数来判断某权限是否存在 (不存在等价于 Java 中的 null) :boolean isPermissionSet(String name)你可能对这里没有用户组的设定感到疑惑。***是:(译者注:Bukkit开发组认为)它们没有存在价值。目前用户组的主要用途之一是添加聊天信息的格式,不过这通过权限系统同样可以做到。在你的聊天插件的配置文件内,你可以定义权限和前缀之间的联系,比如: "someChat.prefix.admin" 权限的效果是前缀: [Admin] 。拥有该权限的玩家在发言时名称前会自动添加上前缀 [Admin] 。另一个常见用途是给某一用户组的所有玩家发送信息,不过这同样能通过权限系统完成:for(Playerplayer: getServer().getOnlinePlayers()) {
if(player.hasPermission("send.recieve.message")){
player.sendMessage("你收到了一条信息");
}}最后你可能会问,没有用户组系统我怎么设置和管理玩家的权限呢?由于Bukkit API 自己没有提供用户组功能,你需要***一个权限提供插件----如permissionsBukkit ----来管理你的用户组。 注意:该API仅仅提供接口,而没有具体内容。配置你的权限如果你想更细致的控制权限,比如设置默认值或者子权限,你需要对 plugin.yml 进行更深入的研究了。可选,但我们强力推荐。下面是一个范例文件:permissions:
doorman.*:
description:拥有 全部 doorman 指令的权限
doorman.kick:true
doorman.ban:true
doorman.knock:true
doorman.denied:false
doorman.kick:
description:允许你踢出玩家
default:op
doorman.ban:
description:允许你封禁玩家
default:op
doorman.knock:
description:敲门!
default:true
doorman.denied:
description:不让该玩家进门现在,你插件中的所有权限都被定义为了权限节点上的子节点。每个权限都可以有自己的描述,默认值,和子权限。默认值如果某玩家没有指定权限,hasPermission 就会返回false 值。在plugin.yml 里你可以把默认值设置为以下选项之一:§
true - 默认拥有权限§
false - 默认不拥有权限.§
op - 如果玩家是OP就拥有权限§
not op - 如果玩家不是OP就拥有权限
子权限你以前可能仅能用 * 来获取所有的权限。不过在Bukkit API 的帮助下,你可以添加和使用灵活性更高的子权限了。范例如下:permissions:
doorman.*:
description:拥有 全部 doorman 指令的权限
doorman.kick:true
doorman.ban:true
doorman.knock:true
doorman.denied:false在这里 doorman.* 拥有多个子权限。当 whendoorman.* 被设置为真时,子权限就会被设置为 plugin.yml 中的默认值。如果howeverdoorman.* 被设置为假,子权限的值就会反转。设置自己的权限如果你想开发自己的权限插件(真正能设置权限),那就看看 开发一个权限插件这篇教程吧。调度任务和后台任务目前Minecraft的服务端将几乎所有程序集中在单个线程上,因此游戏里的每个独立任务都需要控制在非常短的时间内。插件中的一段未正确配置的复杂代码很可能导致服务端的巨大延迟。幸运的是,Bukkit支持插件中的调度代码。你可以提交一个可运行任务以在未来运行,或进行循环,或创建一个独立的可执行较长任务的和服务端程序平行的线程。调度器编程 教程介绍了调度器的概念,也告诉我们如果使用它来调度同步任务并剔除Bukkit中的异步任务。编辑方块创建方块的最简单方法就是取得一个现成的方块并编辑它。例如,如果你想编辑你头顶上方五格高处的方块,你需要先取得它。例如,作为对玩家移动事件的响应:public void onPlayerMove(PlayerMoveEvent evt) {
Locationloc = evt.getPlayer().getLocation();
Worldw = loc.getWorld();
loc.setY(loc.getY() + 5);
Blockb = w.getBlockAt(loc);
b.setTypeId(1);}当playerMove() 事件被触发时,玩家头上五格高处的方块就会变成石头。首先我们取得了玩家的位置,然后从位置中得到了世界名称。然后我们把坐标的高度加了5,这样我们就得到了目标的坐标和世界----我们能在其中创建方块变量以将方块放在指定位置。我们通过使用 w.getBlockAt(loc); 提供的坐标和世界来实现。最后,我们把方块放在了指定位置并改变了它的ID或方块数据----如果我们想要的话。方块数据大小为一比特,因此如果你想设置方块数据,你需要将变量类型转换为比特。例如,在这段代码之外加上 b.setData((byte)3); 。通过使用数学公式,你可以程序化地创建建筑或者独立方块,比如一个立方体:public void generateCube(Locationloc, int length){
//公共可见方法generateCube(),含有2个参数point和location
Worldworld = loc.getWorld();
int x_start = loc.getBlockX();
//将给定坐标赋值到起始点坐标
int y_start = loc.getBlockY();
int z_start = loc.getBlockZ();
/*注意:使用getBlockX()而不是getX()方法是因为前者返回int型变量,这就避免了类型转换(int)loc.getX() */
int x_length = x_start +
//设置了每个维度单独的长度...应该会更清晰易懂
int y_length = y_start +
int z_length = z_start +
for(int x_operate = x_ x_operate &= x_x_operate++){
for(int y_operate = y_ y_operate &= y_ y_operate++){
for(int z_operate = z_ z_operate &= z_z_operate++){//三重嵌套循环,想必大家都看得懂吧。原文太罗嗦,懒得翻译了~。~
//取得当前坐标上的方块
BlockblockToChange = world.getBlockAt(x_operate,y_operate,z_operate);
blockToChange.setTypeId(34);
//将方块ID设置为34
}}以上方法会用提供的长度和起始点位置创建出一个3D立方体。如果想删除方块,只需把 ID 设置为 0 (空气)。编辑 (玩家) 包裹这部分内容主要讲述了对玩家包裹的编辑,不过其对箱子的编辑同样适用,只要你找到了取得箱子包裹的方法 :P 。下面是一个编辑包裹的范例:public void onPlayerJoin(PlayerJoinEvent evt) {
Playerplayer = evt.getPlayer(); //进入游戏的玩家
PlayerInventory inventory = player.getInventory(); //玩家的包裹
ItemStackitemstack = new ItemStack(Material.DIAMOND, 64); //一组钻石
if (inventory.contains(itemstack)) {
inventory.addItem(itemstack); //向玩家包裹里添加一组钻石
player.sendMessage("欢迎!你看起来很很很很很很很很有钱的样子,所以我们决定再给你一组钻石!");
}}在onPlayerJoin 方法中,我们先创建了一些变量来减轻我们的工作:player, inventory 和 itemstack。 Inventory 就是玩家的包裹,而 itemstack 就是一整组的钻石。之后我们坚持了玩家的包裹看看是否已经有一组钻石,如果是,我们就通过inventory.addItem(itemstack) 方法再给他一组,并向他发送一条信息。编辑包裹并不困难,如果我们愿意也可以把 inventory.addItem(itemstack) 替换成inventory.remove(itemstack) 并稍微修改下信息来压榨玩家。希望对你有帮助!编辑物品在代码中处理物品时,你需要用ItemStack类来查找和设置物品的信息。附魔为了给物品附魔,你需要首先了解 物品代码 和 效果ID 。附魔类自身无法被实例化(newEnchantment() 不管用) ,因为他们是抽象的。因此你需要使用EnchantmentWrapper 类。一般情况下你只能给武器装备进行附魔,不给NBT标签的使用使得我们已经能做到给任意物品附魔----不过这超出我们的讨论范畴了。int itemCode = 280;
//你想要附魔的物品的IDint effectId = 20;
//你想要附魔的属性的IDint enchantmentLevel = 100;ItemStack myItem = new ItemStack(itemCode);
//新的物品类EnchantmentmyEnchantment = new EnchantmentWrapper(effectId);
//新附魔类myItem.addEnchantment(myEnchantment,enchantmentLevel);
//进行附魔
图,设置,列表,老天!Besides theMap/HashMapclasses, Java offers many other data structures. They offer thesedifferentclasses because there are times when a Map is not the mostappropriate. Here'sa separate page for discussing Java data structureclasses in more detail.哈希图和使用方法When making a pluginyouwill get to a point where just using single variables to state an eventhashappened or a condition has been met will be insufficient, due to more thanoneplayer performing that action/event.This was the problem Ihadwith one of my old plugins, Zones, now improved and re-named to Regions. Iwasgetting most of these errors because I didn't consider how the pluginwouldbehave on an actual server with more than one on at any given time. I wasusinga single boolean variable to check whether players were in the region ornotand obviously this wouldn't work as the values for each individual playerneedto be separate. So if one player was in a region and one was out thevariablewould constantly be changing which could/would/did cause numerouserrors.A HashMap is anexcellentway of doing this. A HashMap is a way of mapping/assigning a value toa key.You could set up the HashMap so that the key is a player and the valuecould beanything you want, however the useful things with HashMaps is that onekey canonly contain one value and there can be no duplicate keys. So say forexample Iput "adam" as the key and assigned a value of "a"to it.That would work as intended, but then say afterwards I wanted to assignthevalue of "b" to key "adam" I would be able to and would getnoerrors but the value of "a" assigned to key "adam" intheHashMap would be overwritten because HashMaps cannot contain duplicatevalues.定义哈希图public Map&Key, DataType& HashMapName = new HashMap&Key, Datatype&(); //Example syntax//ExampleDeclarationpublic Map&Player, Boolean& pluginEnabled = new HashMap&Player, Boolean&();public Map&Player, Boolean& isGodMode = new HashMap&Player, Boolean&();Keep that code inmindbecause we will be using it for the rest of the tutorial on HashMaps. So,forexample lets create a simple function which will toggle whether the pluginhasbeen enabled or not. Firstly, inside your on command function which Iexplainedearlier you will need to create a function to send the player name tothefunction and adjust the players state accordingly.So inside on command you'llneedthis, the function name can be different but for the sake of simplicityit'sbest if you keep it the same.
Player player = (Player)togglePluginState(player);This code above willcast thevalue of sender to player and pass that argument to thefunctiontogglePluginState(). But now we need to create ourtogglePluginState()function.public void togglePluginState(Player player){
if(pluginEnabled.containsKey(player)){
if(pluginEnabled.get(player)){
pluginEnabled.put(player, false);
player.sendMessage("Plugin disabled");
pluginEnabled.put(player, true);
player.sendMessage("Plugin enabled");
pluginEnabled.put(player, true); //If you want plugin enabled by defaultchange this valueto false.
player.sendMessage("Plugin enabled");
}}Now, what this codeisdoing is checking if the HashMap first contains the key player, so if ithasbeen put into the HashMap, if it is then we check the value of the HashMapkeyby get(player); if this is true then set value to false and send the playeramessage, else if the value is false then do the opposite, set the value totrueand send a message again. But if the HashMap does not contain the keyplayerthen we can assume that this is their first run/use so we change thedefaultvalue and add the player to the HashMap.哈希图的更多创意A HashMap (or reallyanykind of Map in Java) is an association. It allows quick and efficient lookupofsome sort ofvalue, given a unique key. Anywhere this happensin your code, a Map may be your solution.Here are a few otherideaswhich are ideally suited to using Maps. As you will see, it doesn't haveto bedata that you store per player, but can be any kind of data that needs tobe"translated" from one form to another.查阅物品IDpublic Map&String, Integer& wool_colors = new HashMap&String, Integer&();// Runthis onplugin startup (ideally reading from a file instead of copied out rowby row):wool_colors.put("orange",1);wool_colors.put("magenta",2);wool_colors.put("lightblue", 3);
..wool_colors.put("black",15);// Runthis inresponse to user commands - turn "green" into 13int datavalue = 0;if (wool_colors.containsKey(argument)) {
datavalue =wool_colors.get(argument);} else {
try { datavalue = Integer.parseInt(argument); }
catch (Exception e) { ; }}存储/载入哈希图Once you know how toworkwith HashMaps, you probably want to know how to save and load the HashMapdata.Saving and loading HashMap data is appropriate if§
you don'twant anadministrator to edit the data manually§
you needto save data inbinary format (too complex to organize for YAML)§
you wantto avoid parsingblock names and/or other objects from freeform textThis is very simple wayhowto save any HashMap. You can replace HashMap&String, Integer& withanytype of HashMap you want. Let's continue using the"pluginEnabled"HashMap defined from the previous tutorial. This codesaves the given HashMapto the file with given path.public void save(HashMap&String, Integer& map, String path){
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
oos.writeObject(map);
oos.flush();
oos.close();
//Handle I/O exceptions
catch(Exception e)
e.printStackTrace();
}}// ...save(pluginEnabled,getDataFolder()+ File.separator + "example.bin");You can see it'sreallyeasy. Loading works very very similar but we use ObjectInputStreaminstead ofObjectOutputStream ,FileInputStream instead ofFileOutputStream,readObject()instead of writeObject() and we return theHashMap.public HashMap&String, Integer& load(String path){
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
Object result = ois.readObject();
//you can feel free to cast result toHashMap&String, Integer& if youknow there's that HashMap in the file
return (HashMap&String,Integer&)
catch(Exception e)
e.printStackTrace();
}}// ...String path =getDataFolder() + File.separator + "example.bin";File file = new File(path);
if(file.exists()) // checkif file exists before loading to avoid errors!
pluginEnabled
= load(path);You can usethis"API" for saving/loading HashMaps, ArrayLists, Blocks, Players...andall O) . Please credit Tomsik68(the author of this) ifyouuse this in your plugin/other project./** SLAPI =Saving/LoadingAPI* API for Savingand Loading Objects.* You can usethis API in your projects, butplease credit the original author of it.* @authorTomsik68&&*/public class SLAPI{
public static &T extends Object& void save(T obj,Stringpath) throws Exception
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
oos.writeObject(obj);
oos.flush();
oos.close();
public static &T extends Object& T load(String path) throws Exception
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
Tresult = (T)ois.readObject();
ois.close();
}}Example implementationofthis API: I'm skipping somepart of code in this sourcepublic class Example extends JavaPlugin {
private ArrayList&Object& list = new ArrayList&Object&();
public void onEnable()
list= SLAPI.load("example.bin");
}catch(Exception e){
//handle the exception
e.printStackTrace();
public void onDisable()
SLAPI.save(list,"example.bin");
}catch(Exception e){
e.printStackTrace();
}}A minor note aboutthisSLAPI and Java's ObjectOutputStream class. This will work un-modified ifyouare saving almost all well-known Java types like Integer, String, HashMap.Thiswill work un-modified for some Bukkit types as well. If you're writing yourowndata object classes, and you may want to save their state using thistechnique,you should read up on Java's Serializable or Externalizableinterface. The onlydifference between Externalizable and Serializable is, thatSerializableautomatically takes all of class's fields and tries to serializethem, whileExternalizable allows you to define method for reading and writingthe Object.It's easy to add to your code, and it will make your data persistentwith verylittle work on your part. No more parsing!
马克= =打算学java
小技巧点燃玩家CraftBukkit API 能干很多有趣的事情。下面就是一些有趣的运用!如何使用命令将玩家点燃:public booleanonCommand(CommandSender sender, Command cmd, String label, String[] args){if(cmd.getName().equalsIgnoreCase(&ignite&)){Player s = (Player)Player target = s.getServer().getPlayer(args[0]); // 取得指令内提供的玩家名称// 例如,如果输入为 &/ignite notch&, 那玩家就是 ¬ch&.// 注意:参数数组的第一个元素编号为[0], 不是 [1]。因此 arg[0] 能取得玩家名称。target.setFireTicks(10000);}}这样如果某个玩家输入 /ignite Notch并且 &Notch& 刚好在线,Notch身上就会燃起熊熊大火!
杀死玩家如题所示,在onCommand方法中加入以下内容:public booleanonCommand(CommandSender sender, Command cmd, String label, String[] args){if(cmd.getName().equalsIgnoreCase(&KillPlayer&)){Player target = sender.getServer().getPlayer(args[0]);target.setHealth(0);}}
下面是对上面程序的一个拓展:将玩家炸死!floatexplosionPower = 4F; //This is the explosion power - TNTexplosions are 4F bydefaultPlayer target =sender.getWorld().getPlayer(args[0]);target.getWorld().createExplosion(target.getLocation(),explosionPower);target.setHealth(0);
创造爆炸这些代码将会产生TNT/爬行者那样的爆炸效果和音效。如果你取消了TNT爆炸事件但又想保留特效,这段小代码就很有用了。public voidonExplosionPrime(ExplosionPrimeEventevent){Entity entity = event.getEntity();if(entity instanceofTNTPrimed){TNTPrimedtnt = (TNTPrimed)event.getEntity().getWorld().createExplosion(tnt.getLocation(), 0);}}
让某人从其他人眼中消失以下代码将会让命令发送者从指定玩家眼中消失。请注意该命令只能对一个人产生隐藏效果。public booleanonCommand(CommandSendersender, Command cmd, String label, String[] args){if(cmd.getName().equalsIgnoreCase(&HideMe&)&&args.length == 1){Player s = (Player) //取得命令发送玩家Player target = sender.getServer().getPlayer(args[0]); //取得被蒙蔽的对象target.hidePlayer(s);}}
玩家点击触发闪电如果你拿着鱼竿点击一个方块,闪电就会集中你点击的地方。又简单又有趣:)@EventHandlerpublic voidonPlayerInteractBlock(PlayerInteractEventevt){if(evt.getPlayer().getItemInHand().getTypeId() ==Material.FISHING_ROD.getId()){//maximaldistance between player and thunderis 200 blocksevt.getPlayer().getWorld().strikeLightning(evt.getPlayer().getTargetBlock(null,200).getLocation());}}
本次更新结束,感谢大家的支持~不知道多少人贴吧id,
贴吧热议榜
使用签名档&&
保存至快速回贴

参考资料

 

随机推荐