Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Minecraft Bukkit API活动,为PlayerInventory揭幕_Java_Events_Minecraft_Bukkit_Inventory - Fatal编程技术网

Java Minecraft Bukkit API活动,为PlayerInventory揭幕

Java Minecraft Bukkit API活动,为PlayerInventory揭幕,java,events,minecraft,bukkit,inventory,Java,Events,Minecraft,Bukkit,Inventory,我需要一个叫做的事件,当PlayerInventory打开或内容更改时。 InventoryOpenEvent仅适用于箱子、熔炉等,而不适用于PlayerInventory。 我正在使用Java1.6SDK和CraftBukkit1.7API 我在我的Minecraft TheWalls服务器上安装了插件ProWalls。现在我正在编写一个自己的插件,它应该扩展这个plulgin。我的插件应该让用户在游戏开始之前选择一个工具包,当游戏开始并且所有玩家都被传送到他们的开始位置时,我的插件应该添加之

我需要一个叫做的事件,当PlayerInventory打开或内容更改时。 InventoryOpenEvent仅适用于箱子、熔炉等,而不适用于PlayerInventory。 我正在使用Java1.6SDK和CraftBukkit1.7API

我在我的Minecraft TheWalls服务器上安装了插件ProWalls。现在我正在编写一个自己的插件,它应该扩展这个plulgin。我的插件应该让用户在游戏开始之前选择一个工具包,当游戏开始并且所有玩家都被传送到他们的开始位置时,我的插件应该添加之前选择的工具包的工具包项目

我现在的问题是,我需要一个时刻,当玩家被传送到繁殖点。 我先用PlayerTeleportEvent试用过,但现在还为时过早。在ProWalls清除库存并添加自己的项目之前,将添加项目

现在,我想尝试一个名为的事件,当一个项目被添加到玩家的库存中时。然后我可以检查添加的项目是否是在游戏开始时由ProWalls添加的项目,如果这是真的,我将添加我自己的项目

ProWalls在开始时调用initGameSettings()方法来保存库存、清除库存并添加他自己的项目。因此,另一个可能的解决方案是,在插件ProWalls调用自己的方法initGameSettings()时调用一个事件。但我不知道,这是否可能。 使用我当前的代码,我会在我的库存中看到从工具包中添加的项目,但几毫秒后,这些项目将被删除。如果没有其他解决方案,我可能不得不使用计时器,它会等待几毫秒,然后添加项目。但我发现,这并不是一个好的解决方案

为了更好地理解这里的顺序:
玩家加入Walls游戏,ProWalls插件调用initGameSettings(),插件清除玩家库存并添加自己的物品,现在我的插件应该添加工具包中的物品。

主要编辑:在原始帖子下方包括NMS/OBC,以显示如何使用反射进行此操作。

Player
清单通过选择Mojang在客户端缓存。它在打开时不需要请求任何数据,因此除了服务器加入的初始请求外,它不会向服务器发送任何请求。只有在进行了修改后,才能测试库存何时打开

我不太清楚为什么你需要那个事件,除了一些按键触发。如果不调用
InvetoryClickEvent
,资源清册将永远不会更改,因此当玩家加入/进入需要跟踪其资源清册的状态时,只需扫描其资源清册一次,并侦听
资源清册clickevent
,即可处理更改

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
    CraftPlayer craftPlayer = (CraftPlayer) event.getPlayer();
    //I am not actually typing this code in an IDE, so feel free to change
    //the try-catch block to only catch what is needed
    try {
        Field field = CraftHumanEntity.class.getDeclaredField("inventory");
        field.setAccessible(true);
        CraftInventoryPlayer originalInventory = (CraftInventoryPlayer) field.get(craftPlayer);
        //Store inventory here, I will use a Map that would be declared above.
        originalInventories.put(craftPlayer, originalInventory);
        field.set(craftPlayer, new CustomInventory(craftPlayer.getHandle().inventory));
    } catch (Exception e) {
        Bukkit.getLogger.log(Level.SEVERE, "Error creating custom player inventory", e);
    }
}

