我的世界手机有PHP的开服器下载,【BDS】MC基岩版官方开服器Windows版插件开发包...

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x

MC基岩版官方开服器Windows版插件开发教程

2019年5月22日 作者:Player

前言:

MC基岩版官方开服器(BDS)自发布至今,已经有数月时间。其间有各种魔改的开服端以及各种功能的插件出现,但是截止目前,由于MC官方发布BDS在Linux版与Windows版之间存在一些固有的差异,导致插件开发者制作的插件无法跨平台使用,也无法跨平台编译。本文将提供一种开发出能够在Windows版开服器上使用的插件的途径。当前,BDS正处于早期测试版,本教程附带的工具能够利用测试版附带的相关信息实现插件功能。

概述:

本文中的插件是指可执行文件的动态链接库文件。开发者使用开发工具将所写的源代码编译成插件(DLL文件)。然后使用专用的启动器在开服器程序的运行时期将插件导入开服器进程之中,导入后的开服器进程在功能上因插件加载而得到扩展,得到原本没有的功能。插件的使用将允许开服器的功能有一个质的飞跃。

作为插件开发者,开发过程从零开始的流程如下:

1、下载官方BDS压缩包与插件开发工具包,并解压

2、使用工具包中“PDB导出工具”,找到解压后的BDS目录,选择bedrock_server.pdb文件,导出对应的PDB信息文件

3、用Visual Studio 2019打开工具包中的插件开发工程“MCMODDLL”。然后打开其列表中的symbol.txt,按照文件要求添加你需要修改功能的符号名称

4、再利用“PDB导出工具”,选择步骤2导出的PDB信息文件和步骤3中的symbol.txt文件,导出对应的C++头文件(默认SymHook.h)替换掉插件工程中原先的SymHook.h文件

5、打开SymHook.h文件,复制所需要的符号对应的由工具自动生成的C++变量名,再打开插件工程中的mod.cpp文件,利用这个变量名,在内部写上你要对这个符号对应的函数做出的修改部分的代码

6、确认代码无误后,编译生成DLL文件

7、在BDS目录下新建一个目录,叫MOD_DLL,然后将步骤6生成的DLL文件放入这个目录

8、启动工具包中的“MC BDS简易启动器”,勾选“加载插件”复选框(默认为勾选状态),点击“启动服务器”

至此,服务器在加载插件的情况下顺利启动,大功告成!

插件案例:爆炸箭

在Minecraft基岩版中,箭原本是不具有爆炸属性的,但是通过插件,我们可以实现这一独特的功能。

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

image.png (288.76 KB, 下载次数: 2)

2019-5-24 18:48 上传

之前MCMrARM写过一个关于爆炸箭的教程,目标是Linux平台,该教程由于年头久远,又缺乏维护,已经无法按步骤实现。但是可以作为看本案例之前的参考。

从这篇文章中,我们获取了一点重要的信息:

1、当箭中目标时候,会触发ProjectileComponent::onHit类方法

2、产生一次爆炸是用Level::explode类方法

另外,通过分析,我们发现其他的类方法诸如HitResult::getPos在当前版本都已经不复存在了,所以上述说MCMrARM的教程当前已经无法按步骤实现。

接下来,我们将一步步自己实现爆炸箭功能:

(一)利用IDA Pro逆向分析主程序bedrock_server.exe文件

在IDA Pro开始分析的时候会问你是否加载pdb调试信息,选择确定。

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片2.png (142.97 KB, 下载次数: 2)

2019-5-24 18:50 上传

左侧是从调试信息中分析出的各种函数名称,右侧为内容。

(一)确定需要研究的内容

上面提到了两个十分重要的类方法:

ProjectileComponent::onHit和Level::explode

前者在箭击中时候触发的,后者制造一个爆炸效果。基本思路是,让前者触发的时候调用后者制造一个爆炸。这样“爆炸箭”功能就实现了。那么让我们看一下从IDA Pro中获取的原型:

void __fastcall ProjectileComponent::onHit

(ProjectileComponent *__hidden this, const struct HitResult *)

void __fastcall Level::explode

(Level *this, struct BlockSource *, struct Actor *, const struct Vec3 *, float, bool, bool, float, bool)

