Minecraft(我的世界)中文论坛

标题: 插件控制合成与取消合成事件

作者: Bryan33    时间: 2015-9-23 18:54
标题: 插件控制合成与取消合成事件
本帖最后由 a390807154 于 2017-5-20 18:42 编辑

插件控制合成与取消合成事件
怎么说呢,这是个并没有卵用的教程
目地: 用插件添加新的合成 并且限制合成材料必须是用特殊数据值的
                                                                     因为Bukkit的合成只检测物品ID不检测物品的数据值
本教程说明: 类  包  方法

添加合成:
  方法 Bukkit.addRecipe(Recipe) 可以将一个Recipe进行注册是玩家能在服务器中合成
  注意 这个注册在插件被卸载的时候不会被注销 必须手动注销
  Recipe有3个子类 它们位于 org.bukkit.inventory 下 分别是: FurnaceRecipe   熔炉合成
                                                                                      ShapedRecipe    有型合成
                                                                                      ShapelessRecipe 无形合成
FurnaceRecipe : 通过查询API可知,熔炉的合成在构建的时候使用参数来设定目标物品  ←不是本教程重点ShapedRecipe : 在构建的时候通过参数ItemStack设置合成结果
ShapelessRecipe : 在构建的时候通过参数ItemStack设置合成结果


ShapedRecipeShapelessRecipe 的区别:
ShapelessRecip 只需要通过 .addIngredient() 来设置原料 无需设置形状
ShapedRecipe 必须通过 .shape(String[] shape) 来设置形状
例子:
  1. ShapedRecipe sr = new ShapedRecipe(item);
  2.         sr.shape(new String[]{
  3.                     "A C",
  4.                     "CBA",
  5.                     "A C"
  6.                 });
复制代码
那么 这个合成就必须按照这个形状来合成 不需要物品的地方使用空格

在指定形状后还需要指定每个字符代表的物品 空格不用指定
通过 .setIngredient(char key, Material ingredient) 来设置每个字符所代表的物品 因为这个方法不能使用 ItemStack 所以原料是无数据值的
例子:
  1. sr.setIngredient('A', Material.PAPER);
  2. sr.setIngredient('B', Material.VINE);
  3. sr.setIngredient('C', Material.BROWN_MUSHROOM);
复制代码
最后将这个合成进行注册就可以使用了
getServer().addRecipe(sr);

无形合成例子:
  1. ShapelessRecipe sr = new ShapelessRecipe(item);
  2.             sr.addIngredient(9, Material.VINE);
复制代码
就是这么简单 上面是9个藤蔓合成物品 可以重复调用方法来设置多种物品.


重点-限制合成原料必须是带有特定数据的:
此方法需要一个监听器: CraftItemEvent

在监听器中写入
  1. ItemStack item = evt.getRecipe().getResult();
  2.         item.setAmount(1);
  3. if (item.equals(目标物品)) {
  4.             if (!evt.getInventory().contains(必须原料)) {
  5.                 evt.setCancelled(true);
  6.             }
  7. }
复制代码


本教程到此为止 如果有更好方法请在下面回复~

↓ 加人气不扣自己的哦

下页 实例代码
https://coding.net/u/Bryan_lzh/p/SuperBandage/git/blob/master/src/superbandage/ItemsCreater.java

↑ 来自插件 http://www.mcbbs.net/thread-505610-1-1.html


合成注册部分:
  1. ItemStack item = new ItemStack(Material.PAPER);
  2.         ItemMeta im = item.getItemMeta();
  3.         im.setLore(this.Lore);
  4.         im.setDisplayName(ChatColor.translateAlternateColorCodes('&', "&b初级绷带"));
  5.         item.setItemMeta(im);
  6.         ShapedRecipe sr = new ShapedRecipe(item);
  7.         sr.shape(new String[]{
  8.                     "M M",
  9.                     "M M",
  10.                     "M M"
  11.                 });
  12.         sr.setIngredient('M', Material.VINE);
  13.         Items.plugin.getServer().addRecipe(sr);
  14.         Items.plugin.sr.add(sr);
  15.         return item;
复制代码
对应合成:
  1. ItemStack item = new ItemStack(Material.PAPER);
  2.         ItemMeta im = item.getItemMeta();
  3.         im.setLore(this.Lore);
  4.         im.setDisplayName(ChatColor.translateAlternateColorCodes('&', "&b中级绷带"));
  5.         item.setItemMeta(im);
  6.         ShapedRecipe sr = new ShapedRecipe(item);
  7.         sr.shape(new String[]{
  8.                     "MPM",
  9.                     " G ",
  10.                     "M M"
  11.                 });
  12.         sr.setIngredient('M', Material.VINE);
  13.         sr.setIngredient('G', Material.GOLD_INGOT);
  14.         sr.setIngredient('P', Material.PAPER);
  15.         Items.plugin.getServer().addRecipe(sr);
  16.         Items.plugin.sr.add(sr);
  17.         return item;
复制代码
对应合成:

