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