乍一看,似乎前者给的参数不够调用后者,这该如何是好呢?

现在我们来收集整理一下我们手上现有的信息:

这个onHit 方法提供了两个指针,ProjectileComponent(抛射物)指针和HitResult(击中结果)指针。而explode需要四个结构体指针:

1、Level* 存档指针,MC基岩版使用Level表示存档,用于存档的kv数据库叫LevelDB;

2、BlockSource* 不知道是什么结构的指针,不过看上去十分重要;

3、Actor* 似乎是玩家/生物结构的指针;

4、Vec3* 嗯,就是坐标结构的指针,没跑了。

至于后续的float和bool,因为我们可以直接提供,所以先不管。

(二)分析Level::explode和ProjectileComponent::onHit参数指向的结构体

上面我们看到,仅仅使用onHit提供的参数不做任何处理是不能够完成对explode直接调用的。那么我们不妨先找一下其他的函数对Level::explode调用让我们学习参考一下。

首先找到 Level::explode:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片3.png (6.5 KB, 下载次数: 3)

2019-5-24 18:55 上传

然后打开,在右侧的反汇编内容里选择函数符号,右键,点击Jump to xref to operand(跳转到该函数的调用位置列表):

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片4.png (45.32 KB, 下载次数: 4)

2019-5-24 18:56 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片5.png (29.95 KB, 下载次数: 5)

2019-5-24 18:56 上传

可能你也发现了,中间的那个BedBlock::use显得格格不入,而且十分亮眼!没错,这就是玩家在地狱放置床的时候发生的爆炸。那么我们现在就进去看看这葫芦里卖的是啥药呢。为了方便查看,这里我们使用F5插件进行反编译:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片6.png (49.84 KB, 下载次数: 3)

2019-5-24 18:57 上传

哦?这里Actor*居然是不必要的,这算是潜在可能会减少一点我们分析的工作量。接着我们继续追查其他三个指针的来源:

首先分析Level*:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片7.png (2.99 KB, 下载次数: 5)

2019-5-24 18:59 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片8.png (2.06 KB, 下载次数: 2)

2019-5-24 18:59 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片9.png (1.12 KB, 下载次数: 4)

2019-5-24 18:59 上传

是从Player结构体里出来的,我们继续追查,打开Player::Player类构造函数,发现:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片10.png (2.43 KB, 下载次数: 1)

2019-5-24 19:00 上传

再进入Mob::Mob:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片11.png (3.69 KB, 下载次数: 1)

2019-5-24 19:00 上传

再进入Actor::Actor:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片12.png (1.71 KB, 下载次数: 1)

2019-5-24 19:02 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片13.png (4.93 KB, 下载次数: 3)

2019-5-24 19:02 上传

于是,我们发现Player类是由Mod类派生而来,而Mod类又是由Actor类派生出来,而且Level*指针最终归在了Actor结构体内416*sizeof(QWORD*)的位置。

然后分析BlockSource*:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片14.png (4.88 KB, 下载次数: 0)

2019-5-24 19:04 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片15.png (3 KB, 下载次数: 7)

2019-5-24 19:05 上传

从上文分析得知,这个a2是Player*的,v5是取Player内部414*sizeof(QWORD*)的位置,那么这个位置也同样是Actor类的内部。

接下来就是分析Vec3了:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片16.png (6.64 KB, 下载次数: 5)

2019-5-24 19:07 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片17.png (3.74 KB, 下载次数: 3)

2019-5-24 19:07 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片18.png (5.36 KB, 下载次数: 3)

2019-5-24 19:07 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片19.png (4.21 KB, 下载次数: 3)

2019-5-24 19:07 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片20.png (4.28 KB, 下载次数: 5)

2019-5-24 19:07 上传

在一系列复杂的操作之前,v56和v57最终来自于BlockPos结构,这是BedBlock::use的第三个参数:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片21.png (2.41 KB, 下载次数: 5)

2019-5-24 19:09 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片22.png (1.32 KB, 下载次数: 4)

2019-5-24 19:09 上传

显然这里BlockPos储存的是放置的床的坐标,而放置床的操作显然不会跟打击动作扯上关系,更不应该跟HitResult有关系。这里我们选择放弃继续追查这里的坐标来源。

