package micdoodle8.mods.galacticraft.planets.asteroids.dimension;
import micdoodle8.mods.galacticraft.api.galaxies.CelestialBody;
import micdoodle8.mods.galacticraft.api.prefab.world.gen.WorldProviderSpace;
import micdoodle8.mods.galacticraft.api.vector.BlockVec3;
import micdoodle8.mods.galacticraft.api.vector.Vector3;
import micdoodle8.mods.galacticraft.api.world.ISolarLevel;
import micdoodle8.mods.galacticraft.core.event.EventHandlerGC;
import micdoodle8.mods.galacticraft.core.util.ConfigManagerCore;
import micdoodle8.mods.galacticraft.core.util.GCLog;
import micdoodle8.mods.galacticraft.planets.asteroids.AsteroidsModule;
import micdoodle8.mods.galacticraft.planets.asteroids.entities.EntityAstroMiner;
import micdoodle8.mods.galacticraft.planets.asteroids.world.gen.ChunkProviderAsteroids;
import micdoodle8.mods.galacticraft.planets.asteroids.world.gen.WorldChunkManagerAsteroids;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.biome.WorldChunkManager;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.TreeMap;
public class WorldProviderAsteroids extends WorldProviderSpace implements ISolarLevel
{
//Used to list asteroid centres to external code that needs to know them
private HashSet<AsteroidData> asteroids = new HashSet();
private boolean dataNotLoaded = true;
private AsteroidSaveData datafile;
private double solarMultiplier = -1D;
// @Override
// public void registerWorldChunkManager()
// {
// this.worldChunkMgr = new WorldChunkManagerAsteroids(this.worldObj, 0F);
// }
@Override
public CelestialBody getCelestialBody()
{
return AsteroidsModule.planetAsteroids;
}
@Override
public Vector3 getFogColor()
{
return new Vector3(0, 0, 0);
}
@Override
public Vector3 getSkyColor()
{
return new Vector3(0, 0, 0);
}
@Override
public boolean hasSunset()
{
return false;
}
@Override
public long getDayLength()
{
return 0;
}
@Override
public boolean isDaytime()
{
return true;
}
@Override
public Class<? extends IChunkProvider> getChunkProviderClass()
{
return ChunkProviderAsteroids.class;
}
@Override
public Class<? extends WorldChunkManager> getWorldChunkManagerClass()
{
return WorldChunkManagerAsteroids.class;
}
@Override
public float calculateCelestialAngle(long par1, float par3)
{
return 0.25F;
}
@Override
@SideOnly(Side.CLIENT)
public float getStarBrightness(float par1)
{
return 1.0F;
}
// @Override
// public IChunkProvider createChunkGenerator()
// {
// return new ChunkProviderAsteroids(this.worldObj, this.worldObj.getSeed(), this.worldObj.getWorldInfo().isMapFeaturesEnabled());
// }
@Override
public double getHorizon()
{
return 44.0D;
}
@Override
public int getAverageGroundLevel()
{
return 96;
}
@Override
public boolean canCoordinateBeSpawn(int var1, int var2)
{
return true;
}
//Overriding so that beds do not explode on Asteroids
@Override
public boolean canRespawnHere()
{
if (EventHandlerGC.bedActivated)
{
EventHandlerGC.bedActivated = false;
return true;
}
return false;
}
@Override
public float getGravity()
{
return 0.072F;
}
@Override
public double getMeteorFrequency()
{
return 10.0D;
}
@Override
public double getFuelUsageMultiplier()
{
return 0.9D;
}
@Override
public boolean canSpaceshipTierPass(int tier)
{
return tier >= 3;
}
@Override
public float getFallDamageModifier()
{
return 0.1F;
}
public void addAsteroid(int x, int y, int z, int size, int core)
{
AsteroidData coords = new AsteroidData(x, y, z, size, core);
if (!this.asteroids.contains(coords))
{
if (this.dataNotLoaded)
{
this.loadAsteroidSavedData();
}
if (!this.asteroids.contains(coords))
{
this.addToNBT(this.datafile.datacompound, coords);
this.asteroids.add(coords);
}
}
}
public void removeAsteroid(int x, int y, int z)
{
AsteroidData coords = new AsteroidData(x, y, z);
if (this.asteroids.contains(coords))
{
this.asteroids.remove(coords);
if (this.dataNotLoaded)
{
this.loadAsteroidSavedData();
}
this.writeToNBT(this.datafile.datacompound);
}
}
private void loadAsteroidSavedData()
{
this.datafile = (AsteroidSaveData) this.worldObj.loadItemData(AsteroidSaveData.class, AsteroidSaveData.saveDataID);
if (this.datafile == null)
{
this.datafile = new AsteroidSaveData("");
this.worldObj.setItemData(AsteroidSaveData.saveDataID, this.datafile);
this.writeToNBT(this.datafile.datacompound);
}
else
{
this.readFromNBT(this.datafile.datacompound);
}
this.dataNotLoaded = false;
}
private void readFromNBT(NBTTagCompound nbt)
{
NBTTagList coordList = nbt.getTagList("coords", 10);
if (coordList.tagCount() > 0)
{
for (int j = 0; j < coordList.tagCount(); j++)
{
NBTTagCompound tag1 = coordList.getCompoundTagAt(j);
if (tag1 != null)
{
this.asteroids.add(AsteroidData.readFromNBT(tag1));
}
}
}
}
private void writeToNBT(NBTTagCompound nbt)
{
NBTTagList coordList = new NBTTagList();
for (AsteroidData coords : this.asteroids)
{
NBTTagCompound tag = new NBTTagCompound();
coords.writeToNBT(tag);
coordList.appendTag(tag);
}
nbt.setTag("coords", coordList);
this.datafile.markDirty();
}
private void addToNBT(NBTTagCompound nbt, AsteroidData coords)
{
NBTTagList coordList = nbt.getTagList("coords", 10);
NBTTagCompound tag = new NBTTagCompound();
coords.writeToNBT(tag);
coordList.appendTag(tag);
nbt.setTag("coords", coordList);
this.datafile.markDirty();
}
public BlockVec3 getClosestAsteroidXZ(int x, int y, int z, boolean mark)
{
if (this.dataNotLoaded)
{
this.loadAsteroidSavedData();
}
if (this.asteroids.size() == 0)
{
return null;
}
BlockVec3 result = null;
AsteroidData resultRoid = null;
int lowestDistance = Integer.MAX_VALUE;
for (AsteroidData test : this.asteroids)
{
if (mark && (test.sizeAndLandedFlag & 128) > 0)
{
continue;
}
int dx = x - test.centre.x;
int dz = z - test.centre.z;
int a = dx * dx + dz * dz;
if (a < lowestDistance)
{
lowestDistance = a;
result = test.centre;
resultRoid = test;
}
}
if (result == null)
{
return null;
}
if (mark)
{
resultRoid.sizeAndLandedFlag |= 128;
this.writeToNBT(this.datafile.datacompound);
}
result = result.clone();
result.sideDoneBits = resultRoid.sizeAndLandedFlag & 127;
return result;
}
public ArrayList<BlockVec3> getClosestAsteroidsXZ(int x, int y, int z, int facing, int count)
{
if (this.dataNotLoaded)
{
this.loadAsteroidSavedData();
}
if (this.asteroids.size() == 0)
{
return null;
}
TreeMap<Integer, BlockVec3> targets = new TreeMap();
for (AsteroidData roid : this.asteroids)
{
BlockVec3 test = roid.centre;
switch (facing)
{
case 2:
if (z - 16 < test.z)
{
continue;
}
break;
case 3:
if (z + 16 > test.z)
{
continue;
}
break;
case 4:
if (x - 16 < test.x)
{
continue;
}
break;
case 5:
if (x + 16 > test.x)
{
continue;
}
break;
}
int dx = x - test.x;
int dz = z - test.z;
int a = dx * dx + dz * dz;
if (a < 262144)
{
targets.put(a, test);
}
}
int max = Math.max(count, targets.size());
if (max <= 0)
{
return null;
}
ArrayList<BlockVec3> returnValues = new ArrayList();
int i = 0;
int offset = EntityAstroMiner.MINE_LENGTH_AST / 2;
for (BlockVec3 target : targets.values())
{
BlockVec3 coords = target.clone();
GCLog.debug("Found nearby asteroid at " + target.toString());
switch (facing)
{
case 2:
coords.z += offset;
break;
case 3:
coords.z -= offset;
break;
case 4:
coords.x += offset;
break;
case 5:
coords.x -= offset;
break;
}
returnValues.add(coords);
if (++i >= count)
{
break;
}
}
return returnValues;
}
@Override
public int getActualHeight()
{
return 256;
}
@Override
public void registerWorldChunkManager()
{
super.registerWorldChunkManager();
this.hasNoSky = true;
}
@Override
public double getSolarEnergyMultiplier()
{
if (this.solarMultiplier < 0D)
{
double s = this.getSolarSize();
this.solarMultiplier = s * s * s * ConfigManagerCore.spaceStationEnergyScalar;
}
return this.solarMultiplier;
}
@Override
public String getInternalNameSuffix()
{
return "_asteroids";
}
private static class AsteroidData
{
protected BlockVec3 centre;
protected int sizeAndLandedFlag = 15;
protected int coreAndSpawnedFlag = -2;
public AsteroidData(int x, int y, int z)
{
this.centre = new BlockVec3(x, y, z);
}
public AsteroidData(int x, int y, int z, int size, int core)
{
this.centre = new BlockVec3(x, y, z);
this.sizeAndLandedFlag = size;
this.coreAndSpawnedFlag = core;
}
public AsteroidData(BlockVec3 bv)
{
this.centre = bv;
}
@Override
public int hashCode()
{
if (this.centre != null)
{
return this.centre.hashCode();
}
else
{
return 0;
}
}
@Override
public boolean equals(Object o)
{
if (o instanceof AsteroidData)
{
BlockVec3 vector = ((AsteroidData) o).centre;
return this.centre.x == vector.x && this.centre.y == vector.y && this.centre.z == vector.z;
}
if (o instanceof BlockVec3)
{
BlockVec3 vector = (BlockVec3) o;
return this.centre.x == vector.x && this.centre.y == vector.y && this.centre.z == vector.z;
}
return false;
}
public NBTTagCompound writeToNBT(NBTTagCompound tag)
{
tag.setInteger("x", this.centre.x);
tag.setInteger("y", this.centre.y);
tag.setInteger("z", this.centre.z);
tag.setInteger("coreAndFlag", this.coreAndSpawnedFlag);
tag.setInteger("sizeAndFlag", this.sizeAndLandedFlag);
return tag;
}
public static AsteroidData readFromNBT(NBTTagCompound tag)
{
BlockVec3 tempVector = new BlockVec3();
tempVector.x = tag.getInteger("x");
tempVector.y = tag.getInteger("y");
tempVector.z = tag.getInteger("z");
AsteroidData roid = new AsteroidData(tempVector);
if (tag.hasKey("coreAndFlag"))
{
roid.coreAndSpawnedFlag = tag.getInteger("coreAndFlag");
}
if (tag.hasKey("sizeAndFlag"))
{
roid.sizeAndLandedFlag = tag.getInteger("sizeAndFlag");
}
return roid;
}
}
@Override
public int getDungeonSpacing()
{
return 576;
//Used for generating Abandoned Base
}
}