package rtg.world.gen.structure;
import java.util.*;
import java.util.Map.Entry;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.monster.EntityGuardian;
import net.minecraft.init.Biomes;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ReportedException;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.layer.IntCache;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureOceanMonument;
import net.minecraft.world.gen.structure.StructureOceanMonumentPieces;
import net.minecraft.world.gen.structure.StructureStart;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import rtg.api.RTGAPI;
import rtg.util.Logger;
import rtg.world.WorldTypeRTG;
import rtg.world.biome.BiomeProviderRTG;
public class StructureOceanMonumentRTG extends StructureOceanMonument
{
private int spacing;
private int separation;
public static final List<Biome> WATER_BIOMES = Arrays.<Biome>asList(new Biome[] {Biomes.OCEAN, Biomes.DEEP_OCEAN, Biomes.RIVER, Biomes.FROZEN_OCEAN, Biomes.FROZEN_RIVER});
public static final List<Biome> SPAWN_BIOMES = Arrays.<Biome>asList(new Biome[] {Biomes.DEEP_OCEAN});
private static final List<Biome.SpawnListEntry> MONUMENT_ENEMIES = Lists.<Biome.SpawnListEntry>newArrayList();
public StructureOceanMonumentRTG()
{
this.spacing = RTGAPI.config().OCEAN_MONUMENT_SPACING.get(); // Vanilla = 32
this.separation = RTGAPI.config().OCEAN_MONUMENT_SEPARATION.get(); // Vanilla = 5
}
public StructureOceanMonumentRTG(Map<String, String> p_i45608_1_)
{
this();
for (Entry<String, String> entry : p_i45608_1_.entrySet())
{
if (((String)entry.getKey()).equals("spacing"))
{
this.spacing = MathHelper.getInt((String)entry.getValue(), this.spacing, 1);
}
else if (((String)entry.getKey()).equals("separation"))
{
this.separation = MathHelper.getInt((String)entry.getValue(), this.separation, 1);
}
}
}
@Override
public String getStructureName()
{
return "Monument";
}
@Override
protected boolean canSpawnStructureAtCoords(int chunkX, int chunkZ)
{
int i = chunkX;
int j = chunkZ;
if (chunkX < 0)
{
chunkX -= this.spacing - 1;
}
if (chunkZ < 0)
{
chunkZ -= this.spacing - 1;
}
int k = chunkX / this.spacing;
int l = chunkZ / this.spacing;
Random random = this.world.setRandomSeed(k, l, 10387313);
k = k * this.spacing;
l = l * this.spacing;
k = k + (random.nextInt(this.spacing - this.separation) + random.nextInt(this.spacing - this.separation)) / 2;
l = l + (random.nextInt(this.spacing - this.separation) + random.nextInt(this.spacing - this.separation)) / 2;
if (i == k && j == l)
{
int x = i * 16 + 8;
int z = j * 16 + 8;
if (this.world.getBiomeProvider().getBiome(new BlockPos(x, 64, z), Biomes.DEFAULT) != Biomes.DEEP_OCEAN) {
return false;
}
if (!this.areBiomesViable(x, z, 16, SPAWN_BIOMES))
{
return false;
}
boolean flag = this.areBiomesViable(x, z, 29, WATER_BIOMES);
if (flag)
{
Logger.debug("Ocean monument candidate at %d, %d", x, z);
return true;
}
}
return false;
}
public boolean areBiomesViable(int x, int z, int radius, List<Biome> allowed)
{
// Are we in an RTG world?
if (!(this.world.getWorldType() instanceof WorldTypeRTG)) {
//Logger.debug("Could not generate ocean monument. This is not an RTG world.");
return false;
}
// Do we have RTG's chunk manager?
if (!(this.world.getBiomeProvider() instanceof BiomeProviderRTG)) {
//Logger.debug("Could not generate ocean monument. Incompatible chunk manager detected.");
return false;
}
IntCache.resetIntCache();
int i = x - radius >> 2;
int j = z - radius >> 2;
int k = x + radius >> 2;
int l = z + radius >> 2;
int i1 = k - i + 1;
int j1 = l - j + 1;
BiomeProviderRTG cmr = (BiomeProviderRTG) this.world.getBiomeProvider();
int[] aint = cmr.getBiomesGens(i, j, i1, j1);
try
{
for (int k1 = 0; k1 < i1 * j1; ++k1)
{
Biome biome = Biome.getBiome(aint[k1]);
if (!allowed.contains(biome))
{
//Logger.debug("Could not generate ocean monument. Biome (%d) nearby.", BiomeUtils.getId(biome));
return false;
}
}
return true;
}
catch (Throwable throwable)
{
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Invalid Biome id");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Layer");
crashreportcategory.addCrashSection("Layer", Arrays.toString(aint));
crashreportcategory.addCrashSection("x", Integer.valueOf(x));
crashreportcategory.addCrashSection("z", Integer.valueOf(z));
crashreportcategory.addCrashSection("radius", Integer.valueOf(radius));
crashreportcategory.addCrashSection("allowed", allowed);
throw new ReportedException(crashreport);
}
}
@Override
public BlockPos getClosestStrongholdPos(World worldIn, BlockPos pos, boolean findUnexplored)
{
this.world = worldIn;
return findNearestStructurePosBySpacing(worldIn, this, pos, this.spacing, this.separation, 10387313, true, 100, findUnexplored);
}
@Override
protected StructureStart getStructureStart(int chunkX, int chunkZ)
{
return new StructureOceanMonumentRTG.StartMonument(this.world, this.rand, chunkX, chunkZ);
}
@Override
public List<Biome.SpawnListEntry> getScatteredFeatureSpawnList()
{
return MONUMENT_ENEMIES;
}
static
{
MONUMENT_ENEMIES.add(new Biome.SpawnListEntry(EntityGuardian.class, 1, 2, 4));
}
public static class StartMonument extends StructureStart
{
private final Set<ChunkPos> processed = Sets.<ChunkPos>newHashSet();
private boolean wasCreated;
public StartMonument()
{
}
public StartMonument(World worldIn, Random random, int chunkX, int chunkZ)
{
super(chunkX, chunkZ);
this.create(worldIn, random, chunkX, chunkZ);
}
private void create(World worldIn, Random random, int chunkX, int chunkZ)
{
random.setSeed(worldIn.getSeed());
long i = random.nextLong();
long j = random.nextLong();
long k = (long)chunkX * i;
long l = (long)chunkZ * j;
random.setSeed(k ^ l ^ worldIn.getSeed());
int i1 = chunkX * 16 + 8 - 29;
int j1 = chunkZ * 16 + 8 - 29;
EnumFacing enumfacing = EnumFacing.Plane.HORIZONTAL.random(random);
this.components.add(new StructureOceanMonumentPieces.MonumentBuilding(random, i1, j1, enumfacing));
this.updateBoundingBox();
this.wasCreated = true;
}
@Override
public void generateStructure(World worldIn, Random rand, StructureBoundingBox structurebb)
{
if (!this.wasCreated)
{
this.components.clear();
this.create(worldIn, rand, this.getChunkPosX(), this.getChunkPosZ());
}
super.generateStructure(worldIn, rand, structurebb);
}
@Override
public boolean isValidForPostProcess(ChunkPos pair)
{
return this.processed.contains(pair) ? false : super.isValidForPostProcess(pair);
}
@Override
public void notifyPostProcessAt(ChunkPos pair)
{
super.notifyPostProcessAt(pair);
this.processed.add(pair);
}
@Override
public void writeToNBT(NBTTagCompound tagCompound)
{
super.writeToNBT(tagCompound);
NBTTagList nbttaglist = new NBTTagList();
for (ChunkPos chunkpos : this.processed)
{
NBTTagCompound nbttagcompound = new NBTTagCompound();
nbttagcompound.setInteger("X", chunkpos.chunkXPos);
nbttagcompound.setInteger("Z", chunkpos.chunkZPos);
nbttaglist.appendTag(nbttagcompound);
}
tagCompound.setTag("Processed", nbttaglist);
}
@Override
public void readFromNBT(NBTTagCompound tagCompound)
{
super.readFromNBT(tagCompound);
if (tagCompound.hasKey("Processed", 9))
{
NBTTagList nbttaglist = tagCompound.getTagList("Processed", 10);
for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
this.processed.add(new ChunkPos(nbttagcompound.getInteger("X"), nbttagcompound.getInteger("Z")));
}
}
}
}
}