根据MCMrARM的教程,HitResult储存了坐标信息,我们转而去分析HitResult内部的结构。试试看有没有可能取得突破。

由于HitResult没有任何类成员函数,除了一个operator=,给我们的分析带来了麻烦,此时只能选择动态分析内部结构。找到ProjectileComponent::onHit,在它的第一条指令上下断点:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片23.png (9.28 KB, 下载次数: 4)

2019-5-24 19:10 上传

然后我们利用IDA Pro附加windbg(x64)调试器启动开服器进行调试分析。打开MC基岩版客户端(我用的win10版)进入游戏,这里为了构建一个足够识别Vec3的环境,我们进入创造模式,在控制台输入:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片24.png (41.17 KB, 下载次数: 3)

2019-5-24 19:11 上传

然后朝这个基岩射箭:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

file_1558696312000.jpg (161.61 KB, 下载次数: 3)

2019-5-24 19:11 上传

回到IDA Pro调试界面,我们发现IDA Pro已经截获到了这个断点,HitResult是onHit方法的第二个参数,根据微软的x64程序调用约定(fastcall),第二个参数保存位置是RDX寄存器,然后我们跟踪RDX指向的内存区域:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片26.png (12.83 KB, 下载次数: 4)

2019-5-24 19:13 上传

并选择float类型查看该区域:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片27.png (22.61 KB, 下载次数: 2)

2019-5-24 19:14 上传

怎么样?跟刚才输入的/setblock后的坐标是不是大致相同?那么,现在我们确定HitResult内部在一开始的位置就包含Vec3坐标,而且顺序是X,Y,Z。那么这四个结构的来源我们都搞定了,explode中剩下的5个参数就照搬床爆炸的参数吧:“5.0, true, true, 3.4, false”。

最后,我们需要找到ProjectileComponent*与Actor*的关系,找到ProjectileComponent::ProjectileComponent,发现其中正好有一个函数附带Actor*的参数:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片28.png (43.04 KB, 下载次数: 1)

2019-5-24 19:15 上传

Actor*被保存在结构体内2*sizeof(QWORD*)的位置。

至此,爆炸箭功能研究分析部分就完成了,下面我们将要开始着手实现这一切。

(一)下载BDS开服器和工具包,并解压:

本案例中使用的是1.11.2.1版本BDS。

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片29.png (37.83 KB, 下载次数: 3)

2019-5-24 19:17 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片30.png (33.29 KB, 下载次数: 4)

2019-5-24 19:17 上传

(二)解压缩MOD插件工程包,用VS2019打开,复制我们需要的符号到Symbol.txt中,并使用“PDB导出工具”将必要符号导出到工程SymHook.h文件:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片31.png (61.93 KB, 下载次数: 4)

2019-5-24 19:19 上传

图中的符号分别是ProjectileComponent::onHit与Level::explode方法的,点击保存,先使用PDB工具生成PDB信息文件,再使用PDB工具生成SymHook.h覆盖掉原文件:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片32.png (26.71 KB, 下载次数: 4)

2019-5-24 19:20 上传

打开SymHook.h,发现符号对应的变量已成功生成:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片33.png (33.4 KB, 下载次数: 1)

2019-5-24 19:20 上传

(三)打开mod.cpp,编写插件代码,注意,这里的Hook宏的使用方式与MCMrARM那篇教程大致相同,有不同点但在mod.cpp内说明了。

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片34.png (45.35 KB, 下载次数: 0)

2019-5-24 19:22 上传

(四)编译出插件DLL,将它放在开服器目录MOD_DLL目录下,使用工具包中的“BDS简易启动器”启动服务器:

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片35.png (6.98 KB, 下载次数: 1)

2019-5-24 19:23 上传

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

图片36.png (4.33 KB, 下载次数: 3)

2019-5-24 19:23 上传

(五)测试爆炸箭

cc3f09d759d2cdb5ff85a1c6397f2a55.gif

file_1558697076000.jpg (202.56 KB, 下载次数: 3)

2019-5-24 19:24 上传

最后,实验成功!

注意事项:

