轻语

  • 首页
  • 分享
  • 技术
  • 生活
  • 插件
QingYu
分享美好生活
  1. 首页
  2. 分享
  3. 正文

BETweaker开发日志2

2022年3月19日 151点热度 5人点赞 0条评论

注:本文只是记录个人开发过程,可能有部分操作很奇怪或者不对,请见谅!

这不是教程!这不是教程!这不是教程!

前言

写完第一个功能后,有想到了之前玩JE的mod端时,可以右键收割作物。于是继续开始了寻找之旅。

一、开发思路

既然是右键收割,就需要用到LL的PlayerUseItemOnEvent事件了。这功能思路挺简单,玩家右键->判断是否成熟->生成对应作物掉落物->作物变成初始状态。

其实重点是获取作物的掉落物,打开IDA开始寻找相关内容,搜索"cropblock",如下图

CropBlock::spawnResources (生成资源)一眼看中,F5查看伪代码,可以发现生成作物掉落物分了两部分,其实很好理解,一半是种子,一半是作物。查询虚表后补齐对应函数名后,如下

主要看36,50,55行,分别获取了作物成熟等级,对应作物,掉落数量。(种子同理)

了解BDS对于作物收割的相关流程后,再根据BDS处理方块统一使用setBlock,所以恢复初始成长状态也基本能搞定,接下来开始实践。

二、实现过程

首先利用LiteLoader提供的PlayerUseItemOnEvent事件,获取到对应Block判断是否是作物方块(CropBlock),并获取它的成熟度,查阅wiki可知作物成熟度就是他的特殊值,那么利用LL提供的API直接获取。

bool LoadBetterHarvestingCrop(BlockInstance blockin) {
        auto bl = blockin.getBlock();
        if (bl->isCropBlock()) {
            auto growthlevel = bl->getTileData();
        }
}

随后判断是否已经成熟,也就是特殊值为7

bool LoadBetterHarvestingCrop(BlockInstance blockin, Player* sp) {
        auto bl = blockin.getBlock();
        if (bl->isCropBlock()) {
            auto growthlevel = bl->getTileData();
            if (growthlevel == 7) {
            }
        }
}

获取农作物对应的作物,这里我们直接利用LL导出的MCAPI,并判断获得的item不是错误的。随后获取掉落农作物的数量,并且调用BlockLegacy::popResource来生成掉落物,代码如下:

    bool LoadBetterHarvestingCrop(BlockInstance blockin, Player* sp) {
        auto bl = blockin.getBlock();
        if (bl->isCropBlock()) {
            auto growthlevel = bl->getTileData();
            if (growthlevel == 7) {
                auto& block = (CropBlock&)bl->getLegacyBlock();
                auto bs = blockin.getBlockSource();
                auto pos = blockin.getPosition();
                auto rand = Randomize(Random::getThreadLocal());
                auto Crop = block.getBaseCrop();
                if (!Crop.isNull())
                {
                    auto CropNum = block.getCropNum(rand, growthlevel, 0);
                    if (CropNum)
                        block.popResource(*bs, pos, Crop);
                }
            }
        }
        return true;
    }

有好奇的人就要问了,为啥cropNum用的是if,而不是for或者while?

在IDA看CropBlock::getCropNum后就知道答案了

这坨也就是说,只要a3(成熟值)大于等于7就一定返回true,也就是1个作物。所以在游戏里破坏完全成熟的作物,即使运气再背,也会掉落一个对应的作物。(萝卜马铃薯如果只掉一个,属实是种子那块随机到了0)

