Minecraft 1.12.2中,即使生成算法改变,末影之眼仍指向最近的末地堡
这是一篇《Minecraft攻略日记》。
环境
-
Minecraft 1.12.2 Java Edition
- Minecraft 1.12.2 Java Edition
- forgeSrc-1.12.2-14.23.4.2705
背景 -在《Minecraft》的陆地世界中,存在着通向末地要塞(Stronghold)的地方。
https://minecraft-ja.gamepedia.com/%E8%A6%81%E5%A1%9E
只有在世界上特定的地点才能找到它,必须投掷末影之眼进行探寻和攻略。末影之眼会飞向最近的末地遗迹。
好的,1.9版本更新时,终点要塞的数量从之前的3个增加到了128个。而且这些要塞似乎被配置在一个环状区域的电子壳中,每个壳一定有特定数量的要塞。

在下面的网站图中,图形之间不仅间隔不相等,而且角度也是不规律的。
- ジ・エンドに行くために、エンドポータル(要塞)を簡単に見つけるコツを解説 http://chanhino.com/minecraft-end-portal/

请表达这个疑问的中文近义词嗯,不过这里有一个问题。Ender Eye 是指最近的(距离上最短的)遗迹呢?还是指投掷坐标所属方块中的遗迹呢?
从处理上来看,显然后者更容易。将坐标转换为棋子位置并转化为要塞坐标即可求得。如果选择前者,至少需要了解周围数个要塞的情况。
此外,在英文版维基百科中写着要飞往最近的大本营。
- Eye of Ender https://minecraft.gamepedia.com/Eye_of_Ender
调查
为了解决这个谜团,我调查了末影之眼的右键点击处理方法(net.minecraft.item.ItemEnderEye.onItemRightClick)。在那里,他们使用以下代码来获取坐标。
BlockPos blockpos = ((WorldServer)worldIn).getChunkProvider().getNearestStructurePos(worldIn, "Stronghold", new BlockPos(playerIn), false);
BlockPos blockpos = ((WorldServer)worldIn).getChunkProvider().getNearestStructurePos(worldIn, "Stronghold", new BlockPos(playerIn), false);
似乎要计算要塞的坐标,需要通过一个返回“最接近的建筑物坐标”的函数指定要塞并进行获取,而不是在物品的事件中写明。通过以下的方法,成功到达了目的地。
-
- net.minecraft.world.gen.ChunkProviderServer.getNearestStructurePos
- net.minecraft.world.gen.ChunkGeneratorOverworld.getNearestStructurePos
这个方法net.minecraft.world.gen.structure.MapGenStronghold.getNearestStructurePos以及它的附属方法将返回最近的终点要塞的位置。
public BlockPos getNearestStructurePos(World worldIn, BlockPos pos, boolean findUnexplored)
{
if (!this.ranBiomeCheck) {
this.generatePositions();
this.ranBiomeCheck = true;
}
BlockPos blockpos = null;
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(0, 0, 0);
double d0 = Double.MAX_VALUE;
for (ChunkPos chunkpos : this.structureCoords) {
blockpos$mutableblockpos.setPos((chunkpos.x << 4) + 8, 32, (chunkpos.z << 4) + 8);
double d1 = blockpos$mutableblockpos.distanceSq(pos);
if (blockpos == null) {
blockpos = new BlockPos(blockpos$mutableblockpos);
d0 = d1;
} else if (d1 < d0) {
blockpos = new BlockPos(blockpos$mutableblockpos);
d0 = d1;
}
}
return blockpos;
}
private void generatePositions()
{
this.initializeStructureData(this.world);
int i = 0;
ObjectIterator lvt_2_1_ = this.structureMap.values().iterator();
while (lvt_2_1_.hasNext()) {
StructureStart structurestart = (StructureStart) lvt_2_1_.next();
if (i < this.structureCoords.length) {
this.structureCoords[i++] = new ChunkPos(structurestart.getChunkPosX(), structurestart.getChunkPosZ());
}
}
Random random = new Random();
random.setSeed(this.world.getSeed());
double d1 = random.nextDouble() * Math.PI * 2.0D;
int j = 0;
int k = 0;
int l = this.structureMap.size();
if (l < this.structureCoords.length) {
for (int i1 = 0; i1 < this.structureCoords.length; ++i1) {
double d0 = 4.0D * this.distance + this.distance * (double) j * 6.0D + (random.nextDouble() - 0.5D) * this.distance * 2.5D;
int j1 = (int) Math.round(Math.cos(d1) * d0);
int k1 = (int) Math.round(Math.sin(d1) * d0);
BlockPos blockpos = this.world.getBiomeProvider().findBiomePosition((j1 << 4) + 8, (k1 << 4) + 8, 112, this.allowedBiomes, random);
if (blockpos != null) {
j1 = blockpos.getX() >> 4;
k1 = blockpos.getZ() >> 4;
}
if (i1 >= l) {
this.structureCoords[i1] = new ChunkPos(j1, k1);
}
d1 += (Math.PI * 2D) / (double) this.spread;
++k;
if (k == this.spread) {
++j;
k = 0;
this.spread += 2 * this.spread / (j + 1);
this.spread = Math.min(this.spread, this.structureCoords.length - i1);
d1 += random.nextDouble() * Math.PI * 2.0D;
}
}
}
}
这个结构坐标(structureCoords)是一个由128个元素组成的数组,其中存储了要塞的坐标序列。当我们在未初始化的状态下访问要塞坐标时,才会首次执行计算处理(generatePositions)操作。根据看到的getNearestStructurePos函数,明显是在获取最近的要塞坐标。
关于要塞坐标的确定部分,本次不会进行(可能会在之后做,所以把代码备份作为参考资料)。