本篇内容是生成村庄,生成其他建筑的过程也差不多就不研究了(代码太多也研究不完)
构造村庄组件数据
它的recursiveGenerate继承自这里,类名net.minecraft.world.gen.structure.MapGenStructure
// 只是生成结构数据,暂时不操作方块
protected final void recursiveGenerate(World worldIn, final int chunkX, final int chunkZ, int p_180701_4_, int p_180701_5_, ChunkPrimer chunkPrimerIn)
{
// 尝试载入保存的结构数据
this.func_143027_a(worldIn);
// 载入失败则生成
if (!this.structureMap.containsKey(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(chunkX, chunkZ))))
{
this.rand.nextInt();
try
{
// 子类实现判断能否生成
if (this.canSpawnStructureAtCoords(chunkX, chunkZ))
{
// 子类实现的生成数据
StructureStart structurestart = this.getStructureStart(chunkX, chunkZ);
this.structureMap.put(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(chunkX, chunkZ)), structurestart);
// 保存数据
this.func_143026_a(chunkX, chunkZ, structurestart);
}
}
catch (Throwable throwable)
{
// ...
}
}
}
村庄构造流程是这样的:计算村庄里的组件(田、房子、铁匠铺等),构造水井,构造水井周围的道路,沿着道路随机选之前计算好的组件来构造或者构造新的道路
类名net.minecraft.world.gen.structure.MapGenVillage
protected boolean canSpawnStructureAtCoords(int chunkX, int chunkZ)
{
int _chunkX = chunkX;
int _chunkZ = chunkZ;
// field_82665_g是村庄平均距离,默认=32
// field_82666_h是村庄最小距离,默认=8
// 所以在坐标为n * 32 + 12的区块附近比较可能找到村庄
// 防止在原点附近生成的村庄可能靠太近
if (chunkX < 0)
{
chunkX -= this.field_82665_g - 1;
}
if (chunkZ < 0)
{
chunkZ -= this.field_82665_g - 1;
}
// 注意这是整数除法
int keyChunkX = chunkX / this.field_82665_g;
int keyChunkZ = chunkZ / this.field_82665_g;
// 设置世界随机种子并返回Random对象
Random random = this.worldObj.setRandomSeed(keyChunkX, keyChunkZ, 10387312);
// 附近可以生成村庄的区块坐标
// keyChunkXZ * field_82665_g后变成了field_82665_g的倍数
keyChunkX = keyChunkX * this.field_82665_g + random.nextInt(this.field_82665_g - this.field_82666_h);
keyChunkZ = keyChunkZ * this.field_82665_g + random.nextInt(this.field_82665_g - this.field_82666_h);
if (_chunkX == keyChunkX && _chunkZ == keyChunkZ)
{
// 判断生物群系是否可以生成村庄
return this.worldObj.getWorldChunkManager().areBiomesViable(_chunkX * 16 + 8, _chunkZ * 16 + 8, 0, villageSpawnBiomes);
}
return false;
}
protected StructureStart getStructureStart(int chunkX, int chunkZ)
{
// terrainType默认为0,超平坦为1,影响村庄各组件数量
// 读取用的键名为size,所以后面就叫size了
return new MapGenVillage.Start(this.worldObj, this.rand, chunkX, chunkZ, this.terrainType);
}
public static class Start extends StructureStart
{
/** well ... thats what it does */
private boolean hasMoreThanTwoComponents;
public Start()
{
}
public Start(World worldIn, Random rand, int x, int z, int size)
{
super(x, z);
// 计算这个村庄的组件
List<StructureVillagePieces.PieceWeight> pieces = StructureVillagePieces.getStructureVillageWeightedPieceList(rand, size);
// 构造水井
StructureVillagePieces.Start startComponent = new StructureVillagePieces.Start(worldIn.getWorldChunkManager(), 0, rand, x * 16 + 2, z * 16 + 2, pieces, size);
this.components.add(startComponent);
// 这里构造了水井周围的道路并加入components和field_74930_j
startComponent.buildComponent(startComponent, this.components, rand);
// 构造子组件(一开始只有道路)
List<StructureComponent> list1 = startComponent.field_74930_j;
List<StructureComponent> list2 = startComponent.field_74932_i;
// 优先构造list1的组件(道路),然后构造list2的
while (!list1.isEmpty() || !list2.isEmpty())
{
if (list1.isEmpty())
{
// 随机顺序
int i = rand.nextInt(list2.size());
StructureComponent structurecomponent = (StructureComponent)list2.remove(i);
structurecomponent.buildComponent(startComponent, this.components, rand);
}
else
{
int j = rand.nextInt(list1.size());
StructureComponent structurecomponent2 = (StructureComponent)list1.remove(j);
structurecomponent2.buildComponent(startComponent, this.components, rand);
}
}
// 计算包围盒,使所有组件在包围盒内
this.updateBoundingBox();
// 计算除了道路的组件数量
int componentCount = 0;
for (StructureComponent component : this.components)
{
if (!(component instanceof StructureVillagePieces.Road))
{
++componentCount;
}
}
this.hasMoreThanTwoComponents = componentCount > 2;
}
// ...
}
类名net.minecraft.world.gen.structure.StructureVillagePieces
// 计算这个村庄的组件
public static List<StructureVillagePieces.PieceWeight> getStructureVillageWeightedPieceList(Random random, int size)
{
List<StructureVillagePieces.PieceWeight> list = Lists.<StructureVillagePieces.PieceWeight>newArrayList();
// 后两个参数是权重和数量(villagePiecesLimit)
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.House4Garden.class, 4, MathHelper.getRandomIntegerInRange(random, 2 + size, 4 + size * 2)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.Church.class, 20, MathHelper.getRandomIntegerInRange(random, 0 + size,