Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于打开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

复制
相关文章
面向对象的C语言
大家在学C、C++ 的时候,老师多半会讲过:C语言是面向过程的编程语言,C++是面向对象的编程语言。但归根结底,面向过程还是面向对象,这是编程思想的差异,而不是语言的差异。笔者最近在看baresip源码,C语言也能写成面向对象。
杜金房
2020/12/21
7080
C语言面向对象
这种编程风格的被称作面向过程。除了面向过程之外,还有一种被称作面向对象的编程风格被广泛使用。面向对象采用基于对象的概念建立模型,对现实世界进行模拟,从而完成对问题的解决。
WuShF
2023/02/26
1.8K0
C语言面向对象
C语言面向对象
这种编程风格的被称作面向过程。除了面向过程之外,还有一种被称作面向对象的编程风格被广泛使用。面向对象采用基于对象的概念建立模型,对现实世界进行模拟,从而完成对问题的解决。 C语言的语法并不直接支持面向对象风格的编程。但是,我们可以通过额外的代码,让C语言实现一些面向对象特性。在这一节当中,我们将探究什么是面向对象,以及怎样用C语言来实现它。 单纯理论上的讨论可能比较难以理解,为了能够让我们的讨论能够落地到实际中,我们选取学校为场景,展开对面向对象风格编程的讨论。 一般而言面向对象风格的编程具有以下3大特性:
WuShF
2023/02/27
1.5K0
C语言面向对象
C语言的面向对象编程
面向对象编程是一种思想,并非一定要用哪种语言去实现,c语言也可以实现面向对象编程。通过结构体和指针就可以实现。
用户9736681
2023/02/20
1.6K0
C语言的面向对象编程
如何使用C语言的面向对象
我们都知道,C++才是面向对象的语言,但是C语言是否能使用面向对象的功能? (1)继承性 1 typedef struct _parent 2 { 3 int data_parent; 4 }Parent; 5 typedef struct _Child 6 { 7 struct _parent parent; 8 int data_child; 9 }Child;  在设计C语言继承性的时候,我们需要做的就是把基础数据放在继承的结构的首位置即可。这样,不管是数据的访问、数据的强转、数据的访问都不会有什么问
233333
2018/03/07
2.3K0
C语言实现面向对象的原理
不知道有多少人去了解过语言的发展史,早期C语言的语法功能其实比较简单。随着应用需求和场景的变化,C语言的语法功能在不断升级变化。
刘盼
2021/01/25
8860
C语言到C++的OOP 面向对象编程
1、全面兼容C,C的许多代码不经修改就可以为Cpp所用,用C编写的库函数和实用软件可以用于Cpp。
小林C语言
2020/12/21
3.3K0
C语言到C++的OOP 面向对象编程
c语言实现面向对象编程
面向对象编程(OOP)并不是一种特定的语言或者工具,它只是一种设计方法、设计思想。它表现出来的三个最基本的特性就是封装、继承与多态。很多面向对象的编程语言已经包含这三个特性了,例如 Smalltalk、C++、Java。但是你也可以用几乎所有的编程语言来实现面向对象编程,例如 ANSI-C。要记住,面向对象是一种思想,一种方法,不要太拘泥于编程语言。
用户6280468
2022/04/18
8260
c语言实现面向对象编程
专业编写c语言的软件,适合编写C语言代码的几款软件
C语言基本上是大学计算机及其相关专业在大一上学期就会开的一门课程,但是很多学生听得都是一些理论知识,其实究其主要原因,还是因为你在上课认真听了,但是却没有在课后好好的自己去主动敲代码,想要动手操作,就需要几款编程利器,手机电脑都可以,下面我们就先看一下手机软件:
全栈程序员站长
2022/08/24
4.2K0
C语言-结构体面向对象编程技巧
一、面向对象 面向对象是软件开发方法,是相对于面向过程来讲的。通过把数据与方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式 单片机C语言的面向对象编程,是利用结构体,将变量、指针、函数等进行封装,达到编程更加方便、程序可读性更好、方便移植等目的。
好派笔记
2021/09/17
1.4K0
Go语言的面向对象
go语言仅支持封装,不支持继承和多态。 go语言没有class,只有struct。
JavaEdge
2021/02/22
2730
java语言和c语言一样是面向对象的程序设计语言_面向对象和面向过程具体区别
  很多初学编程的小伙伴或者想要学习编程的小白弄不清C语言和Java的区别。本文就针对萌新们尽量用通俗的语言来介绍一下我所理解的编程语言界的两大巨头。
