001    package net.minecraft.src;
002    
003    import java.util.List;
004    import java.util.Random;
005    
006    public abstract class ComponentVillage extends StructureComponent
007    {
008        /** The number of villagers that have been spawned in this component. */
009        private int villagersSpawned;
010    
011        /** The starting piece of the village. */
012        protected ComponentVillageStartPiece startPiece;
013    
014        protected ComponentVillage(ComponentVillageStartPiece par1ComponentVillageStartPiece, int par2)
015        {
016            super(par2);
017            this.startPiece = par1ComponentVillageStartPiece;
018        }
019    
020        /**
021         * Gets the next village component, with the bounding box shifted -1 in the X and Z direction.
022         */
023        protected StructureComponent getNextComponentNN(ComponentVillageStartPiece par1ComponentVillageStartPiece, List par2List, Random par3Random, int par4, int par5)
024        {
025            switch (this.coordBaseMode)
026            {
027                case 0:
028                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 1, this.getComponentType());
029                case 1:
030                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1, 2, this.getComponentType());
031                case 2:
032                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX - 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 1, this.getComponentType());
033                case 3:
034                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.minZ - 1, 2, this.getComponentType());
035                default:
036                    return null;
037            }
038        }
039    
040        /**
041         * Gets the next village component, with the bounding box shifted +1 in the X and Z direction.
042         */
043        protected StructureComponent getNextComponentPP(ComponentVillageStartPiece par1ComponentVillageStartPiece, List par2List, Random par3Random, int par4, int par5)
044        {
045            switch (this.coordBaseMode)
046            {
047                case 0:
048                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 3, this.getComponentType());
049                case 1:
050                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1, 0, this.getComponentType());
051                case 2:
052                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.maxX + 1, this.boundingBox.minY + par4, this.boundingBox.minZ + par5, 3, this.getComponentType());
053                case 3:
054                    return StructureVillagePieces.getNextStructureComponent(par1ComponentVillageStartPiece, par2List, par3Random, this.boundingBox.minX + par5, this.boundingBox.minY + par4, this.boundingBox.maxZ + 1, 0, this.getComponentType());
055                default:
056                    return null;
057            }
058        }
059    
060        /**
061         * Discover the y coordinate that will serve as the ground level of the supplied BoundingBox. (A median of all the
062         * levels in the BB's horizontal rectangle).
063         */
064        protected int getAverageGroundLevel(World par1World, StructureBoundingBox par2StructureBoundingBox)
065        {
066            int var3 = 0;
067            int var4 = 0;
068    
069            for (int var5 = this.boundingBox.minZ; var5 <= this.boundingBox.maxZ; ++var5)
070            {
071                for (int var6 = this.boundingBox.minX; var6 <= this.boundingBox.maxX; ++var6)
072                {
073                    if (par2StructureBoundingBox.isVecInside(var6, 64, var5))
074                    {
075                        var3 += Math.max(par1World.getTopSolidOrLiquidBlock(var6, var5), par1World.provider.getAverageGroundLevel());
076                        ++var4;
077                    }
078                }
079            }
080    
081            if (var4 == 0)
082            {
083                return -1;
084            }
085            else
086            {
087                return var3 / var4;
088            }
089        }
090    
091        protected static boolean canVillageGoDeeper(StructureBoundingBox par0StructureBoundingBox)
092        {
093            return par0StructureBoundingBox != null && par0StructureBoundingBox.minY > 10;
094        }
095    
096        /**
097         * Spawns a number of villagers in this component. Parameters: world, component bounding box, x offset, y offset, z
098         * offset, number of villagers
099         */
100        protected void spawnVillagers(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4, int par5, int par6)
101        {
102            if (this.villagersSpawned < par6)
103            {
104                for (int var7 = this.villagersSpawned; var7 < par6; ++var7)
105                {
106                    int var8 = this.getXWithOffset(par3 + var7, par5);
107                    int var9 = this.getYWithOffset(par4);
108                    int var10 = this.getZWithOffset(par3 + var7, par5);
109    
110                    if (!par2StructureBoundingBox.isVecInside(var8, var9, var10))
111                    {
112                        break;
113                    }
114    
115                    ++this.villagersSpawned;
116                    EntityVillager var11 = new EntityVillager(par1World, this.getVillagerType(var7));
117                    var11.setLocationAndAngles((double)var8 + 0.5D, (double)var9, (double)var10 + 0.5D, 0.0F, 0.0F);
118                    par1World.spawnEntityInWorld(var11);
119                }
120            }
121        }
122    
123        /**
124         * Returns the villager type to spawn in this component, based on the number of villagers already spawned.
125         */
126        protected int getVillagerType(int par1)
127        {
128            return 0;
129        }
130    
131        /**
132         * Gets the replacement block for the current biome
133         */
134        protected int getBiomeSpecificBlock(int par1, int par2)
135        {
136            if (this.startPiece.inDesert)
137            {
138                if (par1 == Block.wood.blockID)
139                {
140                    return Block.sandStone.blockID;
141                }
142    
143                if (par1 == Block.cobblestone.blockID)
144                {
145                    return Block.sandStone.blockID;
146                }
147    
148                if (par1 == Block.planks.blockID)
149                {
150                    return Block.sandStone.blockID;
151                }
152    
153                if (par1 == Block.stairCompactPlanks.blockID)
154                {
155                    return Block.stairsSandStone.blockID;
156                }
157    
158                if (par1 == Block.stairCompactCobblestone.blockID)
159                {
160                    return Block.stairsSandStone.blockID;
161                }
162    
163                if (par1 == Block.gravel.blockID)
164                {
165                    return Block.sandStone.blockID;
166                }
167            }
168    
169            return par1;
170        }
171    
172        /**
173         * Gets the replacement block metadata for the current biome
174         */
175        protected int getBiomeSpecificBlockMetadata(int par1, int par2)
176        {
177            if (this.startPiece.inDesert)
178            {
179                if (par1 == Block.wood.blockID)
180                {
181                    return 0;
182                }
183    
184                if (par1 == Block.cobblestone.blockID)
185                {
186                    return 0;
187                }
188    
189                if (par1 == Block.planks.blockID)
190                {
191                    return 2;
192                }
193            }
194    
195            return par2;
196        }
197    
198        /**
199         * current Position depends on currently set Coordinates mode, is computed here
200         */
201        protected void placeBlockAtCurrentPosition(World par1World, int par2, int par3, int par4, int par5, int par6, StructureBoundingBox par7StructureBoundingBox)
202        {
203            int var8 = this.getBiomeSpecificBlock(par2, par3);
204            int var9 = this.getBiomeSpecificBlockMetadata(par2, par3);
205            super.placeBlockAtCurrentPosition(par1World, var8, var9, par4, par5, par6, par7StructureBoundingBox);
206        }
207    
208        /**
209         * arguments: (World worldObj, StructureBoundingBox structBB, int minX, int minY, int minZ, int maxX, int maxY, int
210         * maxZ, int placeBlockId, int replaceBlockId, boolean alwaysreplace)
211         */
212        protected void fillWithBlocks(World par1World, StructureBoundingBox par2StructureBoundingBox, int par3, int par4, int par5, int par6, int par7, int par8, int par9, int par10, boolean par11)
213        {
214            int var12 = this.getBiomeSpecificBlock(par9, 0);
215            int var13 = this.getBiomeSpecificBlockMetadata(par9, 0);
216            int var14 = this.getBiomeSpecificBlock(par10, 0);
217            int var15 = this.getBiomeSpecificBlockMetadata(par10, 0);
218            super.fillWithMetadataBlocks(par1World, par2StructureBoundingBox, par3, par4, par5, par6, par7, par8, var12, var13, var14, var15, par11);
219        }
220    
221        /**
222         * Overwrites air and liquids from selected position downwards, stops at hitting anything else.
223         */
224        protected void fillCurrentPositionBlocksDownwards(World par1World, int par2, int par3, int par4, int par5, int par6, StructureBoundingBox par7StructureBoundingBox)
225        {
226            int var8 = this.getBiomeSpecificBlock(par2, par3);
227            int var9 = this.getBiomeSpecificBlockMetadata(par2, par3);
228            super.fillCurrentPositionBlocksDownwards(par1World, var8, var9, par4, par5, par6, par7StructureBoundingBox);
229        }
230    }