@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
    CraftPlayer craftPlayer = (CraftPlayer) event.getPlayer();
    //I am not actually typing this code in an IDE, so feel free to change
    //the try-catch block to only catch what is needed
    try {
        Field field = CraftHumanEntity.class.getDeclaredField("inventory");
        field.setAccessible(true);
        CraftInventoryPlayer originalInventory = originalInventories.get(craftPlayer);
        //Store inventory here, I will use a Map that would be declared above.
        field.set(craftPlayer, originalInventory);
    } catch (Exception e) {
        Bukkit.getLogger.log(Level.SEVERE, "Error replacing player inventory with original", e);
    }
}
编辑:存储是不正确的,因为服务器处理更改,缓存是一个更好的术语

使用NMS/OBC:

这可以使用反射和CraftBukkit/NMS类实现,但这样做经常会发生更改,并且会导致插件每次更新都会中断,除非您将来对反射进行验证(这方面的教程非常丰富)

当前的问题是:

Bukkit不允许您监听来自give命令或直接代码清单管理的清单更改。因此,我们需要增加一种方式来倾听这些变化。最好的方法是覆盖更改库存的方法,或者添加事件以便于将来更改,或者在那里进行计算。我将解释后者,因为它更容易处理,并且还存在各种自定义事件教程

建立环境:

使用NMS/OBC时,需要导入CraftBukkit以获得所需的类。下载CraftBukkit jar并将其导入到您的项目中,而您通常是这样做的。如果您收到一些方法签名方法,请确保Bukkit具有更高的导入优先级。同样,教程向您展示了如何在大多数IDE上修复该错误

覆盖玩家资源清册:

if(e.getInventory() !instanceof PlayerInventory
    return;
我们需要做的第一件事是创建players inventory类的子类。查看
CraftPlayer
内部,我们看到它存储的是
CraftInventoryPlayer
类,而不是
PlayerInventory
,因此,这是我们必须扩展的类。创建扩展
CraftInventoryPlayer
的新类。确保它有一个接受
net.minecraft.server.VERSION.PlayerInventory
的构造函数。版本应替换为当前NMS/OBC版本字符串。目前1.7.10的版本是
v1\u 7\u R4
。几乎每一次minecraft版本的更改都会改变这种情况,这是大多数版本错误的根源。随着类的扩展和构造函数调用超级构造函数,您有了一个基本的自定义清单。现在我们必须决定覆盖哪些方法

覆盖
addAll
方法:

假设
Essentials
和其他插件使用
addAll
方法,这就是我们需要监控的方法。我们要做的是覆盖
addAll
方法,并围绕我们希望进行的检查包装它的功能。在自定义库存类中,我们执行以下操作

public HashMap<Integer, ItemStack> addItem(ItemStack... items) {
    HashMap<Integer, ItemStack> leftovers = super.addItem(items);
    //Examination code
    return leftovers;
}
这两个反射点有点复杂,但我会尽可能地解释它们。几乎每个
Bukkit
接口在
CraftBukkit
中都有一个相应的实现,在接口名称前加上“Craft”。有时单词的顺序也会改变。在
PlayerJoinEvent
侦听器中,我们获得
CraftHumanEntity
类,并获得它的
inventory
字段。这是存储玩家库存的字段。它是私有的,因此我们使用
getDeclaredField
方法,而不是
getField
方法,并且必须提供声明它的确切类。然后,我们使字段可访问并操作其数据。对于玩家加入,我们

if(!(e.getPlayer().equals(anotherplayer)))
    return;
if(e.getInventory() !instanceof PlayerInventory
    return;
Player invholder = (Player) e.getInventory().getHolder();
if(!invholder.equals(*anotherplayer*))
    return;