全栈程序员站长
2022/09/20
7000
java语言和c语言一样是面向对象的程序设计语言_面向对象和面向过程具体区别
面向对象的JavaScript代码
人类非常善于将东西归类。编程中有一种数据类型叫对象,就是一种将数据的行为和数据本身归类的方法。这样能帮助设计并理解大段的代码。事实上,面向对象的编程方法在许多程序语言中都有,很多软件都是靠它编写出来的,大家普遍认为它是一种良好的编写代码的方法。
疯狂的技术宅
2019/03/27
5270
采用面向对象的方法编写程序
虽然这一章我们课没有学,也是最后一章,但是我觉得很重要所以就自己自学了,并且在mooc上,我还会系统的学习c++面向对象的程序设计。这里书上讲的很笼统,也很少,我主要学一下一些模板的使用
废江_小江
2022/09/05
1830
神奇的go语言(面向对象)
有过C++语言学习经历的朋友都知道,面向对象主要包括了三个基本特征:封装、继承和多态。封装,就是指运行的数据和函数绑定在一起,C++中主要是通过this指针来完成的;继承,就是指class之间可以相互继承属性和函数;多态,主要就是用统一的接口来处理通用的逻辑,每个class只需要按照接口实现自己的回调函数就可以了。 作为集大成者的go语言,自然不会在面向对象上面无所作为。相比较C++、Java、C#等面向对象语言而言,它的面向对象更简单,也更容易理解。下面,我们不妨用三个简单的例子来说明一下go语言
李海彬
2018/03/22
6030
如何使用Go语言写出面向对象风格的代码
面向对象程序设计是一种计算机编程架构,英文全称:Object Oriented Programming,简称OOP。OOP的一条基本原则是计算机程序由单个能够起到子程序作用的单元或对象组合而成,OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。OOP=对象+类+继承+多态+消息,其中核心概念就是类和对象。
Golang梦工厂
2022/07/11
3850
用C语言编写交换数组数值的代码教程
使用C语言编程的一个常见需求是交换数组中两个元素的值。这个操作在很多算法和程序中都有应用,因此学会如何编写交换数组数值的代码是非常重要的。本教程将向大家介绍如何使用C语言实现这个功能。
用户10354340
2023/08/14
2920
编写高质量代码:改善JavaScript程序建议--面向对象编程
​ 对象(Object)是没有原型的,只有构造函数拥有原型,而构造类的实例对象能够通过prototype属性访问原型对象。 prototype表示类的原型,就是构造类拥有的原始成员。构造函数的prototype属性存储着一个引用对象指针,该指针指向一个原型对象。
奋飛
2019/08/15
3490
面向对象和面向过程的区别理解_c是面向对象还是面向过程
玩家对象负责接受用户输入,棋盘对象棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用规则对象来对棋局进行判定。
全栈程序员站长
2022/09/23
9800
面向对象和面向过程的区别理解_c是面向对象还是面向过程
理解面向对象的语言特点_面向对象的理解并举例
前言:我们学习的javascript语言是一门面向对象的语言,所以这一概念我们需要理解与认识!下面是理解性的理论内容,不需要记忆,理解与思考我们的学习才能站在更高的视角!
全栈程序员站长
2022/09/20
4120

相似问题

_uiState.asStateFlow()和StateFlow<UIState> = _uiState在ViewModel Jetpack组合中的区别是什么?

11

_uiState.value = uiState.value.copy()不会导致重新组合

31

合成与仿制

20

聚集与合成

36

“属性”与“合成”

33
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

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

洞察 腾讯核心技术

剖析业界实践案例

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