package zmaster587.advancedRocketry.dimension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.ArrayUtils;
import scala.util.Random;
import zmaster587.advancedRocketry.AdvancedRocketry;
import zmaster587.advancedRocketry.api.AdvancedRocketryBiomes;
import zmaster587.advancedRocketry.api.IAtmosphere;
import zmaster587.advancedRocketry.api.SatelliteRegistry;
import zmaster587.advancedRocketry.api.dimension.IDimensionProperties;
import zmaster587.advancedRocketry.api.dimension.solar.StellarBody;
import zmaster587.advancedRocketry.api.satellite.SatelliteBase;
import zmaster587.advancedRocketry.atmosphere.AtmosphereType;
import zmaster587.advancedRocketry.network.PacketDimInfo;
import zmaster587.advancedRocketry.network.PacketSatellite;
import zmaster587.advancedRocketry.stations.SpaceObjectManager;
import zmaster587.advancedRocketry.util.OreGenProperties;
import zmaster587.advancedRocketry.world.ChunkManagerPlanet;
import zmaster587.advancedRocketry.world.ChunkProviderPlanet;
import zmaster587.advancedRocketry.world.provider.WorldProviderPlanet;
import zmaster587.libVulpes.network.PacketHandler;
import zmaster587.libVulpes.util.VulpineMath;
import zmaster587.libVulpes.util.ZUtils;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagFloat;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.biome.BiomeGenBase.TempCategory;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.BiomeManager;
import net.minecraftforge.common.BiomeManager.BiomeEntry;
import net.minecraftforge.common.util.Constants.NBT;
public class DimensionProperties implements Cloneable, IDimensionProperties {
/**
* Contains standardized temperature ranges for planets
* where 100 is earthlike, larger values are hotter
*/
public static enum Temps {
TOOHOT(150),
HOT(125),
NORMAL(75),
COLD(50),
FRIGID(25),
SNOWBALL(0);
private int temp;
Temps(int i) {
temp = i;
}
@Deprecated
public int getTemp() {
return temp;
}
/**
* @param lowerBound lower Bound (inclusive)
* @param upperBound upper Bound (inclusive)
* @return true if this resides between the to bounds
*/
public boolean isInRange(Temps lowerBound, Temps upperBound) {
return this.compareTo(lowerBound) <= 0 && this.compareTo(upperBound) >= 0;
}
/**
* @return a temperature that refers to the supplied value
*/
public static Temps getTempFromValue(int value) {
for(Temps type : Temps.values()) {
if(value > type.temp)
return type;
}
return SNOWBALL;
}
}
/**
* Contains standardized pressure ranges for planets
* where 100 is earthlike, largers values are higher pressure
*/
public static enum AtmosphereTypes {
HIGHPRESSURE(125),
NORMAL(75),
LOW(25),
NONE(0);
private int value;
private AtmosphereTypes(int value) {
this.value = value;
}
public int getAtmosphereValue() {
return value;
}
public static AtmosphereTypes getAtmosphereTypeFromValue(int value) {
for(AtmosphereTypes type : AtmosphereTypes.values()) {
if(value > type.value)
return type;
}
return NONE;
}
}
/**
* Contains default graphic {@link ResourceLocation} to display for different planet types
*
*/
public static final ResourceLocation atmosphere = new ResourceLocation("advancedrocketry:textures/planets/Atmosphere.png");
public static final ResourceLocation atmosphereLEO = new ResourceLocation("advancedrocketry:textures/planets/AtmosphereLEO.png");
public static enum PlanetIcons {
EARTHLIKE(new ResourceLocation("advancedrocketry:textures/planets/Earthlike.png")),
LAVA(new ResourceLocation("advancedrocketry:textures/planets/Lava.png")),
MARSLIKE(new ResourceLocation("advancedrocketry:textures/planets/marslike.png")),
MOON(new ResourceLocation("advancedrocketry:textures/planets/moon.png")),
WATERWORLD(new ResourceLocation("advancedrocketry:textures/planets/WaterWorld.png")),
ICEWORLD(new ResourceLocation("advancedrocketry:textures/planets/IceWorld.png")),
GASGIANTBLUE(new ResourceLocation("advancedrocketry:textures/planets/GasGiantBlue.png")),
GASGIANTRED(new ResourceLocation("advancedrocketry:textures/planets/GasGiantOrange.png")),
UNKNOWN(new ResourceLocation("advancedrocketry:textures/planets/Unknown.png"))
;
private ResourceLocation resource;
private ResourceLocation resourceLEO;
private PlanetIcons(ResourceLocation resource) {
this.resource = resource;
this.resourceLEO = new ResourceLocation(resource.toString().substring(0, resource.toString().length() - 4) + "LEO.jpg");
}
private PlanetIcons(ResourceLocation resource, ResourceLocation leo) {
this.resource = resource;
this.resourceLEO = atmosphereLEO;
}
public ResourceLocation getResource() {
return resource;
}
public ResourceLocation getResourceLEO() {
return resourceLEO;
}
}
public static final int MAX_ATM_PRESSURE = 200;
public static final int MIN_ATM_PRESSURE = 0;
public static final int MAX_DISTANCE = 200;
public static final int MIN_DISTANCE = 0;
public static final int MAX_GRAVITY = 200;
public static final int MIN_GRAVITY = 0;
/**True if dimension is managed and created by AR (false otherwise)**/
public boolean isNativeDimension;
//Gas giants DO NOT need a dimension registered to them
public float[] skyColor;
public float[] fogColor;
public float gravitationalMultiplier;
public int orbitalDist;
private int atmosphereDensity;
private int originalAtmosphereDensity;
public int averageTemperature;
public int rotationalPeriod;
//Stored in radians
public double orbitTheta;
StellarBody star;
int starId;
private String name;
public float[] sunriseSunsetColors;
//public ExtendedBiomeProperties biomeProperties;
private LinkedList<BiomeEntry> allowedBiomes;
private LinkedList<BiomeEntry> terraformedBiomes;
private boolean isRegistered = false;
private boolean isTerraformed = false;
public double prevOrbitalTheta;
public double orbitalPhi;
public double rotationalPhi;
public OreGenProperties oreProperties = null;
public String customIcon;
//Planet Heirachy
private HashSet<Integer> childPlanets;
private int parentPlanet;
private int planetId;
private boolean isStation;
private boolean isGasGiant;
//Satallites
private HashMap<Long,SatelliteBase> satallites;
private HashMap<Long,SatelliteBase> tickingSatallites;
public DimensionProperties(int id) {
name = "Temp";
resetProperties();
planetId = id;
parentPlanet = -1;
childPlanets = new HashSet<Integer>();
orbitalPhi = 0;
allowedBiomes = new LinkedList<BiomeManager.BiomeEntry>();
terraformedBiomes = new LinkedList<BiomeManager.BiomeEntry>();
satallites = new HashMap<>();
tickingSatallites = new HashMap<Long,SatelliteBase>();
isNativeDimension = true;
isGasGiant = false;
}
public boolean isGasGiant() {
return isGasGiant;
}
public void setGasGiant() {
isGasGiant = true;
}
public DimensionProperties(int id ,String name) {
this(id);
this.name = name;
}
public DimensionProperties(int id, boolean shouldRegister) {
this(id);
isStation = !shouldRegister;
}
@Override
public Object clone() {
try {
return super.clone();
} catch(CloneNotSupportedException e) {
return null;
}
}
/**
* @param world
* @return null to use default world gen properties, otherwise a list of ores to generate
*/
public OreGenProperties getOreGenProperties(World world) {
if(oreProperties != null)
return oreProperties;
return OreGenProperties.getOresForPressure(AtmosphereTypes.getAtmosphereTypeFromValue(originalAtmosphereDensity), Temps.getTempFromValue(averageTemperature));
}
/**
* Resets all properties to default
*/
public void resetProperties() {
fogColor = new float[] {1f,1f,1f};
skyColor = new float[] {1f,1f,1f};
sunriseSunsetColors = new float[] {.7f,.2f,.2f,1};
gravitationalMultiplier = 1;
rotationalPeriod = 24000;
orbitalDist = 100;
originalAtmosphereDensity = atmosphereDensity = 100; childPlanets = new HashSet<Integer>();
parentPlanet = -1;
starId = 0;
averageTemperature = 100;
}
@Override
public float getGravitationalMultiplier() {
return gravitationalMultiplier;
}
@Override
public void setGravitationalMultiplier(float mult) {
gravitationalMultiplier = mult;
}
/**
* @return the color of the sun as an array of floats represented as {r,g,b}
*/
public float[] getSunColor() {
return getStar().getColor();
}
/**
* Sets the host star for the planet
* @param star the star to set as the host for this planet
*/
public void setStar(StellarBody star) {
this.starId = star.getId();
this.star = star;
if(!this.isMoon() && !isStation())
this.star.addPlanet(this);
}
public void setStar(int id) {
this.starId = id;
if(DimensionManager.getInstance().getStar(id) != null)
setStar(DimensionManager.getInstance().getStar(id));
}
/**
* @return the host star for this planet
*/
public StellarBody getStar() {
if(star == null)
star = DimensionManager.getInstance().getStar(starId);
return star;
}
public int getStarId() {
return starId;
}
/**
* @return the {@link ResourceLocation} representing this planet, generated from the planet's properties
*/
public ResourceLocation getPlanetIcon() {
if(customIcon != null && !customIcon.isEmpty())
{
try {
return PlanetIcons.valueOf(customIcon.toUpperCase()).resource;
} catch(IllegalArgumentException e) {
return PlanetIcons.UNKNOWN.resource;
}
}
AtmosphereTypes atmType = AtmosphereTypes.getAtmosphereTypeFromValue(atmosphereDensity);
Temps tempType = Temps.getTempFromValue(averageTemperature);
if(isGasGiant())
return PlanetIcons.GASGIANTBLUE.resource;
if(tempType == Temps.TOOHOT)
return PlanetIcons.MARSLIKE.resource;
if(atmType != AtmosphereTypes.NONE && VulpineMath.isBetween(tempType.ordinal(), Temps.COLD.ordinal(), Temps.TOOHOT.ordinal()))
return PlanetIcons.EARTHLIKE.resource;//TODO: humidity
else if(tempType.compareTo(Temps.COLD) > 0)
if(atmType.compareTo(AtmosphereTypes.LOW) > 0)
return PlanetIcons.MOON.resource;
else
return PlanetIcons.ICEWORLD.resource;
else if(atmType.compareTo(AtmosphereTypes.LOW) > 0) {
if(tempType.compareTo(Temps.COLD) < 0)
return PlanetIcons.MARSLIKE.resource;
else
return PlanetIcons.MOON.resource;
}
else
return PlanetIcons.LAVA.resource;
}
/**
* @return the {@link ResourceLocation} representing this planet, generated from the planet's properties
*/
public ResourceLocation getPlanetIconLEO() {
if(customIcon != null && !customIcon.isEmpty())
{
try {
return PlanetIcons.valueOf(customIcon.toUpperCase()).resourceLEO;
} catch(IllegalArgumentException e) {
return PlanetIcons.UNKNOWN.resource;
}
}
AtmosphereTypes atmType = AtmosphereTypes.getAtmosphereTypeFromValue(atmosphereDensity);
Temps tempType = Temps.getTempFromValue(averageTemperature);
if(isGasGiant())
return PlanetIcons.GASGIANTBLUE.resourceLEO;
if(tempType == Temps.TOOHOT)
return PlanetIcons.MARSLIKE.resourceLEO;
if(atmType != AtmosphereTypes.NONE && VulpineMath.isBetween(tempType.ordinal(), Temps.COLD.ordinal(), Temps.TOOHOT.ordinal()))
return PlanetIcons.EARTHLIKE.resourceLEO;//TODO: humidity
else if(tempType.compareTo(Temps.COLD) > 0)
if(atmType.compareTo(AtmosphereTypes.LOW) > 0)
return PlanetIcons.MOON.resourceLEO;
else
return PlanetIcons.ICEWORLD.resourceLEO;
else if(atmType.compareTo(AtmosphereTypes.LOW) > 0) {
if(tempType.compareTo(Temps.COLD) < 0)
return PlanetIcons.MARSLIKE.resourceLEO;
else
return PlanetIcons.MOON.resourceLEO;
}
else
return PlanetIcons.LAVA.resourceLEO;
}
/**
* @return the name of the planet
*/
public String getName() {
return name;
}
/**
* Sets the name of the planet
*/
public void setName(String name) {
this.name = name;
}
//Planet hierarchy
/**
* @return the DIMID of the planet
*/
public int getId() {
return planetId;
}
/**
* @return the DimID of the parent planet
*/
public int getParentPlanet() {
return parentPlanet;
}
/**
* @return the {@link DimensionProperties} of the parent planet
*/
public DimensionProperties getParentProperties() {
if(parentPlanet != -1)
return DimensionManager.getInstance().getDimensionProperties(parentPlanet);
return null;
}
/**
* Range 0 < value <= 200
* @return if the planet is a moon, then the distance from the host planet where the earth's moon is 100, higher is farther, if planet, distance from the star, 100 is earthlike, higher value is father
*/
public int getParentOrbitalDistance() {
return orbitalDist;
}
/**
* @return if a planet, the same as getParentOrbitalDistance(), if a moon, the moon's distance from the host star
*/
public int getSolarOrbitalDistance() {
if(parentPlanet != -1)
return getParentProperties().getSolarOrbitalDistance();
return orbitalDist;
}
/**
* Sets this planet as a moon of the supplied planet's id.
* @param parentId parent planet's DIMID, or -1 for none
*/
public void setParentPlanet(DimensionProperties parent) {
this.setParentPlanet(parent, true);
}
/**
* Sets this planet as a moon of the supplied planet's ID
* @param parentId DIMID of the parent planet
* @param update true to update the parent's planet to the change
*/
public void setParentPlanet(DimensionProperties parent, boolean update) {
if(update) {
if(parentPlanet != -1)
parent.childPlanets.remove(new Integer(getId()));
parentPlanet = parent.getId();
star = parent.getStar();
if(parent.getId() != -1)
parent.childPlanets.add(getId());
}
else {
star = parent.getStar();
parentPlanet = parent.getId();
}
}
/**
* @return true if the planet has moons
*/
public boolean hasChildren() {
return !childPlanets.isEmpty();
}
/**
* @return true if this DIM orbits another
*/
public boolean isMoon() {
return parentPlanet != -1 && parentPlanet != SpaceObjectManager.WARPDIMID;
}
/**
* @return true if terraformed
*/
public boolean isTerraformed() {
return isTerraformed;
}
public int getAtmosphereDensity() {
return atmosphereDensity;
}
public void setAtmosphereDensity(int atmosphereDensity) {
int prevAtm = this.atmosphereDensity;
this.atmosphereDensity = atmosphereDensity;
if (AtmosphereTypes.getAtmosphereTypeFromValue(prevAtm) != AtmosphereTypes.getAtmosphereTypeFromValue(this.atmosphereDensity)) {
setTerraformedBiomes(getViableBiomes());
isTerraformed = true;
((ChunkManagerPlanet)((WorldProviderPlanet)net.minecraftforge.common.DimensionManager.getProvider(getId())).chunkMgrTerraformed).resetCache();
}
PacketHandler.sendToAll(new PacketDimInfo(getId(), this));
}
public void setAtmosphereDensityDirect(int atmosphereDensity) {
originalAtmosphereDensity = this.atmosphereDensity = atmosphereDensity;
}
/**
*
* @return true if the dimension properties refer to that of a space station or orbiting object registered in {@link SpaceObjectManager}
*/
public boolean isStation() {
return isStation;
}
//TODO: allow for more exotic atmospheres
/**
* @return the default atmosphere of this dimension
*/
public IAtmosphere getAtmosphere() {
if(hasAtmosphere())
return AtmosphereType.AIR;
return AtmosphereType.VACUUM;
}
/**
* @return {@link ResourceLocation} refering to the image to render as atmospheric haze as seen from orbit
*/
public static ResourceLocation getAtmosphereResource() {
return atmosphere;
}
public static ResourceLocation getAtmosphereLEOResource() {
return atmosphereLEO;
}
/**
* @return true if the planet has an atmosphere
*/
public boolean hasAtmosphere() {
return AtmosphereTypes.getAtmosphereTypeFromValue(atmosphereDensity).compareTo(AtmosphereTypes.NONE) < 0;
}
/**
* @return set of all moons orbiting this planet
*/
public Set<Integer> getChildPlanets() {
return childPlanets;
}
/**
* @return how many moons deep this planet is, IE: if the moon of a moon of a planet then three is returned
*/
public int getPathLengthToStar() {
if(isMoon())
return 1 + getParentProperties().getPathLengthToStar();
return 1;
}
/**
* Does not check for hierarchy loops!
* @param id DIMID of the new child
* @return true if successfully added as a child planet
*/
public boolean addChildPlanet(DimensionProperties child) {
//TODO: check for hierarchy loops!
if(child == this)
return false;
childPlanets.add(child.getId());
child.setParentPlanet(this);
return true;
}
/**
* Removes the passed DIMID from the list of moons
* @param id
*/
public void removeChild(int id) {
childPlanets.remove(id);
}
//Satallites --------------------------------------------------------
/**
* Adds a satellite to this DIM
* @param satellite satellite to add
* @param world world to add the satellite to
*/
public void addSatallite(SatelliteBase satellite, World world) {
satallites.put(satellite.getId(), satellite);
satellite.setDimensionId(world);
if(satellite.canTick())
tickingSatallites.put(satellite.getId(),satellite);
if(!world.isRemote)
PacketHandler.sendToAll(new PacketSatellite(satellite));
}
/**
* Really only meant to be used on the client when recieving a packet
* @param satallite
*/
public void addSatallite(SatelliteBase satallite) {
satallites.put(satallite.getId(), satallite);
if(satallite.canTick()) //TODO: check for dupes
tickingSatallites.put(satallite.getId(), satallite);
}
/**
* Removes the satellite from orbit around this world
* @param satalliteId ID # for this satellite
* @return reference to the satellite object
*/
public SatelliteBase removeSatellite(long satalliteId) {
SatelliteBase satallite = satallites.remove(satalliteId);
//if(satallite != null && satallite.canTick())
tickingSatallites.remove(satalliteId);
return satallite;
}
/**
* @param id ID # for this satellite
* @return a reference to the satelliteBase object given this ID
*/
public SatelliteBase getSatellite(long id) {
return satallites.get(id);
}
//TODO: multithreading
/**
* Tick satellites as needed
*/
public void tick() {
Iterator<SatelliteBase> iterator = tickingSatallites.values().iterator();
while(iterator.hasNext()) {
SatelliteBase satallite = iterator.next();
satallite.tickEntity();
if(satallite.isDead()) {
iterator.remove();
satallites.remove(satallite.getId());
}
}
this.prevOrbitalTheta = this.orbitTheta;
this.orbitTheta += (201-orbitalDist)*0.000005d;
}
public void updateOrbit() {
this.prevOrbitalTheta = this.orbitTheta;
this.orbitTheta = (AdvancedRocketry.proxy.getWorldTimeUniversal(getId())*(201-orbitalDist)*0.000002d) % (2*Math.PI);
}
/**
* @return true if this dimension is allowed to have rivers
*/
public boolean hasRivers() {
return AtmosphereTypes.getAtmosphereTypeFromValue(originalAtmosphereDensity).compareTo(AtmosphereTypes.LOW) <= 0 && Temps.getTempFromValue(averageTemperature).isInRange(Temps.COLD, Temps.HOT);
}
/**
* Each Planet is assigned a list of biomes that are allowed to spawn there
* @return List of biomes allowed to spawn on this planet
*/
public List<BiomeEntry> getBiomes() {
return (List<BiomeEntry>)allowedBiomes;
}
public List<BiomeEntry> getTerraformedBiomes() {
return (List<BiomeEntry>)terraformedBiomes;
}
/**
* Used to determine if a biome is allowed to spawn on ANY planet
* @param biome biome to check
* @return true if the biome is not allowed to spawn on any Dimension
*/
public boolean isBiomeblackListed(BiomeGenBase biome) {
return AdvancedRocketryBiomes.instance.getBlackListedBiomes().contains(biome.biomeID);
}
/**
* @return a list of biomes allowed to spawn in this dimension
*/
public List<BiomeGenBase> getViableBiomes() {
Random random = new Random(System.nanoTime());
List<BiomeGenBase> viableBiomes = new ArrayList<BiomeGenBase>();
if(atmosphereDensity > AtmosphereTypes.LOW.value && random.nextInt(3) == 0) {
List<BiomeGenBase> list = new LinkedList<BiomeGenBase>(AdvancedRocketryBiomes.instance.getSingleBiome());
while(list.size() > 1) {
BiomeGenBase biome = list.get(random.nextInt(list.size()));
Temps temp = Temps.getTempFromValue(averageTemperature);
if((biome.getTempCategory() == TempCategory.COLD && temp.isInRange(Temps.FRIGID, Temps.NORMAL)) ||
((biome.getTempCategory() == TempCategory.MEDIUM || biome.getTempCategory() == TempCategory.OCEAN) &&
temp.isInRange(Temps.COLD, Temps.HOT)) ||
(biome.getTempCategory() == TempCategory.WARM && temp.isInRange(Temps.NORMAL, Temps.HOT))) {
viableBiomes.add(biome);
return viableBiomes;
}
list.remove(biome);
}
}
if(atmosphereDensity <= AtmosphereTypes.LOW.value)
viableBiomes.add(AdvancedRocketryBiomes.moonBiome);
else if(averageTemperature > Temps.TOOHOT.getTemp()) {
viableBiomes.add(AdvancedRocketryBiomes.hotDryBiome);
}
else if(averageTemperature > Temps.HOT.getTemp()) {
for(BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) {
if(biome != null && (BiomeDictionary.isBiomeOfType(biome,BiomeDictionary.Type.HOT) || BiomeDictionary.isBiomeOfType(biome,BiomeDictionary.Type.OCEAN)) && !isBiomeblackListed(biome)) {
viableBiomes.add(biome);
}
}
}
else if(averageTemperature > Temps.NORMAL.getTemp()) {
for(BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) {
if(biome != null && !BiomeDictionary.isBiomeOfType(biome,BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome)) {
viableBiomes.add(biome);
}
}
viableBiomes.addAll(Arrays.asList(BiomeDictionary.getBiomesForType(BiomeDictionary.Type.OCEAN)));
}
else if(averageTemperature > Temps.COLD.getTemp()) {
for(BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) {
if(biome != null && !BiomeDictionary.isBiomeOfType(biome,BiomeDictionary.Type.HOT) && !isBiomeblackListed(biome)) {
viableBiomes.add(biome);
}
}
viableBiomes.addAll(Arrays.asList(BiomeDictionary.getBiomesForType(BiomeDictionary.Type.OCEAN)));
}
else if(averageTemperature > Temps.FRIGID.getTemp()) {
for(BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) {
if(biome != null && !BiomeDictionary.isBiomeOfType(biome,BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome)) {
viableBiomes.add(biome);
}
}
}
else {//(averageTemperature >= Temps.SNOWBALL.getTemp())
for(BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) {
if(biome != null && !BiomeDictionary.isBiomeOfType(biome,BiomeDictionary.Type.COLD) && !isBiomeblackListed(biome)) {
viableBiomes.add(biome);
}
}
//TODO:
}
if(viableBiomes.size() > 5) {
viableBiomes = ZUtils.copyRandomElements(viableBiomes, 5);
}
if(atmosphereDensity > AtmosphereTypes.HIGHPRESSURE.value && Temps.getTempFromValue(averageTemperature).isInRange(Temps.NORMAL, Temps.HOT))
viableBiomes.addAll(AdvancedRocketryBiomes.instance.getHighPressureBiomes());
return viableBiomes;
}
/**
* Adds a biome to the list of biomes allowed to spawn on this planet
* @param biome biome to be added as viable
*/
public void addBiome(BiomeGenBase biome) {
ArrayList<BiomeGenBase> biomes = new ArrayList<BiomeGenBase>();
biomes.add(biome);
allowedBiomes.addAll(getBiomesEntries(biomes));
}
/**
* Adds a biome to the list of biomes allowed to spawn on this planet
* @param biome biome to be added as viable
* @return true if the biome was added sucessfully, false otherwise
*/
public boolean addBiome(int biomeId) {
BiomeGenBase biome = BiomeGenBase.getBiome(biomeId);
if(biomeId == 0 || biome != BiomeGenBase.ocean) {
List<BiomeGenBase> biomes = new ArrayList<BiomeGenBase>();
biomes.add(biome);
allowedBiomes.addAll(getBiomesEntries(biomes));
return true;
}
return false;
}
/**
* Adds a list of biomes to the allowed list of biomes for this planet
* @param biomes
*/
public void addBiomes(List<BiomeGenBase> biomes) {
//TODO check for duplicates
allowedBiomes.addAll(getBiomesEntries(biomes));
}
/**
* Clears the list of allowed biomes and replaces it with the provided list
* @param biomes
*/
public void setBiomes(List<BiomeGenBase> biomes) {
allowedBiomes.clear();
addBiomes(biomes);
}
public void setTerraformedBiomes(List<BiomeGenBase> biomes) {
terraformedBiomes.clear();
terraformedBiomes.addAll(getBiomesEntries(biomes));
}
/**
* Adds all biomes of this type to the list of biomes allowed to generate
* @param type
*/
public void addBiomeType(BiomeDictionary.Type type) {
ArrayList<BiomeGenBase> entryList = new ArrayList<BiomeGenBase>();
entryList.addAll(Arrays.asList(BiomeDictionary.getBiomesForType(type)));
//Neither are acceptable on planets
entryList.remove(BiomeGenBase.hell);
entryList.remove(BiomeGenBase.sky);
//Make sure we dont add double entries
Iterator<BiomeGenBase> iter = entryList.iterator();
while(iter.hasNext()) {
BiomeGenBase nextbiome = iter.next();
for(BiomeEntry entry : allowedBiomes) {
if(BiomeDictionary.areBiomesEquivalent(entry.biome, nextbiome))
iter.remove();
}
}
allowedBiomes.addAll(getBiomesEntries(entryList));
}
/**
* Removes all biomes of this type from the list of biomes allowed to generate
* @param type
*/
public void removeBiomeType(BiomeDictionary.Type type) {
ArrayList<BiomeGenBase> entryList = new ArrayList<BiomeGenBase>();
entryList.addAll(Arrays.asList(BiomeDictionary.getBiomesForType(type)));
for(BiomeGenBase biome : entryList) {
Iterator<BiomeEntry> iterator = allowedBiomes.iterator();
while(iterator.hasNext()) {
if(BiomeDictionary.areBiomesEquivalent(iterator.next().biome, biome))
iterator.remove();
}
}
}
/**
* Gets a list of BiomeEntries allowed to spawn in this dimension
* @param biomeIds
* @return
*/
private ArrayList<BiomeEntry> getBiomesEntries(List<BiomeGenBase> biomeIds) {
ArrayList<BiomeEntry> biomeEntries = new ArrayList<BiomeManager.BiomeEntry>();
for(BiomeGenBase biomes : biomeIds) {
if(biomes == BiomeGenBase.desert) {
biomeEntries.add(new BiomeEntry(BiomeGenBase.desert, 30));
continue;
}
else if(biomes == BiomeGenBase.savanna) {
biomeEntries.add(new BiomeEntry(BiomeGenBase.savanna, 20));
continue;
}
else if(biomes == BiomeGenBase.plains) {
biomeEntries.add(new BiomeEntry(BiomeGenBase.plains, 10));
continue;
}
boolean notFound = true;
label:
for(BiomeManager.BiomeType types : BiomeManager.BiomeType.values()) {
for(BiomeEntry entry : BiomeManager.getBiomes(types)) {
if(biomes == null)
AdvancedRocketry.logger.warn("Null biomes loaded for DIMID: " + this.getId());
else if(entry.biome.biomeID == biomes.biomeID) {
biomeEntries.add(entry);
notFound = false;
break label;
}
}
}
if(notFound && biomes != null) {
biomeEntries.add(new BiomeEntry(biomes, 30));
}
}
return biomeEntries;
}
public void readFromNBT(NBTTagCompound nbt) {
NBTTagList list;
if(nbt.hasKey("skyColor")) {
list = nbt.getTagList("skyColor", NBT.TAG_FLOAT);
skyColor = new float[list.tagCount()];
for(int f = 0 ; f < list.tagCount(); f++) {
skyColor[f] = list.func_150308_e(f);
}
}
if(nbt.hasKey("sunriseSunsetColors")) {
list = nbt.getTagList("sunriseSunsetColors", NBT.TAG_FLOAT);
sunriseSunsetColors = new float[list.tagCount()];
for(int f = 0 ; f < list.tagCount(); f++) {
sunriseSunsetColors[f] = list.func_150308_e(f);
}
}
if(nbt.hasKey("fogColor")) {
list = nbt.getTagList("fogColor", NBT.TAG_FLOAT);
fogColor = new float[list.tagCount()];
for(int f = 0 ; f < list.tagCount(); f++) {
fogColor[f] = list.func_150308_e(f);
}
}
//Load biomes
if(nbt.hasKey("biomes")) {
allowedBiomes.clear();
int biomeIds[] = nbt.getIntArray("biomes");
List<BiomeGenBase> biomesList = new ArrayList<BiomeGenBase>();
for(int i = 0; i < biomeIds.length; i++) {
biomesList.add(AdvancedRocketryBiomes.instance.getBiomeById(biomeIds[i]));
}
allowedBiomes.addAll(getBiomesEntries(biomesList));
}
//Load biomes
if(nbt.hasKey("biomesTerra")) {
terraformedBiomes.clear();
int biomeIds[] = nbt.getIntArray("biomesTerra");
List<BiomeGenBase> biomesList = new ArrayList<BiomeGenBase>();
for(int i = 0; i < biomeIds.length; i++) {
biomesList.add(AdvancedRocketryBiomes.instance.getBiomeById(biomeIds[i]));
}
terraformedBiomes.addAll(getBiomesEntries(biomesList));
}
gravitationalMultiplier = nbt.getFloat("gravitationalMultiplier");
orbitalDist = nbt.getInteger("orbitalDist");
orbitTheta = nbt.getDouble("orbitTheta");
atmosphereDensity = nbt.getInteger("atmosphereDensity");
averageTemperature = nbt.getInteger("avgTemperature");
rotationalPeriod = nbt.getInteger("rotationalPeriod");
name = nbt.getString("name");
isNativeDimension = nbt.hasKey("isNative") ? nbt.getBoolean("isNative") : true; //Prevent world breakages when loading from old version
if(nbt.hasKey("originalAtmosphereDensity"))
originalAtmosphereDensity = nbt.getInteger("originalAtmosphereDensity");
else
originalAtmosphereDensity = atmosphereDensity;
isGasGiant = nbt.getBoolean("isGasGiant");
isTerraformed = nbt.getBoolean("terraformed");
orbitalPhi = nbt.getDouble("orbitPhi");
rotationalPhi = nbt.getDouble("rotationalPhi");
//Hierarchy
if(nbt.hasKey("childrenPlanets")) {
for(int i : nbt.getIntArray("childrenPlanets"))
childPlanets.add(i);
}
//Note: parent planet must be set before setting the star otherwise it would cause duplicate planets in the StellarBody's array
parentPlanet = nbt.getInteger("parentPlanet");
this.setStar( DimensionManager.getInstance().getStar(nbt.getInteger("starId")));
//Satallites
if(nbt.hasKey("satallites")) {
NBTTagCompound allSatalliteNbt = nbt.getCompoundTag("satallites");
for(Object keyObject : allSatalliteNbt.func_150296_c()) {
String key = (String)keyObject;
Long longKey = Long.parseLong(key);
NBTTagCompound satalliteNbt = allSatalliteNbt.getCompoundTag(key);
if(satallites.containsKey(longKey)){
satallites.get(longKey).readFromNBT(satalliteNbt);
}
else {
//Check for NBT errors
try {
SatelliteBase satallite = SatelliteRegistry.createFromNBT(satalliteNbt);
satallites.put(longKey, satallite);
if(satallite.canTick()) {
tickingSatallites.put(satallite.getId(), satallite);
}
} catch (NullPointerException e) {
AdvancedRocketry.logger.warn("Satellite with bad NBT detected, Removing");
}
}
}
}
}
public void writeToNBT(NBTTagCompound nbt) {
NBTTagList list;
if(skyColor != null) {
list = new NBTTagList();
for(float f : skyColor) {
list.appendTag(new NBTTagFloat(f));
}
nbt.setTag("skyColor", list);
}
if(sunriseSunsetColors != null) {
list = new NBTTagList();
for(float f : sunriseSunsetColors) {
list.appendTag(new NBTTagFloat(f));
}
nbt.setTag("sunriseSunsetColors", list);
}
list = new NBTTagList();
for(float f : fogColor) {
list.appendTag(new NBTTagFloat(f));
}
nbt.setTag("fogColor", list);
if(!allowedBiomes.isEmpty()) {
int biomeId[] = new int[allowedBiomes.size()];
for(int i = 0; i < allowedBiomes.size(); i++) {
biomeId[i] = allowedBiomes.get(i).biome.biomeID;
}
nbt.setIntArray("biomes", biomeId);
}
if(!terraformedBiomes.isEmpty()) {
int biomeId[] = new int[terraformedBiomes.size()];
for(int i = 0; i < terraformedBiomes.size(); i++) {
biomeId[i] = terraformedBiomes.get(i).biome.biomeID;
}
nbt.setIntArray("biomesTerra", biomeId);
}
nbt.setInteger("starId", starId);
nbt.setFloat("gravitationalMultiplier", gravitationalMultiplier);
nbt.setInteger("orbitalDist", orbitalDist);
nbt.setDouble("orbitTheta", orbitTheta);
nbt.setInteger("atmosphereDensity", atmosphereDensity);
nbt.setInteger("originalAtmosphereDensity", originalAtmosphereDensity);
nbt.setInteger("avgTemperature", averageTemperature);
nbt.setInteger("rotationalPeriod", rotationalPeriod);
nbt.setString("name", name);
nbt.setBoolean("isNative", isNativeDimension);
nbt.setBoolean("terraformed", isTerraformed);
nbt.setBoolean("isGasGiant", isGasGiant);
nbt.setDouble("orbitPhi", orbitalPhi);
nbt.setDouble("rotationalPhi", rotationalPhi);
//Hierarchy
if(!childPlanets.isEmpty()) {
Integer intList[] = new Integer[childPlanets.size()];
NBTTagIntArray childArray = new NBTTagIntArray(ArrayUtils.toPrimitive(childPlanets.toArray(intList)));
nbt.setTag("childrenPlanets", childArray);
}
nbt.setInteger("parentPlanet", parentPlanet);
//Satallites
if(!satallites.isEmpty()) {
NBTTagCompound allSatalliteNbt = new NBTTagCompound();
for(Entry<Long, SatelliteBase> entry : satallites.entrySet()) {
NBTTagCompound satalliteNbt = new NBTTagCompound();
entry.getValue().writeToNBT(satalliteNbt);
allSatalliteNbt.setTag(entry.getKey().toString(), satalliteNbt);
}
nbt.setTag("satallites", allSatalliteNbt);
}
}
public static DimensionProperties createFromNBT(int id, NBTTagCompound nbt) {
DimensionProperties properties = new DimensionProperties(id);
properties.readFromNBT(nbt);
properties.planetId = id;
return properties;
}
/**
* Function for calculating atmosphere thinning with respect to hieght
* @param y
* @return the density of the atmosphere at the given height
*/
public float getAtmosphereDensityAtHeight(double y) {
return atmosphereDensity*MathHelper.clamp_float((float) ( 1 + (256 - y)/200f), 0f,1f)/100f;
}
/**
* Gets the fog color at a given altitude, used to assist the illusion of thinning atmosphere
* @param y
* @param fogColor current fog color at this location
* @return
*/
public float[] getFogColorAtHeight(double y, Vec3 fogColor) {
float atmDensity = getAtmosphereDensityAtHeight(y);
return new float[] { (float) (atmDensity * fogColor.xCoord), (float) (atmDensity * fogColor.yCoord), (float) (atmDensity * fogColor.zCoord) };
}
/**
* Sets the planet's id
* @param id
*/
public void setId(int id) {
this.planetId = id;
}
public void setParentOrbitalDistance(int orbitalDistance) {
orbitalDist = orbitalDistance;
}
@Override
public String toString() {
return String.format("Dimension ID: %d. Dimension Name: %s. Parent Star %d ", getId(), getName(), getStarId());
}
@Override
public double getOrbitTheta() {
return orbitTheta;
}
@Override
public int getOrbitalDist() {
return orbitalDist;
}
}