1、当你在使用IDA Pro附加windbg(x64)调试的时候一定要先设置好windbg(x64)所在的位置,windbg可以通过Windows SDK安装包来安装,通过设置PATH变量或者更改IDA Pro目录下的/cfg/ida.cfg文件来让IDA Pro找到windbg(x64)。另外,当你发现设置没有问题但是无法启动调试的时候,请注意被调试的程序所在的文件路径,为稳妥考虑,路径中最好不要出现特殊字符或者中文,这些内容可能导致无法调试。我没有去测试到底是不是中文字符的问题。

2、MOD工程中的“T”开头的宏的使用方法参考MCMrARM的教程,如果你写过Linux上的BDS插件,那么你可能对它十分熟悉。另外,SYM_CALL宏是我自己写的,上面已经用注释说明了使用方法。

3、针对不同版本的开服器,插件互相是无法通用的,开服器使用不合适版本的插件将会导致严重错误,这也是为什么我将插件目录设置在开服器目录下而不是启动器目录下的原因。让插件适应当前版本的办法是用“PDB导出工具”将新版的符号重新生成出SymHook.h文件,然后再次编译插件。

4、如果你发现工具中存在的Bug,请反馈给我!在工具中的“关于”按钮内有我的网上联系方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ 协程_用yield实现协程

上一篇 理解python中的yield关键字 介绍了使用yeld实现生成器函数,这一篇我们来继续深入的了解一下yield,用yield实现协程。先来解答一下上一篇留下的问题:下面的代码为什么第二次调用next打印None呢?def 事实是这样的&#xff0c…

pandas 第一行_用Excel表格带你学习pandas最核心的处理操作,不再害怕条件统计

此系列文章收录在公众号中:数据大宇宙 > 数据处理 >E-pd转发本文并私信我"python",即可获得Python资料以及更多系列文章(持续更新的)经常听别人说 Python 在数据领域有多厉害,结果学了很长时间,连数据处理都麻烦得…

网页载入动画 php,网站页面加载动画代码

有时候网站服务器带宽不好或者用户网络不好,网站速度打开就会比较慢,那么用户等待就会比较无聊,下面准备了一个loading页面,可以在网站文件未完全加载完毕之前展示。HTML部分,放在body标签下面(最好是最靠近body)正在加…

ehcache缓存原理_贼厉害,手撸的 SpringBoot缓存系统,性能杠杠的!

