首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >用于打开PlayerInventory的Min克拉夫特Bukkit API事件

用于打开PlayerInventory的Min克拉夫特Bukkit API事件
EN

Stack Overflow用户
提问于 2014-07-25 11:07:31
回答 2查看 2K关注 0票数 0

当打开PlayerInventory或更改内容时,我需要一个调用的事件。InventoryOpenEvent只适用于箱子、家具等,而不适用于PlayerInventory。我使用的是Java1.6SDK和1.7API。

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

我现在的问题是,当玩家被传送到产卵点时,我需要那个时刻。我第一次在PlayerTeleportEvent上试了一下,但这还为时过早。在ProWalls清除库存并添加自己的项目之前,项目将被添加。

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

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

为了更好地理解这个顺序: Player joins Game,ProWalls plugin调用initGameSettings(),plugin清除播放器库存并添加自己的项目,现在我的插件应该添加工具包的项目。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-25 11:35:54

专业编辑:在原始文章下面包括NMS / OBC,以演示如何使用反射.完成此操作。

Player库存是由Mojang选择缓存的客户端。它在打开时不需要请求任何数据,所以除了服务器连接上的初始请求之外,它不向服务器发送任何请求。没有办法测试库存何时打开,只有在修改时才能进行测试。

我不太清楚为什么你会需要那个事件,而不是一些关键的按下扳机。如果不调用InvetoryClickEvent,库存就不会改变,因此当玩家加入/进入需要跟踪库存的状态时,只需扫描一次库存,并侦听InventoryClickEvent处理更改。

编辑:存储的不正确,因为服务器处理更改,缓存是一个更好的术语。

使用NMS /OBC的

这是可能的使用反射和CraftBukkit / NMS类,但这样做经常会改变,并将导致您的插件中断每一个更新,除非您的未来-证明您的反射(这方面的教程非常丰富)。

目前的问题是:

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

建立环境:

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

覆盖球员清单:

我们需要做的第一件事是创建一个球员库存类的子类。查看CraftPlayer实例,我们看到它存储了一个CraftInventoryPlayer类,而不是一个PlayerInventory,因此,这是我们必须扩展的类。创建扩展CraftInventoryPlayer的新类。确保它有一个接受net.minecraft.server.VERSION.PlayerInventory的构造函数。该版本应由当前NMS / OBC版本字符串替换。当前的1.7.10版本是v1_7_R4。随着几乎每一个“我的世界”版本的更改,这都会发生变化,并且是大多数版本错误的根源。通过类的扩展和构造函数调用超级构造函数,您有了一个基本的自定义清单。现在我们必须决定要覆盖哪些方法。

覆盖addAll方法:

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

代码语言:javascript
运行
AI代码解释
复制
public HashMap<Integer, ItemStack> addItem(ItemStack... items) {
    HashMap<Integer, ItemStack> leftovers = super.addItem(items);
    //Examination code
    return leftovers;
}

此方法将调用原始的addItem方法,但允许您检查返回值并检查实际添加到播放机库存中的内容。通过检查itemsleftovers中的差异,您可以确切地知道哪些项目以及其中有多少项被添加到库存中,并在发生重要事情时调用您自己的事件和方法。我让你来写考试代码,因为我不太清楚你想要完成什么。

用我们的自定义类替换播放机的库存:

我不知道该在哪里进行替换,但我已经提供了我能想到的最好的选择。当我们的插件启用时,我们想要替换播放器的库存,但是一旦它被禁用,我们需要撤销我们所做的更改,这样我们的自定义类就可以被正确地卸载。我们将听取PlayerJoinEventPlayerQuitEvent来进行这些更改。

代码语言:javascript
运行
AI代码解释
复制
@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);
    }
}

这两个部分的反射有点复杂,但我会尽可能地解释它们。几乎每个Bukkit接口在CraftBukkit中都有一个相应的实现,该实现在接口名称前加上"Craft“。有时词序也会发生变化。在PlayerJoinEvent侦听器中,我们获取CraftHumanEntity类并获取它的inventory字段。这是存储玩家库存的字段。它是私有的,所以我们使用getDeclaredField方法而不是getField方法,并且必须提供声明它的确切类。然后,我们让字段可以访问并操作它的数据。对于player joins,我们get存储在该字段中的当前CraftInventoryPlayer,然后将其存储在其他地方以供以后检索。然后,我们将该字段set到自定义库存对象。请注意,构造函数接受了一个net.minecraft.server.PlayerInventory,因此我们向构造函数提供该清单。我们终于捕捉到了所有可能发生的异常,我们已经成功地覆盖了玩家的清单。在PlayerQuitEvent中,我们所做的正好相反,我们用原来的库存来代替我们的定制库存,因为我们不再需要管理它了。

