根号Radical233
本帖最后由 根号Radical233 于 2023-9-29 16:08 编辑

        把自己之前写的东西搬运到这里了。希望能够帮助到有需要的人。
        为了防止你们看睡着,我在每章里面都附了音乐。
        之后会陆续出视频,里面应该还能更具体更直观。
        这篇文章献给公共领域(Licenced under Public Domain)。
第一章 综合思路

        1.Fabric和Forge模组的选择        Fabric多机制调整,更容易引发bug,某种意义上更适合整合包制作新人练手,积累经验;Forge模组多“新内容”,加很多一般不会导致直接的崩溃或者明显的bug,但是对于新手,游戏本身的平衡性难以保证。

        从未来的角度来看,Fabric整合包是大势所趋。未来Mojang可能做出更多优化,版本升级将成为重中之重,而许多高版本的Forge模组都正在向Fabric迁移。此外,随着Optifine的替代模组组合(钠与Iris)越来越热门,使用Optifine的必要性也越来越小。由此,Fabric整合包将会有更多新内容可以添加,也会有更好的优化,未来将不仅限于“原版改进”的整合包开发方向。

        2.游戏本身的平衡
        与之密切相关的就是“属性”。属性包括血量,攻击力等等(你可以在wiki上搜索这个词条)。属性需要有一个参照物,比如:武器上参照钻石剑,防具上参考钻石甲,小怪上参考僵尸,boss上参考凋零。别忘了分阶段,前中后期都需要有不同的参照物。

        平衡性是个很严肃的话题,对于模组,我们能调则调,不能就不要,要记住,这不是你的问题,这是模组作者的问题。如果你是玩家,在发现过强(op)的途径或物品时,千万记得向整合包作者汇报,这能帮作者完善整合包。这不是氪金手游,没必要藏着不说。

        3.打好框架
        你想做一个怎样的整合包?直接说可能说不上来,但是拆解开来就很好办了:

        难度:新手向,原版向,挑战向?
        主题:冒险?工业?魔法?
        游戏流程:短?中?长?
        游戏内节奏:慢?中?快?
        风格:漫画?中世纪?传说?原版?

        比如说,RLCraft,它是一款挑战向,冒险,长流程,快节奏,传说风格的整合包;再比如,JetpackCat,它是一款挑战向,中流程,快节奏,漫画风格的整合包;最后再比如我自己的整合包(没人问我但是我每天至少要为它花五个小时),Forget-Me-Not(对的对的对的我知道你们很期待),它是一款原版向,冒险风格,中流程,中节奏的原版风格整合包。

        想完这些问题之后,你心中的框架会更加清晰,选择模组也会更有方向。

        4.选择可靠的核心模组
        第一,选择在整合包版本有release的模组,alpha指内测版,beta指测试版,rc指候选版,release指正式版。

        第二,不要选没有当前版本的模组,模组更新全凭作者个人意愿,说不准作者会跳过你的版本。

        5.留意更新
        时刻关注当前版本的“last update”模组,不错过可能你正好想要的特性。注意,如果你追求整合包所使用的游戏版本上的新,那么,你应当适当降低对版本内模组更新的重视程度,否则,你很可能要等到下个大版本更新才能发布整合包。

        6.分阶段遍历
        在整合包制作的不同阶段(有较大的机制或方向改动时),遍历版本内所有模组(Fabric/Forge,版本过滤记得打开),温故而知新,以前你不感兴趣的模组,现在可不一定。

        参考的遍历速度,也就是我自己的,是200页/天。理论上早中晚分时段可以达到600页/天,但是这是我生理上不允许的。

        7.重视生理限制
        如果你有足够的耐心看到这里,这证明你可能是一位深度的整合包开发人员。整合包制作总是令人如痴如醉。有时限制我们的并不是时间,而是身体。在长时间浏览内容后,我们很容易陷入精神上与生理上的双重疲劳。

       生理上的疲劳主要指视疲劳,它会使你视线模糊,并大幅加重你的精神疲劳。所以,go outside and touch some grass!

        8.尊重他人
        国内很多作者对此并不重视,但这并不代表它不重要。第一,不要分发Minecraft的本体。分发本体是违反Minecraft最终用户许可协议的,简单来说,玩就代表同意协议,如果做不到,就别玩。

        第二,注意模组的licence,以及作者的说明。虽然大多数是MIT,CC0或者GPL3.0,但是仍有部分是ARR(保留所有权利),你需要格外留意ARR作者的说明,有的作者不允许自己的模组脱离curseForge的生态圈(比如,你不能放自己网盘里)。

        比较知名的是optifine,你只能引导玩家下载,并不能将它包含在整合包内。请不要觉得麻烦,尊重是最基本的,也是最必要的,还是那句简单粗暴的话:如果做不到,就不要使用。

        9.搞懂issue提交
        提交issue有以下几个部分:准备工作,分析问题,提交问题。

        准备工作。注册github账号,打开模组页面,点击“sources”或者“issues”(有的用的是curseForge内置的问题提交系统),找到模组的github页面。然后,搜索与你问题相关的关键词,如崩溃(crash),卡顿(lag),看看是否已经有同类的问题。

        分析问题。你需要明确,是这一个模组的问题,还是几个(一般为两个)模组共同导致的问题。运用在之前文章中说过的二分法,你很容易就能排查出这个,或这些模组。接下来,你需要把它们放到一个除必要前置外,别的都没有的环境里,再次测试。


        提交问题。有的作者会设计好issue的格式,但大多数不会。下面我将介绍通用的格式:

        1.游戏版本(game version),Fabric/Forge(loader),单人/多人(singleplayer/multiplayer);
        2.游戏环境(environment,就是模组文件夹里的所有模组);
        3.问题简介(description,简单介绍你遇到的问题);
        4.触发问题的步骤(steps to reproduce,分点详细说明操作);
        5.日志与崩溃报告(log/crash report,不要直接复制粘贴,最好使用网址,如Pastbin,https://pastebin.com/,来粘贴你的内容);
        6.截图(screenshot,能辅助说明问题的截图,非必要)。通过给出这些信息,你能帮助模组作者快速定位问题并及时修复之。注意,除非作者有特殊说明,请尽量使用英语(方便所有人阅读)。

        另外,你还可以请求新的功能(Feature Request),格式如下:

        1.这项功能是否与你游戏中遇到的不便有关?如果有,请简述。( Is your feature request related to a problem? Please describe.)
        2.说明你的解决方法。(Describe the solution you'd like.)
        3.说明你考虑的备选方案。(Describe alternatives you've considered.)
        4.其他相关信息。(Additional context.)

        要注意,这是一项请求,作者没有必要为你实现它。所以,最好从改善模组的角度考虑,而不是从个人需求的层面出发,注意语言得体。

        10.打出模组“组合拳”
        模组的“组合拳”出拳有道,我们需要对Minecraft进行模块化的拆解。下面将以“掉落物”这一模块为例。

        10.1掉落物模块
        1.为了让掉落物更自然,我们可以加入Item Physic模组;
        2.为了让玩家知道物品什么时候会消失,我们可以添加Clear Despawn模组(要消失前闪烁);
        3.为了告诉玩家掉落物在哪(因为贴地板上不明显),我们可以添加Drop Light模组(战利品光束);
        4.为了优化性能,我们可以加入Stxck模组(更远的掉落物合并);
        5.为了再次优化性能,我们可以加入Fabrication模组,为如小麦种子,腐肉等我们并不太需要捡起来的东西单独设置更短的消失时间。

        这听起来很周全,我是怎么想出来的?实际上,我根本想不出来这种组合,只是因为我看过了它们,才知道它们,最后才选择它们,并运用到刚才距离的“掉落物”模块中。

        不只是“掉落物”这种模块,模组的组合拳对于“问题”也有奇效。比如困扰玩家已久的“Inventory issue”(背包库存问题)。直接加大库存是治标不治本的,玩家只会浪费更多的时间在整理背包,分类无数种肉类上(或者我上一篇文章开篇讲到的泥土)。以下是我的解决方法,仅供参考。

        10.2背包库存问题
        首先,启用Interactic模组中的“手动拾取”功能,这样大大减少了被动捡起的“垃圾”。然后,用Fabricarion的自定义掉落物消失时间,让特定物品消失更快,进一步降低捡起垃圾的风险。

        接下来,我使用Diggus Maximus模组,在实现连锁采掘的同时,让玩家想要的方块能够直接进入背包,平衡心理。再下一步,我自定义了Andrometa模组中的可投掷物品,让一些垃圾可被投掷,赋予它们一些用途,让玩家得以“优雅”地摆脱它们(而不是直接烧掉、丢掉)。

        然后,我使用Stacker模组,重置了各类物品的堆叠上限,防止如圆石、红石、青金石一类的物品爆满。再之后(要没词了),我使用了Mouse Wheelie模组中的整理物品功能(绑定中键),让玩家快速整理背包,也是为了更好地适应堆叠上限的改变。

       还没完,我使用了Quick Shulker(好像是这个?)中的部分功能,让玩家能够在手持工作台时打开它,方便下矿的玩家直接合成粗矿块。

        倒数第二点,我使用kubejs,添加了自定义烧炼配方,让玩家能够烧炼粗矿块(时间9倍,经验9倍)。最后,我使用了Openloader,载入自定义数据包,将部分模组的掉落物原版化。对于如Mobz一类强行加入战利品箱的模组,我则使用了Item Ban来强硬地阻止它们生成。

        最后,在约16h的游戏实测中,我的背包几乎总能保持有空位的状态,即便极限状况下(两小时高强度挖矿),选择丢掉的物品也不过4个。箱子也只用了两个(小箱)多一点的容量。

        从这个实战例中不难得知,背包模组和高级箱子模组都不是必要的,我们完全有更优的解法。而这都要归功于我们的模组“组合拳”,而实现“组合拳”,全凭个人的模组阅历。

        11.体验方式
        在上面的例子中,我们在最后提到了游戏实测。游戏实测与普通游玩不同,我们应尽量与“一般玩家”保持一致。很多时候,你需要手动调整(比如:丢掉前期带时运的镐子,在创造模式下换成别的附魔),降低“好运气”或“坏运气”的影响。
        12.版本号命名
        可以参考Minecraft的命名,如1.18.2,其中,1是主版本号,有大的功能变化或兼容性改变时增加;18是子版本号,有一定内容或功能变化时增加;2是修订版本号,修复bug时增加。之前讲过了alpha,beta,rc与release,就不赘述了。结合以上所学,不难得知,你的第一个发布版本的版本号一般为“1.0.0_beta”。

        13.发布时机
        应尽可能避免大幅度的改动,内容确定稳定后再发布。整合包发布后更多的是加内容、做平衡,而不是做删减。

        这通常需要30小时以上的个人整合包体验,你需要比玩家更“懂行”(有什么路线可走,有什么捷径等等)。
第二章 整合包优化
        

        这个方案将分为两大部分:第一部分,事前优化,第二部分,事后优化。

        第一部分,事前优化。

        事前优化主要关于模组的选择。

       1. 尽量选择知名度高的作者(看注册时长以及模组下载量)的模组。较不知名的模组作者的模组也是可以选择的,但它们可能影响性能(作者可能编程经验并不丰富,导致模组性能低下)。

        2. 少就是好。这句话的前提是,你已经有制作大型整合包(模组数量超过200个)的经验,或者你已经遍历了整合包版本下的所有模组。请注意,对于整合包作者来说,这是基础的。

        这个点可以划分为两个小项,第一项,模组功能;第二项,模组数量。

        模组功能方面:比如:若A模组的功能被B模组涵盖在内,那么你应该选择B模组(能少则少)。

        模组数量方面:实现任何一项功能都是有开销的,若无关整合包核心玩法,就不要加入(睁一只眼闭一只眼)。比如:一个模组带来了大量bug修复内容,但是你不该一股脑全选上。模组终究不是对Minecraft本体的修改,如果确实看重这些修复,你应该优先考虑升级游戏版本(水管漏了,修水管才是根本,贴胶带只是暂缓之策)。

        最后补充一个整合包制作中非常重要的点:给模组分类命名。我的办法是,加上一个字母前缀标记,我的分类是:规则或机制调整、视听优化、新内容、主世界群系、维度、建筑、性能优化、前置模组。下面是与分类对应的模组举例:Debugify、Fancymenu、Terralith、BetterNether、Towns&Towers、Sodium、ForgeConfigAPIPort。这么做可以大大降低模组排查的难度。

        第二部分,事后优化。
        事后优化分为下面几个项目:简单优化、内存使用量、站立不动时的tps、区块加载性能、群系内性能、维度内性能。

        第一步是简单优化。

        使用spark模组,来到一个比较卡的地方,游戏内输入命令/sparkc profiler start --thread *,瞎跑五分钟,再输入/spark profiler stop,进入spark给出的网页,打开mods栏目,你可以看看哪些模组占用线程大,删掉,再启动试试。这就是最简单的优化。

        第二步是内存使用量的优化。

        首先,下载Memory a nalyzer,获取游戏进程的heapdump,查看是否存在内存泄漏的现象,如果有,先删除导致内存泄漏的模组(这通常是两个模组“配合”导致的),如果有实例占用了较高的内存,请找到对应的模组并考虑删除之(但这很难,除非占用量实在是太大)。

        第二步,把所有模组,除了前置类模组和性能类模组移动到其他的文件夹中(不要忘记暂时移除数据包和材质包 ),然后按类加入,我的顺序是:主世界群系→建筑→新内容→新生物→视听优化→机制调整→维度。这一步主要测试的是站立不动时的内存消耗量(跑图时内存开销主要由群系与建筑类模组导致)。现在,你需要记录gc前(内存消耗突然减少前) 最高的内存占用量,以及gc后的内存剩余百分比。你一般需要做两次记录(重启游戏,进同一个地图),取平均值,因为Minecraft每次启动都有些许不同。如果发现占用量上升幅度较大,你需要使用二分法进行排查,直到找到导致高占用的模组。

        二分法是什么?

        二分法是你排查的利器,也是传统意义上的“笨方法”。这与数学上的二分法相似。举个例子,在机制调整类模组中,有30个模组,为了排查出问题模组,你需要将它分成15,15的两块,然后确定这个模组在哪块里,然后再分成7,8的两块……不断反复这个过程,你最终能找到问题模组(可能不止一个)。这个办法在很多情况下都有效,不只是排查高占用模组。只要是排查,你大概就会用到这个方法。


        有个小技巧,分块中的东西较少时,你可以分为“比较怀疑的”和“没那么怀疑的”,提升效率。最后提供一些值得怀疑的,会导致内存占用高的东西:精致的3D生物(模型),大量配方的加入,大量的新内容。

        以上就是内存优化。接下来是站立不动时的tps。        这一部分,你需要再次移除所有模组,然后分类加入、二分排查。
        是的,整合包优化就是这样一个不断迭代的过程,简单来讲,就是累、麻烦。但是做好一个优化良好的整合包,能带给你的成就感也是很大的。

        我的方法是“红线法”:

        进游戏不动三十秒,按alt+f3打开调试界面,按win+shift+s打开系统自带截图截下右边的框,粘贴进绘图软件(第三图层),用红色的直虚线描一条平均tps的基准线(第一图层) ,加入模组,截图调试信息,粘贴进绘图软件(第二图层,别忘记对齐像素,截图时往下额外取一点)。如果高出来了,就找到导致问题的模组,单独放一个文件夹里。在这一部分,你可能会排查出一些看起来非常“无辜”的模组——“这个模组只是添加了一个音效,为啥?”这就是为什么我在之前建议说要选择知名度较高的作者,有的模组作者经验并不丰富,可能为了实现功能,忽视性能,或者干脆就是初学者,写得一般。什么?你说用mcreator制作的模组?整合包不加入这种模组可是基础知识。

        接下来我也会分享一些值得怀疑的东西:环境音效(检测周围方块),血量显示(检测范围内所有生物),背包检测……这里加省略号是因为例子是在太多,用原理解释,就是“检查(check)和获取(get)”,在不在生物群系里,看不看得到天空,亮度多少,周围有什么,生物血量有多少...还有一大堆乱七八糟的。

        第三部分,区块加载性能。

        世界生成的部分参考文章:https://www.alanzucconi.com/2022/06/05/minecraft-world-generation/。Minecraft的地形生成包括:biome map(群系,如沙漠、海洋),terrain(地形,就是地形高度,海平面以下用水填充),surfaces(地表方块,如草方块、沙子、沙砾),caves(洞穴),structures(建筑,如沙漠神殿),decorations(地形装饰,如花、草、树)。所以现在,你应该知道,一些加入了群系的模组做了什么(主要是群系与地形),一些加入了地牢的模组做了什么(建筑),一些加入了植物的模组做了什么(地形装饰)。为了改进区块加载的性能,这类模组可不能加多了。

        是否你有这样想过:“这个模组的XX建筑我喜欢,但是别的无所谓”?我来教你怎么实现对建筑生成的控制。首先,看模组配置文件,如果能关闭生成,或者进行其他调节,那么皆大欢喜,但是如果不能,就让我们来到第二步。

        第二步,用压缩包形式打开模组,复制data文件夹到单独的文件夹中,然后进入data/【模组名】/worldgen/configured_structure_feature,你可以通过改写“biomes”一栏,调节允许建筑生成的群系(做完后,除了configured_structure_feature文件夹,别的可以删了)。

        如果你不喜欢某个群系模组里面的某些花、草或者树,你可以重复上述步骤,打开configured_feature文件夹,把其中的内容替换为:{"type": "minecraft:no_op","config": {}}  ,这样,它就不会生成了。

        为了方便,你可以在data文件夹下创建下列路径:data\minecraft\tags\worldgen\biome ,在其中新建后缀名为.json的文件,对指定的群系进行分类,例如:

文件名:hot.json
内容:
{
  "pack": {
  "pack_format": 9,
  "description": "Description here."
  }
}复制代码




         这样,我就把炎热的群系做了标签分类,以后使用这类群系时,只需要写"#minecraft:hot"就行了。你也可以留空("values": []),什么都不生成(用来禁用建筑生成)。

        这个打标签的方法可以省下不少功夫。你会在很多场景下运用到它。如果不知道文件的结构,你只需要打开相关模组文件夹,一顿抄(文件结构的模仿属于学习用途)就行了。

        值得注意的是,Terralith(所有Starmute的模组)只允许对建筑的修改,不允许对configured_structure_feature相关内容的修改!修改这些内容前,千万记得看模组的license,避免侵犯作者的权利。

        数据包的格式:1.data文件夹,2.pack.mcmeta。

       pack.mcteta是必要的文件,示例内容如下:

{
  "pack": {
  "pack_format": 9,
  "description": "Description here."
  }
}复制代码
        做好数据包后,你可以用openloader之类的全局数据包加载模组来载入。不要直接修改模组本体文件!

        第四部分,群系内性能与维度内性能。
        用的方法一样,就合一块儿讲了。方法和简单优化部分一样,但是我会额外讲一些内容。

        群系内的卡顿有很多导致的因素,比如方块更新、实体运作。方块更新,经典的就是太多树叶的地方,这种地方常常会有检测“是否这是树”,“是否范围内有树叶”,然后更新方块状态。有一些功能与它们相关:环境音效、树叶快速腐烂。在沼泽内,则可能会有很多关于水的方块更新。

        实体运作:太聪明的实体并不好:兔子,它移速快,能很快到达目标点,喜欢瞎蹦跶;蝙蝠,这玩意的行动轨迹计算比较困难(飞行生物),没事还要挂天花板上休息会儿;美西螈,水路两栖,开销两路;龙(就是在说ice&fire),作为敌对生物,它飞得高,需要检查超大范围内(地上)的目标。如果这些生物生成频繁,但是你并不需要它们,就把它们放生到游戏外吧。
第三章 模组兼容性


        我承认阁下群系很多,但是倘若我拿出高原土,冻土,永冻土,草甸土,泥炭土,阁下的背包又该如何应对?

        今天,让我来讲讲整合包中,创造模组兼容性,减少重复物品的两样神器:数据包与kubejs模组。

        数据包方面,我将分为以下几点依次讲解:制作准备,基本格式,用法,以及纠错。

        制作准备方面,你需要下载VSCode这一软件,在制作数据包过程中,你需要打开大量.json文件,这款软件可以防止你出现语法错误。

        数据包对语法的准确度要求较高,常见错误比如:缺少逗号,缺少},混淆英文逗号与中文逗号。上面的例子会直接导致数据包错误,存档无法进入,而“使用了不存在的东西”并缺少“required:false”时,这个json将失效。至于怎么看是否失效,就是后话了,我们会在“纠错”中了解。

        此外,最好下载全局数据包模组(如open loader)来载入数据包,节省手动导入的时间。

        基本格式方面。
        数据包有两大组成部分,第一,data文件夹,也就是你要修改的内容第二,pack.mcmeta,这是形式上必备的文件,示例内容如下:{  "pack": {  "pack_format": 9,  "description": "Description here."  }}至于具体格式,你可以查阅维基:https://minecraft.fandom.com/zh/wiki/教程/制作数据包。看完了吗?其实不用看。格式可以直接用抄的,复制粘贴就行了,要用时再看维基。

        用法方面,这个可以分为以下几个小点:战利品表,标签以及其他。
        战利品表,听起来很复杂,实际上专注于“战利品”三字就行。这里,“战利品”这一概念极为宽泛,也就是说,通过挖掘方块,开启箱子,或者击杀生物所获得的掉落物,都算“战利品”。

        对于方块的战利品,你有什么想法?煤矿掉落煤炭,但是通过修改战利品表,我们可以使煤矿“小概率”“额外”掉落“最少一颗最多两颗”钻石。这时,我们的战利品表如下:

…(省略原版的内容)
    {
      "rolls": {
        "min": 1,
        "max": 2  //你可以在这里设置两个
        },
          "conditions": [
            {
              "condition": "random_chance",
              "chance": 0.01  //小概率
            }
          ],
        "entries": [
          {
            "type": "item",
            "weight": 1,  //并不必要加的权重
            "name": "minecraft:diamond",
            "functions": [
              {
                "function": "set_count",
                "count": {
                  "min": 1,
                  "max": 2  //你也可以在这里设置两个
                }
              }
            ]
          }
        ]
      }
…(省略原版的内容)复制代码




        当然,方块的战利品表可不止能用来爆钻石。你可以“加一些东西”,比如,破坏刷怪笼给予玩家奖励;还可以“减一些东西”,比如,你不希望玩家获得某方块,于是你把这个方块的战利品表删个干净;更可以“改一些东西”,比如,你不想要“高原土”掉落“高原土”,于是你改为原版的“泥土”;甚至还能“造一些东西”,比如,你想鼓励玩家探索地底,于是,你让所有深板岩矿物概率有双倍掉落。

        对于箱子的战利品,我们能做什么?我这里也有一些例子:你可以在丛林神庙的箱子里加上本不会出现的“香蕉”,你可以为每个地牢生成类模组的箱子自定义战利品。

        对于生物的战利品,你以为我要问你,但是我不问。前面已经举完例子了。

        标签方面。

        标签主要是为了兼容设计的,具体能兼容什么,那得看作者心情,所以,最好在加入有“新内容”的模组时,打开(如果有)它的data文件夹,看一眼标签。

        比如,A模组加入了鸭蛋和鸭肉,你希望鸭蛋被认为是蛋类,而鸭肉被认为是鸡肉类,在农夫乐事模组中派上用场,你可以把“鸭蛋”加入到“eggs”标签中,“生鸭肉”加入到“raw_chicken”中,“熟鸭肉”加入到“cooked_chicken”中(这类标签你可以打开待兼容模组的data文件夹查看)。

        打开minecraft本体的data文件夹,进入tags文件夹中,你能看到原版的标签,比如“freeze_immune_entity_types”(免疫寒冷伤害的生物),“piglin_loved”(猪灵喜欢的物品)。有时候,模组作者会忘记打上标签,这时候,就该你出场了。

        纠错方面。

        你需要进入.minecraft/logs,打开latest.log,也就是最近一次启动日志。日志能够记录下各种事件,便于排错,而分析日志是制作整合包的基础技能。

        如果你无法进入存档,在日志中搜索“安全模式”,向上翻,你能找到导致无法进入存档的原因;如果你想确认是否数据包生效,你可以搜索“couldn”和“a string”,然后遍历所有选项。如果你自定义了大量内容,那么你可能“收获颇丰”。

        最后,让我们稍作总结。相信你对我在之前文章中写到的“少就是好”有了进一步的理解,每多一个“新内容”型模组,一位优秀的整合包作者就要多掉一根头发,随着同类别“如美食,怪物”模组的不断加入,工作量甚至会呈指数级增长。

       虽然数据包已经能应对绝大部分需求,但是这还不足以做到“完全掌控”。kubejs模组的使用,将把你的整合包制作水平抬上新的高度。最多的工作量,给控制欲最强的你。

        这里,我将从兼容性拓展的角度,依次讲解“配方”与“新物品”,谈谈kubejs的用法。

        kubejs的维基:https://wiki.latvian.dev/books/kubejs,你可以在这里找到各种用法与示例。

        配方方面。

        在谈数据包时,我没有说到“标签”这一部分,原因就在于此。kubejs提供了强大的配方自定义手段,比如,你可以禁止用木棍进行合成:

event.remove({input: 'minecraft:stick'})复制代码




        你还可以禁止合成出木棍:

event.remove({output: 'minecraft:stick'})复制代码




        你甚至还能直接禁用某个模组(名字点开模组文件的assets可以看到)的所有配方:

event.remove({mod: 'minecraft'})复制代码




        加入有序或无序合成配方的就不举例了,维基上都有示例。

        新物品方面。这里直接上实战例子:模组A加入了新材料,钢;模组B加入新武器类别,镰刀,但很可惜,并不存在“钢镰刀”这一物品。我们可以通过kubejs手动加入钢镰刀。

        首先,我们创建一个材料等级,叫做钢(steel)。在.minecraft\kubejs\starup_scripts文件夹下新建文件steel.js(名字随意,后缀固定)。

onEvent('item.registry.tool_tiers', event => {
    event.add('steel', tier => {
      tier.uses = 2281  //耐久度
      tier.speed = 10.0  //挖掘速度
      tier.attackDamageBonus = 4.0  //攻击力改变,基础值为4,改变值为4,最终攻击力为8
      tier.level = 4  //挖掘等级
      tier.enchantmentValue = 15  //附魔能力
      tier.repairIngredient = 'a:steel'  //修复材料
    })
})复制代码




        然后,我们需要注册这个物品(Steel Scythe)。同文件夹内新建文件registry.js。

onEvent('item.registry', event => {
  //其中,speedBaseline是攻击速度改变,基础值为4,改变值为-2.7,最终攻击速度为1.3。
  event.create('steel_scythe', 'sword').tier('steel').attackDamageBaseline(4.0).speedBaseline(-2.7)
})复制代码
        接下来,我们需要翻译它(英文默认加大写,并将下划线改为空格,这里省去英文翻译)。在.minecraft\kubejs\assets\kubejs下新建一个名为“lang”的文件夹,在其中新建zh_cn.json。

{
  "item.kubejs.steel_scythe":"钢镰刀"
}复制代码
        最后,我们需要为它创建材质,加上模型。在.minecraft\kubejs\assets\kubejs\textures\item下,创建你的材质(通常为16x16),然后重命名为steel_scythe.png。在模型方面,在.minecraft\kubejs\assets\kubejs\models\item下新建文件steel_scythe.json。

{
  "parent": "minecraft:item/handheld",
  "textures": {
    "layer0": "kubejs:item/steel_scythe"
  }
}复制代码
        内容并不一定是这个,比如在安装了SimplySwords模组后,你可以使用他们的镰刀模型:

{
  "parent": "simplyswords:item/big_handheld",
  "textures": {
    "layer0": "kubejs:item/steel_scythe"
  }
}复制代码
        完美!现在你已经成功为A模组与B模组牵线搭桥,它们之间的兼容性因为你更好了。

        我并不打算单独把“纠错”放在一个一级段落里面讲。你只需要打开logs文件夹,看kubejs创建的日志文件就好了。

        这仅仅只是一个武器类别,一种材料。通过数学上排列组合的知识,这两个变量的增加会带来多少种可能性,我就不必多说了。不过,kubejs的能力远不止于此,这篇文章只是从改善兼容性的角度来使用它的,只要善用它,你甚至能够制造出“迷你模组”。


        就到这里。很多人常说(或者这么炫耀自己的见解):整合包不是看模组数量多少,而是看模组之间的搭配。模组间的兼容性一直是整合包作者们需要关注的命题。读完这篇文章,你对添加新模组,是少一分顾虑,还是多一分顾虑呢?

第四章 jvm优化参数


        我发现,虽然帧数能保持在150以上(甚至200),但Minecraft看起来仍然有一些卡顿。在进行整合包的jvm参数调优的过程中,我注意到了Shenandoah这款垃圾收集器,用它代替G1后,虽然帧数提升不大,但是游戏的画面流畅度得到了极大提升。这对有较多自定义地形和建筑的整合包有着尤为明显的提升。

        这是我整合包使用的jvm参数,应该能兼容配置需求更低的整合包,或者原版:

        传统G1垃圾收集器:
-Xmx5G -Xms5G -Xss1m -XX:+UnlockExperimentalVMOptions -XX:ParallelGCThreads=8 -XX:CICompilerCount=3 -XX:ConcGCThreads=3 -XX:G1ConcRefinementThreads=13 -XX:-DontCompileHugeMethods -XX:-UseAdaptiveSizePolicy -XX:+SegmentedCodeCache -XX:ReservedCodeCacheSize=184m -XX:NonProfiledCodeHeapSize=96m -XX:ProfiledCodeHeapSize=82m -XX:NonNMethodCodeHeapSize=6m -XX:MetaspaceSize=264m -XX:MaxMetaspaceSize=264m -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1NewSizePercent=25 -XX:G1MaxNewSizePercent=30 -XX:G1ReservePercent=15 -XX:G1HeapRegionSize=32m -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:G1MixedGCCountTarget=4  -XX:+AlwaysPreTouch -XX:+PerfDisableSharedMem -XX:+UseStringDeduplication -XX:+UseNUMA -XX:+UseNewLongLShift -XX:+UseVectorCmov -XX:+UseFastStosb -XX:+UseLargePages -XX:+UseCompressedOops -XX:+UseCompressedClassPointers复制代码

        更新的(更好的)Shenandoah垃圾收集器:
-Xms8G -Xmx8G -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+SegmentedCodeCache -XX:ReservedCodeCacheSize=192m -XX:NonProfiledCodeHeapSize=96m -XX:ProfiledCodeHeapSize=84m -XX:NonNMethodCodeHeapSize=12m -XX:MetaspaceSize=384m -XX:+AlwaysPreTouch -XX:+PerfDisableSharedMem  -XX:+UseNUMA -XX:+UseNewLongLShift -XX:+UseVectorCmov -XX:+UseFastStosb -XX:-DontCompileHugeMethods -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UseLargePages复制代码

        附录:大页面支持你可以启用large page support(大页面支持)来提升渲染速度。方法:控制面板\系统和安全\管理工具\本地安全策略\本地策略\用户权限分配,找到“锁定内存页”,添加当前计算机账户。

第一页 上一页 下一页 最后一页