接下来到了种子环节,其实与上面差不多,只是if部分改为了while或者for和添加一个获取手上物品的时运等级(CropBlock::getSeedNum中用到),直接上代码:

    bool LoadBetterHarvestingCrop(BlockInstance blockin, Player* sp) {
        auto bl = blockin.getBlock();
        if (bl->isCropBlock()) {
            auto growthlevel = bl->getTileData();
            if (growthlevel == 7) {
                auto& block = (CropBlock&)bl->getLegacyBlock();
                auto bs = blockin.getBlockSource();
                auto pos = blockin.getPosition();
                auto rand = Randomize(Random::getThreadLocal());
                auto Crop = block.getBaseCrop();
                if (!Crop.isNull())
                {
                    auto CropNum = block.getCropNum(rand, growthlevel, 0);
                    if (CropNum)
                        block.popResource(*bs, pos, Crop);
                }
                auto Seed = block.getBaseSeed();
                if (!Seed.isNull())
                {
                    auto level = EnchantUtils::getEnchantLevel(Enchant::Type::fortune, *sp->getHandSlot());
                    auto seedNum = block.getSeedNum(rand, growthlevel, level);
                    --seedNum;
                    if (seedNum > 0)
                    {
                        do {
                            block.popResource(*bs, pos, Seed);
                            --seedNum;
                        } while (seedNum);
                    }
                }
            }
        }
        return true;
    }

好奇的人又要问了,中间为啥要--seedNum?右键直接收割种上了,减去一个种子不过分吧~

最后加上一个 Level::setBlock()来还原作物的初始生成状态就行了。

完整代码如下:

    bool LoadBetterHarvestingCrop(BlockInstance blockin, Player* sp) {
        auto bl = blockin.getBlock();
        if (bl->isCropBlock()) {
            auto growthlevel = bl->getTileData();
            if (growthlevel == 7) {
                auto& block = (CropBlock&)bl->getLegacyBlock();
                auto bs = blockin.getBlockSource();
                auto pos = blockin.getPosition();
                auto rand = Randomize(Random::getThreadLocal());
                auto Crop = block.getBaseCrop();
                if (!Crop.isNull())
                {
                    auto CropNum = block.getCropNum(rand, growthlevel, 0);
                    if (CropNum)
                        block.popResource(*bs, pos, Crop);
                }
                auto Seed = block.getBaseSeed();
                if (!Seed.isNull())
                {
                    auto level = EnchantUtils::getEnchantLevel(Enchant::Type::fortune, *sp->getHandSlot());
                    auto seedNum = block.getSeedNum(rand, growthlevel, level);
                    --seedNum;
                    if (seedNum > 0)
                    {
                        do {
                            block.popResource(*bs, pos, Seed);
                            --seedNum;
                        } while (seedNum);
                    }
                }
                Level::setBlock(blockin.getPosition(), blockin.getDimensionId(), bl->getTypeName(), NULL);
            }
        }
        return true;
    }

三、总结

通过实现这个功能,又可以知道BDS是如果处理作物的了,我的理解大概如下

  • 农作物掉落这块大概是:只要作物成熟了(特殊值达到7)必掉一个。
  • 种子这块大概是:如果成长值小于7,必掉落一个种子,否则就通过随机来获取数量,具体概率看wiki。有趣的是,如果时运等级小于等于-3,则不掉落作物。
  • 另外毒马铃薯是另外处理的~

 

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2022年3月19日

ADMIN

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

取消回复

ADMIN

这个人很懒,什么都没留下

归档
  • 2022年3月
  • 2021年12月
  • 2021年6月
  • 2021年5月
  • 2021年4月
最新 热点 随机
最新 热点 随机
BETweaker开发日志2 BETweaker开发日志1 使用LiteLoaderBDS2.0编写MCBE插件-2 使用LiteLoaderBDS2.0编写MCBE插件-1 狂野工艺行为包 CustomMap - 自定义地图[1.16.221]
HologramGlows - 全息文本[1.16.221] 使用LiteLoaderBDS2.0编写MCBE插件-1 CustomMap - 自定义地图[1.16.221] 狂野工艺行为包 BETweaker开发日志2 使用LiteLoaderBDS2.0编写MCBE插件-2
标签聚合
Minecraft
网站统计
  • 0
  • 292
  • 40
  • 794
  • 85
  • 337,878
  • 26,156
  • 98
  • 7
  • 2022年3月19日

COPYRIGHT © 2022 轻语. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang