本帖最后由 Vinogradov 于 2019-8-22 20:31 编辑

史莱姆区块探测器

CustomModelData范围:13810001~13810003
介绍:

原版游戏中,要获取粘液球,往往需要建造史莱姆农场。而建造史莱姆农场的第一步就是找到史莱姆区块。一般找史莱姆区块全凭运气,比较麻烦。本原版模组添加了一种新的物品:史莱姆区块探测器,使得寻找史莱姆区块变得非常容易。

适用版本:

1.14.4

理论上1.14+都可以使用,但作者没有测试过。

使用方法与注意事项:

  • 加载附件中的资源包(必须)与数据包。
  • OP使用/seed命令获取种子并记录,然后执行命令

    1. /function slime:input/input
    复制代码

    效果如下
  • 将种子用此键盘输入。更改符号请按”+/-“键;如有输入错误或想重新输入(没有退格功能,如有输入错误必须重新输入)请按”CLEAR“键;输入完毕后请按‘ENTER”键(必须)。
  • 每击杀50只史莱姆(不分大小)会掉落一台史莱姆区块探测器(第一次击杀满50只会解锁成就)。
  • 探测器有三种工作状态:关闭/绿灯/红灯。在你获取探测器时,它处于关闭状态(黑色屏幕)。站在你想要检测的区块内,拿着探测器右键。如果该区块为史莱姆方块,则会亮绿灯

    ,若不是则亮红灯 ;两者皆会有tellraw提示。注意:绿灯/红灯不会自动熄灭。而每次检测时,如果该区块对应的灯的颜色与上次检测时的颜色相同,则屏幕颜色不会改变;而此时你仍然能够通过tellraw的提示与检测时探测器的动画(上下会动一下)来知道探测器的状态是否已经更新。注意:为了防止长时间卡顿,两次使用探测器的时间间隔必须长于30秒。否则你会见到如下提示:
  • 如果你想关闭探测器,可以在手持探测器时按两下f键即可。
  • 探测器没有耐久,可无限次使用。
  • 探测瞬间很可能会造成瞬间卡顿。
  • 请OP仔细输入种子。如果种子输入错误,本模组不会给出任何错误提示,且会给出错误的探测结果。
  • 作者没说要运行的function别瞎运行。
  • 如果检测结果不对,请务必告诉作者!!!!!!

原理讲解:

核心原理

以下引用自Wiki:

"Slime chunks"[edit]

Slimes spawn throughout the world (except mushroom islands) below level Y=40 regardless of light level, but only in certain chunks, 1 in 10 of all chunks. These "slime chunks" are determined pseudo-randomly by combining their chunk coordinates with the seed of the world:

  1. Random rnd = new Random(seed +
  2.                         (long) (xPosition * xPosition * 0x4c1906) +
  3.                         (long) (xPosition * 0x5ac0db) +
  4.                         (long) (zPosition * zPosition) * 0x4307a7L +
  5.                         (long) (zPosition * 0x5f24f) ^ 0x3ad8025f);
  6. return rnd.nextInt(10) == 0;
复制代码

That is, using the chunk coordinates to help generate a seed, a random number between 0 and 9 inclusive is generated, and if that number is 0, the chunk can spawn slimes. To convert world coordinates to chunk coordinates, divide by 16 and round down. Note that xPosition and zPosition are 32 bits integers.

换句话说,只要部分模拟Java的伪随机数生成器即可。这与之前作者写的Minecraft内计算字符串MD5没用任何技术上的本质区别,感兴趣的读者可以看一下那个帖子。

如果你翻阅了数据包中的函数文件,你会看到一个叫MathCraft的东西频繁出现,并伴有很多没有明显意义的记分板名。这是使用作者正在开发的一个运算库所生成的,目前以及可见的将来该运算库不会公开。

输入法

这只是个很稀疏平常的tellraw输入法,类似于乙稀_中国所写的中文输入法,不过更加迷你和简陋。另外这个输入法与本模组的核心功能是高度整合的,所以无法直接移植(虽然移植起来很方便)。

探测器

首先便是胡萝卜钓竿的右键检测,这几乎是原版模组制作者的基本技能了,在此不再展开。

其次探测器的三种状态实际是通过CustomModelData的值来区分的。而为了实现探测器工作时上下动一下的效果(实际上这是无奈之举,因为本来计划中的设计是让探测器亮屏几秒后自动关闭,但在实践时这有一些技术上的困难,所以没有这么做。于是为了让玩家知到探测器确实工作了,而不是仍然显示上次探测时的结果,就想办法添加了这一效果),实际将玩家手中的探测器replaceitem为关闭状态的探测器,然后再修改CustomModelData使其变为正确的颜色。

关闭探测器是标准的F键检测,自然也不必多说。

改进:

显然,本模组最大的问题在于需要人工输入种子。这是由于目前原版游戏内无法获取种子(这里说的获取是指把种子转化为二进制bit存入记分板一类的操作),而目前最多可以做到获取种子的补码的低32bit,而这是不够的。

另外,探测时会有卡顿。这是因为本模组整数运算的实现方式(所有整数全部转化为二进制位分开存入积分板,所有运算均在bit级上实现)及作者的运算库在生成mcfunction文件时(完全)没有优化(事实上要做0-overhead的抽象是非常难的,作者曾经尝试实现类似转移语义的东西,但会产生另一些问题。当然这已经超出本帖的讨论范围了。)。作者会在日后尝试手工优化,但目测改善程度有限。计算量与种子还有玩家的位置有很大的关系,可能检测时单tick运行的命令数会超过10w。

感谢

@ruhuasiyu 耐心地解答了作者一堆弱智的问题,教程给了作者很大启发

@xuan_su 好像也回答了我的一些问题

@折君 好像也回答了我的一些问题

@SPGoding 好像也回答了我的一些问题

@00ll00 忘了为啥要感谢他了

@zzzz_pku 忘了为啥要感谢他了



resourcepacks.zip (7.69 KB, 下载次数: 88)

slime.zip (40.98 KB, 下载次数: 119)



[groupid=546]Command Block Logic[/groupid]