Minecraft钻石矿生成定位器①(版本:1.16和1.17的Java版本)

某天在我B站的推荐上出现了这个视频:

这个视频将我的世界(Java Edition)中的钻石矿生成机制实属搞明白了,但是要想从原理上理解这个算法,需要一点基础知识。

在此先特别感谢up主“一只冰迷”的授权。


 (一)钻石矿生成常识

一般地,版本为1.17以下的Java版中默认五个公理:

公理1:存在一个区块至少有一个钻石矿石;

公理2:存在一个区块,钻石矿石的位置是确定的;

公理5:所有区块的钻石矿生成高度在20m以下;

公理3:存在一个区块至少有一个青金石矿石,且青金石矿石的位置与钻石矿石的位置可以相互定位;

公理4:一个地图种子中的钻石矿石的位置是确定的。

为什么排序是个乱的?如果将这五个公理调换顺序就可以看出其重要性的排序了。


(二)钻石矿生成算法

我们可以推得如下定理:

定理1:地图种子和玩家所在区块决定钻石矿的生成位置。

公理1、公理4、公理2即可证明。

定理2:在高度为20m以下的矿区内只要青金石矿石就能找到钻石矿石。

公理3、公理5即可证明。

在这篇文章中我们先复现定理1,后面再复现定理2。

定理1可以用一个参数方程表示:

\large \left\{\begin{aligned} x=f_{1}(x_{0},y_{0},z_{0},s_{0})\\ y=f_{2}(x_{0},y_{0},z_{0},s_{0})\\ z=f_{3}(x_{0},y_{0},z_{0},s_{0}) \end{aligned}\right.

但是,这是一个定义式,真实情况是参数方程的求值及其困难。根据视频中作者提出的理论,我们先定义三个常数。

\large c_{1}=25214903917,c_{2}=281474976710655,c_{3}=60011.

其中,第三个常数通常被为版本常数,这里用的是1.17的Java版本的对应常数,如果是1.16的Java版本将值改为60009。第二个常数通常称为等比数列常数。第一个常数通过因式分解可以分成四个质数的乘积:

\large c_{1}=7\times443\times739\times11003

故可以称之为四质数常数

接下来就是最难的部分了。

根据视频中的理论,视频中告诉我们的是地图种子通过直接控制两个值从而间接控制钻石矿生成位置,视频里面设成(i,j)的意义在于类比向量的写法:空间直角坐标系内可以用三个单位向量的数乘表示所有向量。以下我将展开视频的流程一步一步讲透。

第一步:先求出种子常数\large s_{1}=s_{0}\, \wedge\, \left ( c_{1}\, \&\, c_{2} \right ).

第二步:构造递推数列\large s_{i+1}=\left(s_{i}c_{1}+11\right)\&\, c_{2},计算\large s_{2},s_{3},s_{4},s_{5}

第三步:求出地图种子控制常数组

\large \left\{\begin{aligned} A=\left [ (s_{2} >>16<<32)+(s_{3}<<16>>32) \right ] |\, 1\\ B=\left [ (s_{4} >>16<<32)+(s_{5}<<16>>32) \right ] |\, 1 \end{aligned}\right.

第四步:对玩家所在坐标取区块坐标,其中Floor函数为\large Floor(x)=\left \{ \begin{aligned} [x],x \geqslant 0\\ [x]-1,x < 0 \end{aligned} \right.

\large \begin{bmatrix} X\\ Y \end{bmatrix} = \begin{bmatrix} g(\frac{x}{16})\\ g(\frac{y}{16}) \end{bmatrix},g(x)=Floor(x)

第五步:求地图区块基数

\large b_{0}=\left[\left(16\begin{bmatrix} A & B \end{bmatrix}\begin{bmatrix} X\\ Y \end{bmatrix}\right)\wedge s_{0}\right]+c_{3}

第六步:模仿前三步,将地图区块常数、构造数列第二项和第三项依次求出:

\large b_{1}=b_{0}\, \wedge\, \left ( c_{1}\, \&\, c_{2} \right )\\ b_{i+1}=\left(b_{i}c_{1}+11\right)\&\, c_{2} \Rightarrow b_{2},b_{3}

第七步:将目的地区块坐标和绝对坐标求出:

\large \begin{bmatrix} X_{d}\\ Y_{d} \end{bmatrix} = \begin{bmatrix} b_{2}>>44\\ b_{3}>>44 \end{bmatrix}, \begin{bmatrix} x_{d}\\ y_{d} \end{bmatrix} =16 \begin{bmatrix} X\\ Y \end{bmatrix} + \begin{bmatrix} X_{d}\\ Y_{d} \end{bmatrix}

计算过程实质上是复合函数套来套去。最后得出的表达式是及其复杂的,这里不再写出来。至此已经将视频中的观点讲明白了。

检验:种子:-901706805885164814,版本1.17.1;

           第一组:(-207,29,64)推出(-193,23,14),正确;

           第二组:(-182,20,64)推出(-189,26,14),正确;

           第三组:(-214,53,64)推出(-215,49,6),由于铁矿石生成与钻石矿石生成冲突优先生成铁矿,有钻石矿石的坐标为(-215,48,6)。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,我会尽力回答你的问题。首先,你需要了解以下几个知识点: 1. Minecraft Forge:Minecraft Forge 是一个用于 Minecraft 的模组框架,可以帮助开发者更轻松地创建和管理模组。 2. Java 编程语言:Java 是一种广泛使用的面向对象编程语言,可以用于编写 Minecraft 模组。 3. Eclipse 集成开发环境:Eclipse 是一个流行的 Java 集成开发环境,可以帮助开发者更轻松地编写、调试和测试 Java 代码。 下面是一个简单的示例代码,它创建了一个新的方块,并且在玩家放置该方块时输出一条信息: ```java package com.example.examplemod; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.registry.GameRegistry; @Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION) public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; public static Block exampleBlock; @EventHandler public void init(FMLInitializationEvent event) { exampleBlock = new Block(Material.rock) .setHardness(2.0f) .setResistance(10.0f) .setUnlocalizedName("example_block") .setCreativeTab(CreativeTabs.tabBlock); GameRegistry.registerBlock(exampleBlock, "example_block"); GameRegistry.addShapelessRecipe(new ItemStack(exampleBlock), new ItemStack(Blocks.dirt)); GameRegistry.addSmelting(Blocks.stone, new ItemStack(exampleBlock), 0.1f); ItemBlock itemBlock = new ItemBlock(exampleBlock); itemBlock.setRegistryName(exampleBlock.getRegistryName()); GameRegistry.registerItem(itemBlock, itemBlock.getUnlocalizedName()); } } ``` 这段代码创建了一个名为 "example_block" 的新方块,它的贴图和材质与基岩块相同。在玩家放置该方块时,控制台会输出一条信息。该代码还注册了一个熔炉配方和一个无序合成配方,以及一个用于在创造模式下找到方块的创造标签。最后,该代码还注册了一个 ItemBlock,用于将方块添加到游戏中。 需要注意的是,这只是一个简单的示例代码,实际的 Minecraft 模组开发涉及到更多的知识和技能。如果你想深入了解 Minecraft 模组开发,建议你查阅相关的文档和教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金坷垃jin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值