缓存是最直接有效提升系统性能的手段之一。个人认为用好用对缓存是优秀程序员的必备基本素质。本文结合实际开发经验,从简单概念原理和代码入手,一步一步搭建一个简单的二级缓存系统。一、通用缓存接口1、缓存基础算法FIFO(First In First Ou…

angular 字符串转换成数字_Angular日期在TypeScript中格式化转换应用

组件模板中我们常常使用Angular内置管道DatePipe将其日期格式化,如同{{ startTime | date:yyyy-MM-dd }}这般操作,即可转换为字符串格式。那么在TS文件中我们也可以通过DatePipe或formatDate方法将其格式化。Angular日期在TypeScript中格式化转换应用​w…

python罗马数字转换,Python3.5实现的罗马数字转换成整数功能示例

本文实例讲述了Python3.5实现的罗马数字转换成整数功能。分享给大家供大家参考,具体如下:问题概述:给定一个罗马数字 ,将罗马数字转换成整数。如罗马数字I,II,III,IV,V分别代表数字 …

js在一个指定元素前添加内容_WebAR开发指南(1)---使用AR.js实现第一个WebAR demo...

前面有一篇文章万字干货介绍WebAR的实现与应用 分析了目前流行的WebAR框架并简单的介绍一些实现方法,这个专栏我们具体的来通过一些框架实现WebAR效果。关于AR.jsAR.js是一个轻量级的增强现实类JavaScript库,支持基于标记和位置的增强现实。开发人员可以…

python 最小二乘回归 高斯核_从简单数学建模开始:08最小二乘准则的应用(附python代码)...

模型拟合一般来说有这么三种:切比雪夫近似准则极小化绝对偏差之和最小二乘准则这几个原则各有各的适用范围。其中最小二乘准则是比较容易计算的。接下来我将简要的介绍最小二乘准则以及举例说明如何用python实现。最小二乘准则定义:给定某种函数类型 和 …

oracle 时间集合,oracle 日期函数集合(集中版本)第2/2页

oracle 日期函数集合(集中版本)第2/2页更新时间:2009年06月16日 23:45:55 作者:oracle 日期函数网上已经有了不少,特我们跟集中一下,免得大家麻烦。一、 常用日期数据格式1.Y或YY或YYY 年的最后一位,两位或三位SQL&g…

中缀表达式转后缀表达式两位数_再见,正则表达式!

从一段指定的字符串中,取得期望的数据,正常人都会想到正则表达式吧?写过正则表达式的人都知道,正则表达式入门不难,写起来也容易。但是正则表达式几乎没有可读性可言,维护起来,真的会让人抓狂&a…

php 腾讯云 文字识别_腾讯科技(成都)有限公司

成都IT内推圈是由IT行业老兵组建的民间组织,我们希望能为广大IT同仁提供力所能及的帮助,我们不仅提供靠谱的职位,我们更是有温度的圈子!为了帮助更多的朋友寻找到靠谱的内推职位,老农在此号召大家:1. 发布职…

oracle插入性能优化,Oracle- insert性能优化

看见朋友导入数据,花了很长时间都没完成!其实有很多快速的方法,整理下!向表中插入数据有很多办法,但是方法不同,性能差别很大.----1.原始语句drop table t1 purge;create table t1(sid number,sname varchar2(20)) tab…

winscp 自动断开无法连接_winscp教程,winscp教程,看完就学会的winscp教程

作为一个站长,当你的网站流量逐渐变大时,就会发现目前的主机无法满足正常需要,就要更换更高一级的云主机或VPS主机,新手就需要使用WinSCP和Putty,来管理主机。IIS7服务器管理工具可以批量管理、定时上传下载、同步操作…

oracle客户端数据恢复,AnyBackup-Oracle 数据恢复任务恢复到异客户端失败,并提示错误:数据源为空,请检查恢复环境是否授权...

关键字Oracle、数据源适用产品AnyBackup Express 7.0.6 - 7.0.8AnyBackup CDM 7.0.6 - 7.0.8问题描述登录 AnyBackup 管理控制台,依次点击定时数据保护 > 数据恢复 > 新建,新建 Oracle 数据恢复任务,选择恢复数据到异客户端&#xff0c…

linux祖先进程,Linux下的几种特殊进程

1、Linux的登录环境Linux是一个多任务多用户的操作系统,其设计初衷: 就是要达成多用户同时使用单个计算机大的任务。多用户:早期计算机资源紧张,为了让更多的人都可以使用。多任务:服务于多用户,同时提高计算机的吞吐量…

@select注解_SSM框架(十三):Spring框架中的IoC(3)新注解,完全摆脱xml文件

spring中的新注解1、Configuration作用:指定当前类是一个配置类细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。2、ComponentScan作用:用于通过注解指定spring在创建容器时要扫描的包属性…

element ui 多个子组件_ElementUI 技术揭秘(2) 组件库的整体设计

需求分析当我们去实现一个组件库的时候,并不会一上来就撸码,而是把它当做产品一样,思考一下我们的组件库的需求。那么对于 element-ui,除了基于 Vue.js 技术栈开发组件,它还有哪些方面的需求呢。丰富的 feature&#x…

arraylist线程安全吗_Java的线程安全、单例模式、JVM内存结构等知识梳理

java技术总结知其然,不知其所以然 !在技术的海洋里,遨游!做一个积极的人编码、改bug、提升自己我有一个乐园,面向编程,春暖花开!本篇以一些问题开头,请先不看答案,自己思…

【GitHub精选项目】抖音/ TikTok 视频下载:TikTokDownloader 操作指南

前言 本文为大家带来的是 JoeanAmier 开发的 TikTokDownloader 项目,这是一个高效的下载 抖音/ TikTok 视频的开源工具。特别适合用户们保存他们喜欢的视频或分享给其他人。 TikTokDownloader 是一个专门设计用于下载 TikTok 视频的工具,旨在为用户提供一…

python的界面文字翻译_一个把网站全英文转成中文的方法,让你轻松看懂python官网...

近日,在看python官网(英文网站)时,使用了有道翻译工具查看了几个专有名词。无意间,有了是不是可以输入网站地址进行翻译的想法,翻译后的网站地址点击进去后,又是一个什么情况呢?小编…