监听部分:
https://coding.net/u/Bryan_lzh/p/SuperBandage/git/blob/master/src/superbandage/S_BandageListener.java










作者: Bryan33    时间: 2015-9-24 18:03
本帖最后由 a390807154 于 2015-9-26 17:16 编辑

已经更新原内容
作者: 可可可可可乐    时间: 2015-9-26 10:03
感谢楼主,我上次就想问这个问题
作者: CatSeed    时间: 2015-11-21 23:04
弱弱问句 这个合成的

不卸载有什么关系?

Jre在结束的时候不是会自动回收吗
作者: Bryan33    时间: 2015-11-22 08:44
Event 发表于 2015-11-21 23:04
弱弱问句 这个合成的

不卸载有什么关系?

话说我没卸载这个监听器吧
作者: 深蓝の回忆    时间: 2015-11-22 09:55
福音啊,感谢楼主写此教程
作者: 494308843    时间: 2016-3-14 15:35
能设置所需物品数量么
作者: Bryan33    时间: 2016-3-14 18:14
494308843 发表于 2016-3-14 15:35
能设置所需物品数量么

物品数量请通过CraftItemEvent事件获取CraftingInventory后自行分析是否达到物品数量要求

大部分的条件都要通过这步实现

建议你设置一个ItemStack[]为必要的物品 然后进行对比
作者: 494308843    时间: 2016-3-14 22:19
如果有同ID自定义lore物品  合成不同的物品
怎么弄
合成摆放一样
作者: Bryan33    时间: 2016-3-15 06:54
494308843 发表于 2016-3-14 22:19
如果有同ID自定义lore物品  合成不同的物品
怎么弄
合成摆放一样

因为CraftItemEvent是继承InventoryClickEvent的

所以你可以通过InventoryClickEvent事件的方法将合成的结果物品替换掉(在拿起物品的时候)

setCurrentItem(ItemStack stack)方法来实现
作者: 494308843    时间: 2016-3-17 13:34
{:10_494:}怎么卸载
我复制你插件的卸载代码
发现无效
然后测试你插件
卸载插件
发现
也无效
作者: 494308843    时间: 2016-3-17 13:37
a390807154 发表于 2016-3-15 06:54
因为CraftItemEvent是继承InventoryClickEvent的

所以你可以通过InventoryClickEvent事件的方法将合成的 ...

这个方法有毒!为什么玩家点击自己背包能触发
也能获取物品
但是!修改物品  也成功了!
LORE我输出  也是修改了
但是物品就是没变!
但是在箱子就一切正常!
作者: Bryan33    时间: 2016-3-17 18:06
请不要直接监听InventoryClickEvent事件
请监听CraftItemEvent事件并使用他的父方法

另外你是要卸载什么
卸载合成的话https://coding.net/u/Bryan_lzh/p/SuperBandage/git/blob/master/src/superbandage/SuperBandage.java


作者: 494308843    时间: 2016-3-17 20:50
我调试了好久
发现
迭代器获得的Recipe
equals
不能比较
唯一能比较的只有结果物品
但是如果有合成结果相同 不同公式的  没法确定是哪一个
强制转换为对应的
比如(ShapedRecipe)
getShape
这个获取到的String数组
好像次次都是
abc
d..
...这样的
不能用来对比
但是这确实是之前添加的合成
太蛋疼了

不知道我测试的有问题没
具体该怎么弄才能移除指定的合成



作者: Bryan33    时间: 2016-3-17 21:07
494308843 发表于 2016-3-17 20:50
我调试了好久
发现
迭代器获得的Recipe

看来应该是合成被注册后被修改了呢

那么在下这里给你提供一个解决方案

合成出的目的物品在设置时先设置为不同Lore的

最后通过事件在取出的时候替换 这样能做到合成出相同的物品
而且能够通过Bukkit.getRecipesFor()方法来寻找那个要卸载的合成
作者: hhttll    时间: 2016-5-4 09:50
受教了谢谢
作者: jkaa13579    时间: 2016-5-28 16:44
解决了无MOD无法自定义合成公式的问题,感谢楼主兼版主
作者: chenzizai    时间: 2016-7-21 09:21
请问FurnaceRecipe   熔炉合成怎么写
作者: Bryan33    时间: 2016-7-21 12:19
chenzizai 发表于 2016-7-21 09:21
请问FurnaceRecipe   熔炉合成怎么写

利用构建方法
FurnaceRecipe(ItemStack result, Material source)
来指定生成的物品和烧制之前的物品
烧的时间不能指定
然后直接用Bukkit.addRecipe(Recipe recipe);来添加
作者: chenzizai    时间: 2016-7-23 12:33
a390807154 发表于 2016-7-21 12:19
利用构建方法
FurnaceRecipe(ItemStack result, Material source)
来指定生成的物品和烧制之前的物品

能不能举两个代码例子:
石砖烧成裂石砖
多个物品无形合成:藤蔓+园石=苔石
作者: Bryan33    时间: 2016-7-23 13:21
chenzizai 发表于 2016-7-23 12:33
能不能举两个代码例子:
石砖烧成裂石砖
多个物品无形合成:藤蔓+园石=苔石 ...

