本篇內容是生成村莊,生成其他建築的過程也差不多就不研究了(代碼太多也研究不完)
構造村莊組件數據
它的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, 1 + size)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.House1.class, 20, MathHelper.getRandomIntegerInRange(random, 0 + size, 2 + size)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.WoodHut.class, 3, MathHelper.getRandomIntegerInRange(random, 2 + size, 5 + size * 3)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.Hall.class, 15, MathHelper.getRandomIntegerInRange(random, 0 + size, 2 + size)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.Field1.class, 3, MathHelper.getRandomIntegerInRange(random, 1 + size, 4 + size)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.Field2.class, 3, MathHelper.getRandomIntegerInRange(random, 2 + size, 4 + size * 2)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.House2.class, 15, MathHelper.getRandomIntegerInRange(random, 0, 1 + size)));
list.add(new StructureVillagePieces.PieceWeight(StructureVillagePieces.House3.class, 8, MathHelper.getRandomIntegerInRange(random, 0 + size, 3 + size * 2)));
net.minecraftforge.fml.common.registry.VillagerRegistry.addExtraVillageComponents(list, random, size);
Iterator<StructureVillagePieces.PieceWeight> iterator = list.iterator();
while (iterator.hasNext())
{
// villagePiecesLimit = 0代表不生成,這裏直接去掉
if (((StructureVillagePieces.PieceWeight)iterator.next()).villagePiecesLimit == 0)
{
iterator.remove();
}
}
return list;
}
// 繼承自Well,說明水井是村莊的起點,每個村莊一定有水井
public static class Start extends StructureVillagePieces.Well
{
public WorldChunkManager worldChunkMngr;
/** Boolean that determines if the village is in a desert or not. */
public boolean inDesert;
/** World terrain type, 0 for normal, 1 for flap map */
public int terrainType;
public StructureVillagePieces.PieceWeight structVillagePieceWeight;
public List<StructureVillagePieces.PieceWeight> structureVillageWeightedPieceList;
public List<StructureComponent> field_74932_i = Lists.<StructureComponent>newArrayList();
public List<StructureComponent> field_74930_j = Lists.<StructureComponent>newArrayList();
public BiomeGenBase biome;
public Start()
{
}
public Start(WorldChunkManager chunkManagerIn, int componentType, Random rand, int x, int z, List<StructureVillagePieces.PieceWeight> pieces, int size)
{
super((StructureVillagePieces.Start)null, 0, rand, x, z);
this.worldChunkMngr = chunkManagerIn;
this.structureVillageWeightedPieceList = pieces;
this.terrainType = size;
BiomeGenBase biomegenbase = chunkManagerIn.getBiomeGenerator(new BlockPos(x, 0, z), BiomeGenBase.field_180279_ad);
this.inDesert = biomegenbase == BiomeGenBase.desert || biomegenbase == BiomeGenBase.desertHills;
this.biome = biomegenbase;
// 設置是否在沙漠
this.func_175846_a(this.inDesert);
}
// ...
}
public static class Well extends StructureVillagePieces.Village
{
// ...
/**
* Initiates construction of the Structure Component picked, at the current Location of StructGen
*/
public void buildComponent(StructureComponent start, List<StructureComponent> components, Random rand)
{
// 對水井周圍四個方向構造道路並加入組件
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX - 1, this.boundingBox.maxY - 4, this.boundingBox.minZ + 1, EnumFacing.WEST, this.getComponentType());
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.maxX + 1, this.boundingBox.maxY - 4, this.boundingBox.minZ + 1, EnumFacing.EAST, this.getComponentType());
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX + 1, this.boundingBox.maxY - 4, this.boundingBox.minZ - 1, EnumFacing.NORTH, this.getComponentType());
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX + 1, this.boundingBox.maxY - 4, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, this.getComponentType());
}
// ...
}
// 構造道路
private static StructureComponent func_176069_e(StructureVillagePieces.Start start, List<StructureComponent> components, Random rand, int x, int y, int z, EnumFacing facing, int componentType)
{
if (componentType > 3 + start.terrainType)
{
return null;
}
else if ( Math.abs(x - start.getBoundingBox().minX) <= 112
&& Math.abs(z - start.getBoundingBox().minZ) <= 112) // 不能離起點太遠
{
// 構造道路的包圍盒,保證不與其他組件重疊
StructureBoundingBox structureboundingbox = StructureVillagePieces.Path.func_175848_a(start, components, rand, x, y, z, facing);
if (structureboundingbox != null && structureboundingbox.minY > 10)
{
StructureComponent path = new StructureVillagePieces.Path(start, componentType, rand, structureboundingbox, facing);
int xCenter = (path.boundingBox.minX + path.boundingBox.maxX) / 2;
int zCenter = (path.boundingBox.minZ + path.boundingBox.maxZ) / 2;
int xSize = path.boundingBox.maxX - path.boundingBox.minX;
int zSize = path.boundingBox.maxZ - path.boundingBox.minZ;
int length = xSize > zSize ? xSize : zSize;
// 判斷中心生物羣系
if (start.getWorldChunkManager().areBiomesViable(xCenter, zCenter, length / 2 + 4, MapGenVillage.villageSpawnBiomes))
{
components.add(path);
// 加入優先構造的組件
start.field_74930_j.add(path);
return path;
}
}
return null;
}
else
{
return null;
}
}
public static class Path extends StructureVillagePieces.Road
{
// ...
// 構造道路包圍盒
public static StructureBoundingBox func_175848_a(StructureVillagePieces.Start start, List<StructureComponent> components, Random rand, int x, int y, int z, EnumFacing facing)
{
for (int length = 7 * MathHelper.getRandomIntegerInRange(rand, 3, 5); length >= 7; length -= 7)
{
// 向指定方向構造這個組件的包圍盒
StructureBoundingBox structureboundingbox = StructureBoundingBox.getComponentToAddBoundingBox(x, y, z, 0, 0, 0, 3, 3, length, facing);
// 沒有與已有組件重疊
if (StructureComponent.findIntersecting(components, structureboundingbox) == null)
{
return structureboundingbox;
}
}
return null;
}
public void buildComponent(StructureComponent start, List<StructureComponent> components, Random rand)
{
boolean hasNewComponent = false;
// 構造組件
for (int lengthOffset = rand.nextInt(5); lengthOffset < this.length - 8; lengthOffset += 2 + rand.nextInt(5))
{
StructureComponent component = this.getNextComponentNN((StructureVillagePieces.Start)start, components, rand, 0, lengthOffset);
if (component != null)
{
lengthOffset += Math.max(component.boundingBox.getXSize(), component.boundingBox.getZSize());
hasNewComponent = true;
}
}
for (int lengthOffset = rand.nextInt(5); lengthOffset < this.length - 8; lengthOffset += 2 + rand.nextInt(5))
{
StructureComponent component = this.getNextComponentPP((StructureVillagePieces.Start)start, components, rand, 0, lengthOffset);
if (component != null)
{
lengthOffset += Math.max(component.boundingBox.getXSize(), component.boundingBox.getZSize());
hasNewComponent = true;
}
}
// 構造左右兩邊新的道路
if (hasNewComponent && rand.nextInt(3) > 0 && this.coordBaseMode != null)
{
switch (this.coordBaseMode)
{
case NORTH:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.minZ, EnumFacing.WEST, this.getComponentType());
break;
case SOUTH:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY, this.boundingBox.maxZ - 2, EnumFacing.WEST, this.getComponentType());
break;
case WEST:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, this.getComponentType());
break;
case EAST:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.maxX - 2, this.boundingBox.minY, this.boundingBox.minZ - 1, EnumFacing.NORTH, this.getComponentType());
}
}
if (hasNewComponent && rand.nextInt(3) > 0 && this.coordBaseMode != null)
{
switch (this.coordBaseMode)
{
case NORTH:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.minZ, EnumFacing.EAST, this.getComponentType());
break;
case SOUTH:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY, this.boundingBox.maxZ - 2, EnumFacing.EAST, this.getComponentType());
break;
case WEST:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.minX, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, this.getComponentType());
break;
case EAST:
StructureVillagePieces.func_176069_e((StructureVillagePieces.Start)start, components, rand, this.boundingBox.maxX - 2, this.boundingBox.minY, this.boundingBox.maxZ + 1, EnumFacing.SOUTH, this.getComponentType());
}
}
}
// ...
}
public abstract static class Village extends StructureComponent
{
// ...
/**
* Gets the next village component, with the bounding box shifted -1 in the X and Z direction.
*/
protected StructureComponent getNextComponentNN(StructureVillagePieces.Start start, List<StructureComponent> components, Random rand, int yOffset, int lengthOffset)
{
if (this.coordBaseMode != null)
{
switch (this.coordBaseMode)
{
case NORTH:
return StructureVillagePieces.func_176066_d(start, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + yOffset, this.boundingBox.minZ + lengthOffset, EnumFacing.WEST, this.getComponentType());
case SOUTH:
return StructureVillagePieces.func_176066_d(start, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + yOffset, this.boundingBox.minZ + lengthOffset, EnumFacing.WEST, this.getComponentType());
case WEST:
return StructureVillagePieces.func_176066_d(start, components, rand, this.boundingBox.minX + lengthOffset, this.boundingBox.minY + yOffset, this.boundingBox.minZ - 1, EnumFacing.NORTH, this.getComponentType());
case EAST:
return StructureVillagePieces.func_176066_d(start, components, rand, this.boundingBox.minX + lengthOffset, this.boundingBox.minY + yOffset, this.boundingBox.minZ - 1, EnumFacing.NORTH, this.getComponentType());
}
}
return null;
}
// ...
}
// 構造組件,和構造道路差不多
private static StructureComponent func_176066_d(StructureVillagePieces.Start start, List<StructureComponent> components, Random rand, int x, int y, int z, EnumFacing facing, int componentType)
{
if (componentType > 50)
{
return null;
}
else if ( Math.abs(x - start.getBoundingBox().minX) <= 112
&& Math.abs(z - start.getBoundingBox().minZ) <= 112) // 不能離起點太遠
{
// 構造組件,保證不與其他組件重疊
StructureComponent component = func_176067_c(start, components, rand, x, y, z, facing, componentType + 1);
if (component != null)
{
int xCenter = (component.boundingBox.minX + component.boundingBox.maxX) / 2;
int zCenter = (component.boundingBox.minZ + component.boundingBox.maxZ) / 2;
int xSize = component.boundingBox.maxX - component.boundingBox.minX;
int zSize = component.boundingBox.maxZ - component.boundingBox.minZ;
int length = xSize > zSize ? xSize : zSize;
// 判斷中心生物羣系
if (start.getWorldChunkManager().areBiomesViable(xCenter, zCenter, length / 2 + 4, MapGenVillage.villageSpawnBiomes))
{
components.add(component);
// 加入後構造的組件
start.field_74932_i.add(component);
return component;
}
}
return null;
}
else
{
return null;
}
}
// 隨機選剩下的組件來構造
private static StructureVillagePieces.Village func_176067_c(StructureVillagePieces.Start start, List<StructureComponent> components, Random rand, int x, int y, int z, EnumFacing facing, int componentType)
{
// 剩下組件的總權重
int totalWeight = func_75079_a(start.structureVillageWeightedPieceList);
if (totalWeight <= 0)
{
return null;
}
else
{
// 嘗試構造structureVillageWeightedPieceList裏的組件5次
for (i = 0; i < 5; ++i)
{
// 加權隨機選一個組件
int weight = rand.nextInt(totalWeight);
for (StructureVillagePieces.PieceWeight piece : start.structureVillageWeightedPieceList)
{
weight -= piece.villagePieceWeight;
// 應該生成這個組件
if (weight < 0)
{
if ( !piece.canSpawnMoreVillagePiecesOfType(componentType) // 已達到數量限制
|| piece == start.structVillagePieceWeight // 上次已經生成這個了?
&& start.structureVillageWeightedPieceList.size() > 1)
{
break;
}
// 構造組件,根據不同的class調用不同的函數
StructureVillagePieces.Village component = func_176065_a(start, piece, components, rand, x, y, z, facing, componentType);
if (component != null)
{
// 已生成數量+1
++piece.villagePiecesSpawned;
start.structVillagePieceWeight = piece;
// 已達到數量限制則去掉這個組件
if (!piece.canSpawnMoreVillagePieces())
{
start.structureVillageWeightedPieceList.remove(piece);
}
return component;
}
}
}
}
// 構造路燈包圍盒,保證不與其他組件重疊
StructureBoundingBox structureboundingbox = StructureVillagePieces.Torch.func_175856_a(start, components, rand, x, y, z, facing);
if (structureboundingbox != null)
{
// 構造路燈
return new StructureVillagePieces.Torch(start, componentType, rand, structureboundingbox, facing);
}
else
{
return null;
}
}
}
// 計算剩下組件的總權重
private static int func_75079_a(List<StructureVillagePieces.PieceWeight> pieces)
{
boolean hasPiece = false;
int totalWeight = 0;
for (StructureVillagePieces.PieceWeight piece : pieces)
{
if ( piece.villagePiecesLimit > 0
&& piece.villagePiecesSpawned < piece.villagePiecesLimit)
{
hasPiece = true;
}
totalWeight += piece.villagePieceWeight;
}
return hasPiece ? totalWeight : -1;
}
這樣這個村莊的所有組件和它們的位置就決定好了,接下來該操作方塊生成整個村莊
生成村莊
在provideChunk之後還會調用populate函數,它的作用是給區塊加上礦石、樹、雪層之類的點綴,還會真正生成村莊等建築
調用populate函數的參數滿足以下條件:1)周圍4個區塊有且只有一個區塊不存在,2)參數爲這4個區塊中XZ座標最小的
它會調用這個函數,類名net.minecraft.world.gen.structure.MapGenStructure
public boolean generateStructure(World worldIn, Random randomIn, ChunkCoordIntPair chunkCoord)
{
// 嘗試載入保存的結構數據,recursiveGenerate也調用過
this.func_143027_a(worldIn);
// 用來構造4個區塊中心16*16的包圍盒
int xMin = (chunkCoord.chunkXPos << 4) + 8;
int zMin = (chunkCoord.chunkZPos << 4) + 8;
boolean generated = false;
for (StructureStart start : this.structureMap.values())
{
if ( start.isSizeableStructure() // 只有村莊實現了,非道路組件>2則返回true
&& start.func_175788_a(chunkCoord) // 只有神廟實現了
&& start.getBoundingBox().intersectsWith(xMin, zMin, xMin + 15, zMin + 15)) // 這個結構和包圍盒有重疊
{
// 生成結構和包圍盒重疊的部分
start.generateStructure(worldIn, randomIn, new StructureBoundingBox(xMin, zMin, xMin + 15, zMin + 15));
// 只有神廟實現了
start.func_175787_b(chunkCoord);
generated = true;
// 保存數據,recursiveGenerate也調用過
this.func_143026_a(start.getChunkPosX(), start.getChunkPosZ(), start);
}
}
return generated;
}
類名net.minecraft.world.gen.structure.StructureStart
/**
* Keeps iterating Structure Pieces and spawning them until the checks tell it to stop
*/
public void generateStructure(World worldIn, Random rand, StructureBoundingBox structurebb)
{
Iterator<StructureComponent> iterator = this.components.iterator();
// 遍歷結構所有組件
while (iterator.hasNext())
{
StructureComponent structurecomponent = (StructureComponent)iterator.next();
if ( structurecomponent.getBoundingBox().intersectsWith(structurebb) // 和包圍盒有重疊
&& !structurecomponent.addComponentParts(worldIn, rand, structurebb)) // 生成組件,如果生成失敗返回false
{
// 組件生成失敗
iterator.remove();
}
}
}
addComponentParts由子類實現,這裏只研究水井的實現吧
類名net.minecraft.world.gen.structure.StructureVillagePieces.Well
/**
* second Part of Structure generating, this for example places Spiderwebs, Mob Spawners, it closes
* Mineshafts at the end, it adds Fences...
*/
public boolean addComponentParts(World worldIn, Random randomIn, StructureBoundingBox structureBoundingBoxIn)
{
// 地面高度,默認-1
if (this.field_143015_k < 0)
{
this.field_143015_k = this.getAverageGroundLevel(worldIn, structureBoundingBoxIn);
if (this.field_143015_k < 0)
{
return true;
}
// 把包圍盒移動到地面
this.boundingBox.offset(0, this.field_143015_k - this.boundingBox.maxY + 3, 0);
}
// 填充水,兩個方塊參數是邊界方塊和填充方塊
this.fillWithBlocks(worldIn, structureBoundingBoxIn, 1, 0, 1, 4, 12, 4, Blocks.cobblestone.getDefaultState(), Blocks.flowing_water.getDefaultState(), false);
// 開口
this.setBlockState(worldIn, Blocks.air.getDefaultState(), 2, 12, 2, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.air.getDefaultState(), 3, 12, 2, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.air.getDefaultState(), 2, 12, 3, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.air.getDefaultState(), 3, 12, 3, structureBoundingBoxIn);
// 柵欄
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 1, 13, 1, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 1, 14, 1, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 4, 13, 1, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 4, 14, 1, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 1, 13, 4, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 1, 14, 4, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 4, 13, 4, structureBoundingBoxIn);
this.setBlockState(worldIn, Blocks.oak_fence.getDefaultState(), 4, 14, 4, structureBoundingBoxIn);
// 房頂
this.fillWithBlocks(worldIn, structureBoundingBoxIn, 1, 15, 1, 4, 15, 4, Blocks.cobblestone.getDefaultState(), Blocks.cobblestone.getDefaultState(), false);
// 底座的砂礫
for (int x = 0; x <= 5; ++x)
{
for (int z = 0; z <= 5; ++z)
{
if (z == 0 || z == 5 || x == 0 || x == 5)
{
this.setBlockState(worldIn, Blocks.gravel.getDefaultState(), z, 11, x, structureBoundingBoxIn);
this.clearCurrentPositionBlocksUpwards(worldIn, z, 12, x, structureBoundingBoxIn);
}
}
}
return true;
}
}
MC中沒有模型,建築全是硬編碼生成的…