001 package net.minecraft.world.gen.structure; 002 003 import java.util.HashMap; 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.Map; 007 import java.util.Random; 008 import net.minecraft.crash.CrashReport; 009 import net.minecraft.crash.CrashReportCategory; 010 import net.minecraft.util.ReportedException; 011 import net.minecraft.world.ChunkCoordIntPair; 012 import net.minecraft.world.ChunkPosition; 013 import net.minecraft.world.World; 014 import net.minecraft.world.gen.MapGenBase; 015 016 public 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 var7 = this.getStructureStart(par2, par3); 039 this.structureMap.put(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(par2, par3)), var7); 040 } 041 } 042 catch (Throwable var10) 043 { 044 CrashReport var8 = CrashReport.makeCrashReport(var10, "Exception preparing structure feature"); 045 CrashReportCategory var9 = var8.makeCategory("Feature being prepared"); 046 var9.addCrashSectionCallable("Is feature chunk", new CallableIsFeatureChunk(this, par2, par3)); 047 var9.addCrashSection("Chunk location", String.format("%d,%d", new Object[] {Integer.valueOf(par2), Integer.valueOf(par3)})); 048 var9.addCrashSectionCallable("Chunk pos hash", new CallableChunkPosHash(this, par2, par3)); 049 var9.addCrashSectionCallable("Structure type", new CallableStructureType(this)); 050 throw new ReportedException(var8); 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 var5 = (par3 << 4) + 8; 061 int var6 = (par4 << 4) + 8; 062 boolean var7 = false; 063 Iterator var8 = this.structureMap.values().iterator(); 064 065 while (var8.hasNext()) 066 { 067 StructureStart var9 = (StructureStart)var8.next(); 068 069 if (var9.isSizeableStructure() && var9.getBoundingBox().intersectsWith(var5, var6, var5 + 15, var6 + 15)) 070 { 071 var9.generateStructure(par1World, par2Random, new StructureBoundingBox(var5, var6, var5 + 15, var6 + 15)); 072 var7 = true; 073 } 074 } 075 076 return var7; 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 var4 = this.structureMap.values().iterator(); 085 086 while (var4.hasNext()) 087 { 088 StructureStart var5 = (StructureStart)var4.next(); 089 090 if (var5.isSizeableStructure() && var5.getBoundingBox().intersectsWith(par1, par3, par1, par3)) 091 { 092 Iterator var6 = var5.getComponents().iterator(); 093 094 while (var6.hasNext()) 095 { 096 StructureComponent var7 = (StructureComponent)var6.next(); 097 098 if (var7.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 var5 = this.rand.nextLong(); 114 long var7 = this.rand.nextLong(); 115 long var9 = (long)(par2 >> 4) * var5; 116 long var11 = (long)(par4 >> 4) * var7; 117 this.rand.setSeed(var9 ^ var11 ^ par1World.getSeed()); 118 this.recursiveGenerate(par1World, par2 >> 4, par4 >> 4, 0, 0, (byte[])null); 119 double var13 = Double.MAX_VALUE; 120 ChunkPosition var15 = null; 121 Iterator var16 = this.structureMap.values().iterator(); 122 ChunkPosition var19; 123 int var21; 124 int var20; 125 double var23; 126 int var22; 127 128 while (var16.hasNext()) 129 { 130 StructureStart var17 = (StructureStart)var16.next(); 131 132 if (var17.isSizeableStructure()) 133 { 134 StructureComponent var18 = (StructureComponent)var17.getComponents().get(0); 135 var19 = var18.getCenter(); 136 var20 = var19.x - par2; 137 var21 = var19.y - par3; 138 var22 = var19.z - par4; 139 var23 = (double)(var20 + var20 * var21 * var21 + var22 * var22); 140 141 if (var23 < var13) 142 { 143 var13 = var23; 144 var15 = var19; 145 } 146 } 147 } 148 149 if (var15 != null) 150 { 151 return var15; 152 } 153 else 154 { 155 List var25 = this.getCoordList(); 156 157 if (var25 != null) 158 { 159 ChunkPosition var26 = null; 160 Iterator var27 = var25.iterator(); 161 162 while (var27.hasNext()) 163 { 164 var19 = (ChunkPosition)var27.next(); 165 var20 = var19.x - par2; 166 var21 = var19.y - par3; 167 var22 = var19.z - par4; 168 var23 = (double)(var20 + var20 * var21 * var21 + var22 * var22); 169 170 if (var23 < var13) 171 { 172 var13 = var23; 173 var26 = var19; 174 } 175 } 176 177 return var26; 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 var1, int var2); 196 197 protected abstract StructureStart getStructureStart(int var1, int var2); 198 }