001package net.minecraft.world.gen.structure; 002 003import java.util.HashMap; 004import java.util.Iterator; 005import java.util.List; 006import java.util.Map; 007import java.util.Random; 008import net.minecraft.crash.CrashReport; 009import net.minecraft.crash.CrashReportCategory; 010import net.minecraft.util.ReportedException; 011import net.minecraft.world.ChunkCoordIntPair; 012import net.minecraft.world.ChunkPosition; 013import net.minecraft.world.World; 014import net.minecraft.world.gen.MapGenBase; 015 016public abstract class MapGenStructure extends MapGenBase 017{ 018 /** 019 * Used to store a list of all structures that have been recursively generated. Used so that during recursive 020 * generation, the structure generator can avoid generating structures that intersect ones that have already been 021 * placed. 022 */ 023 protected Map structureMap = new HashMap(); 024 025 /** 026 * Recursively called by generate() (generate) and optionally by itself. 027 */ 028 protected void recursiveGenerate(World par1World, int par2, int par3, int par4, int par5, byte[] par6ArrayOfByte) 029 { 030 if (!this.structureMap.containsKey(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par2, par3)))) 031 { 032 this.rand.nextInt(); 033 034 try 035 { 036 if (this.canSpawnStructureAtCoords(par2, par3)) 037 { 038 StructureStart structurestart = this.getStructureStart(par2, par3); 039 this.structureMap.put(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par2, par3)), structurestart); 040 } 041 } 042 catch (Throwable throwable) 043 { 044 CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception preparing structure feature"); 045 CrashReportCategory crashreportcategory = crashreport.makeCategory("Feature being prepared"); 046 crashreportcategory.addCrashSectionCallable("Is feature chunk", new CallableIsFeatureChunk(this, par2, par3)); 047 crashreportcategory.addCrashSection("Chunk location", String.format("%d,%d", new Object[] {Integer.valueOf(par2), Integer.valueOf(par3)})); 048 crashreportcategory.addCrashSectionCallable("Chunk pos hash", new CallableChunkPosHash(this, par2, par3)); 049 crashreportcategory.addCrashSectionCallable("Structure type", new CallableStructureType(this)); 050 throw new ReportedException(crashreport); 051 } 052 } 053 } 054 055 /** 056 * Generates structures in specified chunk next to existing structures. Does *not* generate StructureStarts. 057 */ 058 public boolean generateStructuresInChunk(World par1World, Random par2Random, int par3, int par4) 059 { 060 int k = (par3 << 4) + 8; 061 int l = (par4 << 4) + 8; 062 boolean flag = false; 063 Iterator iterator = this.structureMap.values().iterator(); 064 065 while (iterator.hasNext()) 066 { 067 StructureStart structurestart = (StructureStart)iterator.next(); 068 069 if (structurestart.isSizeableStructure() && structurestart.getBoundingBox().intersectsWith(k, l, k + 15, l + 15)) 070 { 071 structurestart.generateStructure(par1World, par2Random, new StructureBoundingBox(k, l, k + 15, l + 15)); 072 flag = true; 073 } 074 } 075 076 return flag; 077 } 078 079 /** 080 * Returns true if the structure generator has generated a structure located at the given position tuple. 081 */ 082 public boolean hasStructureAt(int par1, int par2, int par3) 083 { 084 Iterator iterator = this.structureMap.values().iterator(); 085 086 while (iterator.hasNext()) 087 { 088 StructureStart structurestart = (StructureStart)iterator.next(); 089 090 if (structurestart.isSizeableStructure() && structurestart.getBoundingBox().intersectsWith(par1, par3, par1, par3)) 091 { 092 Iterator iterator1 = structurestart.getComponents().iterator(); 093 094 while (iterator1.hasNext()) 095 { 096 StructureComponent structurecomponent = (StructureComponent)iterator1.next(); 097 098 if (structurecomponent.getBoundingBox().isVecInside(par1, par2, par3)) 099 { 100 return true; 101 } 102 } 103 } 104 } 105 106 return false; 107 } 108 109 public ChunkPosition getNearestInstance(World par1World, int par2, int par3, int par4) 110 { 111 this.worldObj = par1World; 112 this.rand.setSeed(par1World.getSeed()); 113 long l = this.rand.nextLong(); 114 long i1 = this.rand.nextLong(); 115 long j1 = (long)(par2 >> 4) * l; 116 long k1 = (long)(par4 >> 4) * i1; 117 this.rand.setSeed(j1 ^ k1 ^ par1World.getSeed()); 118 this.recursiveGenerate(par1World, par2 >> 4, par4 >> 4, 0, 0, (byte[])null); 119 double d0 = Double.MAX_VALUE; 120 ChunkPosition chunkposition = null; 121 Iterator iterator = this.structureMap.values().iterator(); 122 ChunkPosition chunkposition1; 123 int l1; 124 int i2; 125 double d1; 126 int j2; 127 128 while (iterator.hasNext()) 129 { 130 StructureStart structurestart = (StructureStart)iterator.next(); 131 132 if (structurestart.isSizeableStructure()) 133 { 134 StructureComponent structurecomponent = (StructureComponent)structurestart.getComponents().get(0); 135 chunkposition1 = structurecomponent.getCenter(); 136 i2 = chunkposition1.x - par2; 137 l1 = chunkposition1.y - par3; 138 j2 = chunkposition1.z - par4; 139 d1 = (double)(i2 + i2 * l1 * l1 + j2 * j2); 140 141 if (d1 < d0) 142 { 143 d0 = d1; 144 chunkposition = chunkposition1; 145 } 146 } 147 } 148 149 if (chunkposition != null) 150 { 151 return chunkposition; 152 } 153 else 154 { 155 List list = this.getCoordList(); 156 157 if (list != null) 158 { 159 ChunkPosition chunkposition2 = null; 160 Iterator iterator1 = list.iterator(); 161 162 while (iterator1.hasNext()) 163 { 164 chunkposition1 = (ChunkPosition)iterator1.next(); 165 i2 = chunkposition1.x - par2; 166 l1 = chunkposition1.y - par3; 167 j2 = chunkposition1.z - par4; 168 d1 = (double)(i2 + i2 * l1 * l1 + j2 * j2); 169 170 if (d1 < d0) 171 { 172 d0 = d1; 173 chunkposition2 = chunkposition1; 174 } 175 } 176 177 return chunkposition2; 178 } 179 else 180 { 181 return null; 182 } 183 } 184 } 185 186 /** 187 * Returns a list of other locations at which the structure generation has been run, or null if not relevant to this 188 * structure generator. 189 */ 190 protected List getCoordList() 191 { 192 return null; 193 } 194 195 protected abstract boolean canSpawnStructureAtCoords(int i, int j); 196 197 protected abstract StructureStart getStructureStart(int i, int j); 198}