package net.minecraft.world.gen.structure;
import com.google.common.collect.Maps;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ReportedException;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.gen.MapGenBase;
public abstract class MapGenStructure extends MapGenBase
{
private MapGenStructureData field_143029_e;
/**
* Used to store a list of all structures that have been recursively generated. Used so that during recursive
* generation, the structure generator can avoid generating structures that intersect ones that have already been
* placed.
*/
protected Map structureMap = Maps.newHashMap();
private static final String __OBFID = "CL_00000505";
public abstract String getStructureName();
protected final void func_180701_a(World worldIn, final int p_180701_2_, final int p_180701_3_, int p_180701_4_, int p_180701_5_, ChunkPrimer p_180701_6_)
{
this.func_143027_a(worldIn);
if (!this.structureMap.containsKey(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_180701_2_, p_180701_3_))))
{
this.rand.nextInt();
try
{
if (this.canSpawnStructureAtCoords(p_180701_2_, p_180701_3_))
{
StructureStart var7 = this.getStructureStart(p_180701_2_, p_180701_3_);
this.structureMap.put(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_180701_2_, p_180701_3_)), var7);
this.func_143026_a(p_180701_2_, p_180701_3_, var7);
}
}
catch (Throwable var10)
{
CrashReport var8 = CrashReport.makeCrashReport(var10, "Exception preparing structure feature");
CrashReportCategory var9 = var8.makeCategory("Feature being prepared");
var9.addCrashSectionCallable("Is feature chunk", new Callable()
{
private static final String __OBFID = "CL_00000506";
public String call()
{
return MapGenStructure.this.canSpawnStructureAtCoords(p_180701_2_, p_180701_3_) ? "True" : "False";
}
});
var9.addCrashSection("Chunk location", String.format("%d,%d", new Object[] {Integer.valueOf(p_180701_2_), Integer.valueOf(p_180701_3_)}));
var9.addCrashSectionCallable("Chunk pos hash", new Callable()
{
private static final String __OBFID = "CL_00000507";
public String call()
{
return String.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_180701_2_, p_180701_3_));
}
});
var9.addCrashSectionCallable("Structure type", new Callable()
{
private static final String __OBFID = "CL_00000508";
public String call()
{
return MapGenStructure.this.getClass().getCanonicalName();
}
});
throw new ReportedException(var8);
}
}
}
public boolean func_175794_a(World worldIn, Random p_175794_2_, ChunkCoordIntPair p_175794_3_)
{
this.func_143027_a(worldIn);
int var4 = (p_175794_3_.chunkXPos << 4) + 8;
int var5 = (p_175794_3_.chunkZPos << 4) + 8;
boolean var6 = false;
Iterator var7 = this.structureMap.values().iterator();
while (var7.hasNext())
{
StructureStart var8 = (StructureStart)var7.next();
if (var8.isSizeableStructure() && var8.func_175788_a(p_175794_3_) && var8.getBoundingBox().intersectsWith(var4, var5, var4 + 15, var5 + 15))
{
var8.generateStructure(worldIn, p_175794_2_, new StructureBoundingBox(var4, var5, var4 + 15, var5 + 15));
var8.func_175787_b(p_175794_3_);
var6 = true;
this.func_143026_a(var8.func_143019_e(), var8.func_143018_f(), var8);
}
}
return var6;
}
public boolean func_175795_b(BlockPos p_175795_1_)
{
this.func_143027_a(this.worldObj);
return this.func_175797_c(p_175795_1_) != null;
}
protected StructureStart func_175797_c(BlockPos p_175797_1_)
{
Iterator var2 = this.structureMap.values().iterator();
while (var2.hasNext())
{
StructureStart var3 = (StructureStart)var2.next();
if (var3.isSizeableStructure() && var3.getBoundingBox().func_175898_b(p_175797_1_))
{
Iterator var4 = var3.getComponents().iterator();
while (var4.hasNext())
{
StructureComponent var5 = (StructureComponent)var4.next();
if (var5.getBoundingBox().func_175898_b(p_175797_1_))
{
return var3;
}
}
}
}
return null;
}
public boolean func_175796_a(World worldIn, BlockPos p_175796_2_)
{
this.func_143027_a(worldIn);
Iterator var3 = this.structureMap.values().iterator();
StructureStart var4;
do
{
if (!var3.hasNext())
{
return false;
}
var4 = (StructureStart)var3.next();
}
while (!var4.isSizeableStructure() || !var4.getBoundingBox().func_175898_b(p_175796_2_));
return true;
}
public BlockPos func_180706_b(World worldIn, BlockPos p_180706_2_)
{
this.worldObj = worldIn;
this.func_143027_a(worldIn);
this.rand.setSeed(worldIn.getSeed());
long var3 = this.rand.nextLong();
long var5 = this.rand.nextLong();
long var7 = (long)(p_180706_2_.getX() >> 4) * var3;
long var9 = (long)(p_180706_2_.getZ() >> 4) * var5;
this.rand.setSeed(var7 ^ var9 ^ worldIn.getSeed());
this.func_180701_a(worldIn, p_180706_2_.getX() >> 4, p_180706_2_.getZ() >> 4, 0, 0, (ChunkPrimer)null);
double var11 = Double.MAX_VALUE;
BlockPos var13 = null;
Iterator var14 = this.structureMap.values().iterator();
BlockPos var17;
double var18;
while (var14.hasNext())
{
StructureStart var15 = (StructureStart)var14.next();
if (var15.isSizeableStructure())
{
StructureComponent var16 = (StructureComponent)var15.getComponents().get(0);
var17 = var16.func_180776_a();
var18 = var17.distanceSq(p_180706_2_);
if (var18 < var11)
{
var11 = var18;
var13 = var17;
}
}
}
if (var13 != null)
{
return var13;
}
else
{
List var20 = this.getCoordList();
if (var20 != null)
{
BlockPos var21 = null;
Iterator var22 = var20.iterator();
while (var22.hasNext())
{
var17 = (BlockPos)var22.next();
var18 = var17.distanceSq(p_180706_2_);
if (var18 < var11)
{
var11 = var18;
var21 = var17;
}
}
return var21;
}
else
{
return null;
}
}
}
/**
* Returns a list of other locations at which the structure generation has been run, or null if not relevant to this
* structure generator.
*/
protected List getCoordList()
{
return null;
}
private void func_143027_a(World worldIn)
{
if (this.field_143029_e == null)
{
this.field_143029_e = (MapGenStructureData)worldIn.loadItemData(MapGenStructureData.class, this.getStructureName());
if (this.field_143029_e == null)
{
this.field_143029_e = new MapGenStructureData(this.getStructureName());
worldIn.setItemData(this.getStructureName(), this.field_143029_e);
}
else
{
NBTTagCompound var2 = this.field_143029_e.func_143041_a();
Iterator var3 = var2.getKeySet().iterator();
while (var3.hasNext())
{
String var4 = (String)var3.next();
NBTBase var5 = var2.getTag(var4);
if (var5.getId() == 10)
{
NBTTagCompound var6 = (NBTTagCompound)var5;
if (var6.hasKey("ChunkX") && var6.hasKey("ChunkZ"))
{
int var7 = var6.getInteger("ChunkX");
int var8 = var6.getInteger("ChunkZ");
StructureStart var9 = MapGenStructureIO.func_143035_a(var6, worldIn);
if (var9 != null)
{
this.structureMap.put(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(var7, var8)), var9);
}
}
}
}
}
}
}
private void func_143026_a(int p_143026_1_, int p_143026_2_, StructureStart p_143026_3_)
{
this.field_143029_e.func_143043_a(p_143026_3_.func_143021_a(p_143026_1_, p_143026_2_), p_143026_1_, p_143026_2_);
this.field_143029_e.markDirty();
}
protected abstract boolean canSpawnStructureAtCoords(int p_75047_1_, int p_75047_2_);
protected abstract StructureStart getStructureStart(int p_75049_1_, int p_75049_2_);
}