,如果我上面概述的任何东西不起作用,请随时通知我。这大部分都是理论上的,但从以往处理相关问题的经验来看,它应该可以工作。

票数 2
EN

Stack Overflow用户

发布于 2016-12-02 10:08:32

您可以使用InventoryOpenEvent:

代码语言:javascript
运行
AI代码解释
复制
@EventHandler
public void onInvOpen(InventoryOpenEvent e)

也许你得检查一下玩家:

代码语言:javascript
运行
AI代码解释
复制
if(!(e.getPlayer().equals(anotherplayer)))
    return;

然后,您可以检查库存是否是玩家的库存:

代码语言:javascript
运行
AI代码解释
复制
if(e.getInventory() !instanceof PlayerInventory
    return;

(这只是为了检查库存是否是播放器的库存)

您还可以通过检查库存持有者来检查哪个玩家的库存:

代码语言:javascript
运行
AI代码解释
复制
Player invholder = (Player) e.getInventory().getHolder();
if(!invholder.equals(*anotherplayer*))
    return;

那你就有你的活动了!

(我没有测试它,但类似的代码对我有用.)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24962864

复制
相关文章
bukkit开发环境搭建
顺便下载了Chinese,Translation以及Camelcase(可选,单纯个人习惯)
阿超
2022/08/16
6750
bukkit开发环境搭建
【5min+】美化API,包装AspNetCore的返回结果
【五分钟的dotnet】是一个利用您的碎片化时间来学习和丰富.net知识的博文系列。它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net知识等等。
句幽
2020/05/19
1.4K0
Bukkit NMS 开发实践 —— 创建你自己的自定义实体(适用于 1.16.3 – 1.16.5 版本)
NMS 是 net.minecraft.server 包的简写,是 CraftBukkit 服务端及其下游服务端的底层实现,其代码包含 Mojang 发布的 Vanilla 服务端代码和 SpigotMC 添加的、用于与 BukkitAPI 进行交互的代码。在开发者无法借助 BukkitAPI 完成所需要的功能时,开发者我常常使用 NMS 进行开发。NMS 开发是底层行为,同时跨版本兼容性较差,除非必须使用,否则还请尽量使用 BukkitAPI。NMS 仅存在于编译后的服务端内部,不属于 BukkitAPI 内容。各版本的 NMS 包名一般均为 net.minecraft.server.v版_本_R号,如 net.minecraft.server.v1_16_R3。NMS 包内为扁平结构,没有二级包。NMS 包内类名为 Spigot 定义的反混淆名;方法、字段名一部分为 Spigot 定义的反混淆名,一部分为原混淆名;方法参数名一般为原混淆名。本教程旨在教授 Bukkit 开发者以 NMS 使用方法,拓展 Bukkit 开发者的开发视野。
HikariLan贺兰星辰
2022/10/27
1.4K0
API,打开“共享之门”的最好钥匙
我们经常听到开发人员讨论API。API与APP一词看上去很相似,对于APP我们很熟悉,即是应用程序Application的缩写,随着智能手机的普及这一词成了手机软件的代称。但是API又是什么呢? AP
BestSDK
2018/03/01
1K0
API,打开“共享之门”的最好钥匙
CEF 拦截打开超链接事件
使用 CEF 加载指定页面后,如果你希望控制页面在打开超链接时根据自己预定义的一些行为来操作,比如在自己的 UI 框架中新建一个 Tab 页又或者阻止打开新的页面等。我们就需要通过 CEF 提供的两个接口来实现这个功能了,分别是 OnBeforeBrowser 和 OnBeforePopup,两个接口各有各的用处,下面分别来详细介绍两个接口的作用。
我与梦想有个约会
2020/01/04
3.2K0
调接口事件API常用事件方法
 整理点调接口事件API常用事件方法 目录 倒计时事件 弹窗提示事件 弹窗修改 倒计时事件 setTimeout(function(){ this.loadingShow = false }, 1000); 弹窗提示事件 // 封装好的提示 showToast(title) { uni.showToast({ title: title, icon: "none", durat
痴心阿文
2022/11/18
2880
调接口事件API常用事件方法
用于监控USB设备连接事件的取证工具
usbrip(是“USB Ripper”的简写,而不是“USB R.I.P.”)是一个带有CLI接口的开源取证工具,可用于跟踪/监控Linux机器上的USB设备连接事件(即USB事件历史记录,“已连接”和“已断开连接”事件)。
FB客服
2019/08/28
2.3K0
用于监控USB设备连接事件的取证工具
打开API网关设计的一扇窗
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。 背景 移动互联网时代的挑战 移动互联时代迭代速率对
IT大咖说
2018/04/03
1.3K0
打开API网关设计的一扇窗
我的第一个bukkit插件
新人第一次写插件本插件24小时内能进行一次占卜 占卜后会根据占卜结果影响 钓鱼 获得双倍物品 或者 失去物品 OP可以获取转运符,转运符为物品,点击使用
阿超
2022/08/16
3460
我的第一个bukkit插件
leaflet 地图弹框popup打开显示之前的事件
比如给地图绑定popupopen 事件,在地图中弹框打开之前会触发该事件,alert一个提示,
acoolgiser
2019/01/17
2.5K0
Facebook推出用于android数据加密的开源API
小编吐槽 恶意应用和android手机的续航能力一样是令android用户格外头疼的一个问题(至少我就这么觉得 – -!),Facebook把它使用的用于数据加密的API开源了,的确是一件不错的事情。 正文 现如今很多的智能手机,都支持把应用安装到SD卡中,这会帮用户节省很多空间,但是许多黑客也会利用这一点窃取用户的隐私。一般情况下,应用都有SD卡的读写权限,当然他也可以读取到其他应用,存储在SD卡上的数据。这意味着如果你安装了恶意的应用,他就可以轻易的获取SD卡上的所有数据。 当然,为了
FB客服
2018/02/02
1.2K0
一条龙服务: 开服从入门到精通(Minecraft-Server-Starting-Guide)
本文原文发布于 GitHub,完整版可见于 此处 。因为使用了一些非标准 Markdown 语法因此在本页面可能显示不完全,在此处发布仅仅只是为了归档原文。
HikariLan贺兰星辰
2022/10/27
4.1K0
Node中的事件循环和异步API
单线程编程会因阻塞I/O导致硬件资源得不到更优的使用。多线程编程也因为编程中的死锁、状态同步等问题让开发人员头痛。 Node在两者之间给出了它的解决方案:利用单线程,远离多线程死锁、状态同步等问题;利用异步I/O,让单线程远离阻塞,以好使用CPU。
前端下午茶
2018/10/22
1.6K0
Node中的事件循环和异步API
Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
Tyan
2019/05/25
6680
1441: Min
1441: Min Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 320  Solved: 213 [Submit][Status][Discuss] Description 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 Input 第一行给出数字N,代表有N个数 下面一行给出N个数 Output S的最小值 Sample Input 2 4059 -1782 Sample Ou
HansBug
2018/04/11
8150
1441: Min
包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。 public: /*入栈时,判断存放最小元素的栈是否为空, 入栈元素是否小于存放最小元素栈的栈顶元素*/ void push(int value) { stacktemp.push(value); if(minstack.empty() || value<minstack.top()) minstack.push(value); } /*出栈时,判断出栈元素和最小元
用户3003813
2018/09/06
6610
论一种模块化的 Minecraft Minigame 游戏架构模型
近一年来,我都在负责一款 Minecraft Minigame 的开发,籍此机会,我总结了一套灵活的,可拓展的,模块化的架构,可以高效的处理游戏主循环的运行。简而言之,这些架构由一些被称之为 Flow, Phase 和 Module 的东西共同组成。要想了解它们,我们需要先从游戏主循环开始…
HikariLan贺兰星辰
2023/01/31
6600
包含min函数的栈
基于数据结构: “栈”,实现一个min函数,调用此函数即可获取栈中的最小元素。在该栈中,调用min、push、pop的时间复杂度都是O(1)。
神奇的程序员
2022/10/30
6560
包含min函数的栈
10.0 探索API调试事件原理
本章笔者将通过Windows平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于DEBUG_EVENT这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的DEBUG_EVENT调试事件,通常DEBUG_EVENT包含了多种调试类型,包括异常事件、进程创建事件、线程创建事件、进程退出事件和线程退出事件等等,我们只需要动态捕捉这些调试事件并作相应的处理即可实现更多有用的功能。
王瑞MVP
2023/10/03
2040
10.0 探索API调试事件原理
10.0 探索API调试事件原理
本章笔者将通过Windows平台下自带的调试API接口实现对特定进程的动态转存功能,首先简单介绍一下关于调试事件的相关信息,调试事件的建立需要依赖于DEBUG_EVENT这个特有的数据结构,该结构用于向调试器报告调试事件。当一个程序发生异常事件或者被调试器附加时,就会产生对应的DEBUG_EVENT调试事件,通常DEBUG_EVENT包含了多种调试类型,包括异常事件、进程创建事件、线程创建事件、进程退出事件和线程退出事件等等,我们只需要动态捕捉这些调试事件并作相应的处理即可实现更多有用的功能。
王瑞MVP
2023/10/11
1800
10.0 探索API调试事件原理

相似问题

Python插件,如Min克拉夫特Bukkit

24

基于Java编程的Min克拉夫特bukkit插件

67

Min克拉夫特bukkit调度程序和过程实例命名

14

为什么我要让mysql滞后在我的Min克拉夫特bukkit插件上?

26

如何使用Bukkit API触发事件?

27
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档