帖子第二页有有型合成的
这种东西需要你自己手动写代码去摸索的
作者: User:guest    时间: 2016-12-4 17:53
感谢楼主提供的菜谱自定义技术分享。请问Recipe接口这里,实例化时是用实现它的实现类吗
作者: Bryan33    时间: 2016-12-5 22:39
User:guest 发表于 2016-12-4 17:53
感谢楼主提供的菜谱自定义技术分享。请问Recipe接口这里,实例化时是用实现它的实现类吗 ...


构建他的子类new

作者: byxiaobai    时间: 2017-1-14 11:53
感谢楼主,666啊
作者: 拉普达    时间: 2017-2-11 03:01
楼主我是小白
想问您一些问题
这是我写的代码
应该如何制定leather的合成材料腐肉名字必须是§6烧制腐肉?
否则不能合成


作者: Bryan33    时间: 2017-2-11 17:50
拉普达 发表于 2017-2-11 03:01
楼主我是小白
想问您一些问题
这是我写的代码

物品不能使用equals方法
而要使用isSimilar方法
另外 可以通过item.getItemMeta().getDisplayName()来获取物品的名字
建议先用item.getItemMeta().hasDisplayName()来判断是否有名字
  1. if(item.getItemMeta().hasDisplayName()&&item.getItemMeta().getDisplayName().equalsIgnoreCase("§6烧制腐肉")){
  2.     //TODO}
复制代码


作者: 拉普达    时间: 2017-2-11 20:20

腐肉经过烧制得到命名"§6烧制腐肉"的腐肉
然后再用腐肉与线合成皮革
前面我通过你的教程研究写好了
但是我想要腐肉的名字必须为§6烧制腐肉才可以合成皮革
作者: Bryan33    时间: 2017-2-11 22:20
拉普达 发表于 2017-2-11 20:20
腐肉经过烧制得到命名"§6烧制腐肉"的腐肉
然后再用腐肉与线合成皮革
前面我通过你的教程研究写好了
  1. @EventHandler
  2.     public void onCraft(CraftItemEvent evt) {
  3.         if (evt.getRecipe().getResult().isSimilar(leather)) {
  4.             for (ItemStack is : evt.getInventory().getMatrix()) {
  5.                 if (is.getType() == Material.ROTTEN_FLESH && is.hasItemMeta() && is.getItemMeta().hasDisplayName()) {
  6.                     if (!is.getItemMeta().getDisplayName().equals("§6烧制腐肉")) {
  7.                         evt.setCancelled(true);
  8.                         return;
  9.                     }
  10.                 }
  11.             }
  12.         }
  13.     }
复制代码

作者: Kyokuki    时间: 2018-8-23 16:55
不是我说,写的一点都不清楚,萌新是看不明白的,不推荐
作者: Bryan33    时间: 2018-8-24 09:37
残雪、 发表于 2018-8-23 16:55
不是我说,写的一点都不清楚,萌新是看不明白的,不推荐

抱歉了 这个教程不是给没有任何基础的人看的

作者: gooding300    时间: 2018-8-24 18:46
本帖最后由 gooding300 于 2018-8-24 20:07 编辑

作者您好,有个问题想请教一下,用这个方法修改的合成表可以同步到客户端吗?
(例如原版自带的合成书中能否看到变更后的合成表?)
或者是CraftGuide、NEI、JEI等可以显示合成表的mod

作者: Bryan33    时间: 2018-8-24 20:01
gooding300 发表于 2018-8-24 18:46
作者您好,有个问题想请教一下,用这个方法修改的合成表可以同步到客户端吗?
(例如原版自带的合成书中能否 ...

抱歉啊
因为这个教程是很早之前写的
那个时候客户端还没有合成书之类的东西
所以我也没有测试过
作者: Bryan33    时间: 2018-8-25 21:28
gooding300 发表于 2018-8-24 18:46
作者您好,有个问题想请教一下,用这个方法修改的合成表可以同步到客户端吗?
(例如原版自带的合成书中能否 ...

测试了一下原版的合成书
发现 如果你删除了服务端的合成配方
客户端不会显示任何配方
自定义的配方也不会显示在其中
作者: Sssss...    时间: 2020-3-17 17:36
补充:现在的ShapedRecipe已经有实例方法setIngredient(char, ItemStack)了(好像很久以前就有了)
作者: lxf2051703348    时间: 2020-3-19 10:56
支持一下,感谢分享

作者: lxf2051703348    时间: 2020-3-19 10:59
Sssss... 发表于 2020-3-17 17:36
补充:现在的ShapedRecipe已经有实例方法setIngredient(char, ItemStack)了(好像很久以前就有了) ...

为啥1.12.2没有
作者: Sssss...    时间: 2020-3-19 11:46
lxf2051703348 发表于 2020-3-19 10:59
为啥1.12.2没有

不知道,反正1.13是有的