Package forestry.arboriculture.genetics

Source Code of forestry.arboriculture.genetics.Tree

/*******************************************************************************
* Copyright (c) 2011-2014 SirSengir.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-3.0.txt
*
* Various Contributors including, but not limited to:
* SirSengir (original work), CovertJaguar, Player, Binnie, MysteriousAges
******************************************************************************/
package forestry.arboriculture.genetics;

import com.mojang.authlib.GameProfile;
import forestry.api.arboriculture.EnumGrowthConditions;
import forestry.api.arboriculture.EnumTreeChromosome;
import forestry.api.arboriculture.IAlleleLeafEffect;
import forestry.api.arboriculture.IAlleleTreeSpecies;
import forestry.api.arboriculture.IFruitProvider;
import forestry.api.arboriculture.ITree;
import forestry.api.arboriculture.ITreeGenome;
import forestry.api.arboriculture.ITreeMutation;
import forestry.api.genetics.IAllele;
import forestry.api.genetics.IAlleleBoolean;
import forestry.api.genetics.IChromosome;
import forestry.api.genetics.IEffectData;
import forestry.api.genetics.IFruitFamily;
import forestry.api.genetics.IGenome;
import forestry.api.world.ITreeGenData;
import forestry.core.genetics.Allele;
import forestry.core.genetics.Chromosome;
import forestry.core.genetics.Individual;
import forestry.core.utils.StringUtil;
import forestry.plugins.PluginArboriculture;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.StatCollector;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenerator;
import net.minecraftforge.common.EnumPlantType;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.common.util.ForgeDirection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;

public class Tree extends Individual implements ITree, ITreeGenData, IPlantable {

  private ITreeGenome genome;
  private ITreeGenome mate;

  /* CONSTRUCTOR */
  public Tree(NBTTagCompound nbttagcompound) {
    readFromNBT(nbttagcompound);
  }

  public Tree(ITreeGenome genome) {
    this.genome = genome;
  }

  public Tree(World world, ITreeGenome genome) {
    this.genome = genome;

  }

  /* SAVING & LOADING */
  @Override
  public void readFromNBT(NBTTagCompound nbttagcompound) {

    super.readFromNBT(nbttagcompound);

    if (nbttagcompound.hasKey("Genome"))
      genome = new TreeGenome(nbttagcompound.getCompoundTag("Genome"));
    else
      genome = PluginArboriculture.treeInterface.templateAsGenome(TreeTemplates.getOakTemplate());
    if (nbttagcompound.hasKey("Mate"))
      mate = new TreeGenome(nbttagcompound.getCompoundTag("Mate"));

  }

  @Override
  public void writeToNBT(NBTTagCompound nbttagcompound) {

    super.writeToNBT(nbttagcompound);

    if (genome != null) {
      NBTTagCompound NBTmachine = new NBTTagCompound();
      genome.writeToNBT(NBTmachine);
      nbttagcompound.setTag("Genome", NBTmachine);
    }
    if (mate != null) {
      NBTTagCompound NBTmachine = new NBTTagCompound();
      mate.writeToNBT(NBTmachine);
      nbttagcompound.setTag("Mate", NBTmachine);
    }

  }

  /* INTERACTION */
  @Override
  public void mate(ITree other) {
    mate = new TreeGenome(other.getGenome().getChromosomes());
  }

  /* EFFECTS */
  @Override
  public IEffectData[] doEffect(IEffectData[] storedData, World world, int biomeid, int x, int y, int z) {
    IAlleleLeafEffect effect = (IAlleleLeafEffect) getGenome().getActiveAllele(EnumTreeChromosome.EFFECT.ordinal());

    if (effect == null)
      return null;

    storedData[0] = doEffect(effect, storedData[0], world, biomeid, x, y, z);

    // Return here if the primary can already not be combined
    if (!effect.isCombinable())
      return storedData;

    IAlleleLeafEffect secondary = (IAlleleLeafEffect) getGenome().getInactiveAllele(EnumTreeChromosome.EFFECT.ordinal());
    if (!secondary.isCombinable())
      return storedData;

    storedData[1] = doEffect(secondary, storedData[1], world, biomeid, x, y, z);

    return storedData;
  }

  private IEffectData doEffect(IAlleleLeafEffect effect, IEffectData storedData, World world, int biomeid, int x, int y, int z) {
    storedData = effect.validateStorage(storedData);
    return effect.doEffect(getGenome(), storedData, world, x, y, z);
  }

  @Override
  public IEffectData[] doFX(IEffectData[] storedData, World world, int biomeid, int x, int y, int z) {
    return null;
  }

  /* GROWTH */
  @Override
  public WorldGenerator getTreeGenerator(World world, int x, int y, int z, boolean wasBonemealed) {
    return genome.getPrimary().getGenerator(this, world, x, y, z);
  }

  @Override
  public boolean canStay(World world, int x, int y, int z) {
    Block block = world.getBlock(x, y - 1, z);
    if (block == null)
      return false;

    for (EnumPlantType type : getPlantTypes()) {
      this.plantType = type;
      if (block.canSustainPlant(world, x, y - 1, z, ForgeDirection.UP, this))
        return true;
    }

    return false;
  }

  private EnumPlantType plantType;

  @Override
  public EnumPlantType getPlantType(IBlockAccess world, int x, int y, int z) {
    return plantType;
  }

  @Override
  public Block getPlant(IBlockAccess world, int x, int y, int z) {
    return null;
  }

  @Override
  public int getPlantMetadata(IBlockAccess world, int x, int y, int z) {
    return 0;
  }

  @Override
  public boolean canGrow(World world, int x, int y, int z, int expectedGirth, int expectedHeight) {
    return genome.getGrowthProvider().canGrow(genome, world, x, y, z, expectedGirth, expectedHeight);
  }

  @Override
  public int getRequiredMaturity() {
    return genome.getMaturationTime();
  }

  @Override
  public EnumGrowthConditions getGrowthCondition(World world, int x, int y, int z) {
    return genome.getGrowthProvider().getGrowthConditions(getGenome(), world, x, y, z);
  }

  @Override
  public int getGirth(World world, int x, int y, int z) {
    return genome.getGirth();
  }

  @Override
  public int getResilience() {
    int base = (int)(getGenome().getFertility() * getGenome().getSappiness() * 100);
    return (base > 1 ? base : 1) * 10;
  }

  @Override
  public float getHeightModifier() {
    return genome.getHeight();
  }

  @Override
  public void setLeaves(World world, GameProfile owner, int x, int y, int z) {
    PluginArboriculture.treeInterface.setLeaves(world, this, owner, x, y, z);
  }

  @Override
  public boolean allowsFruitBlocks() {
    IFruitProvider provider = getGenome().getFruitProvider();
    if (!provider.requiresFruitBlocks())
      return false;

    Collection<IFruitFamily> suitable = genome.getPrimary().getSuitableFruit();
    if (!suitable.contains(provider.getFamily()))
      return false;

    return true;
  }

  @Override
  public boolean trySpawnFruitBlock(World world, int x, int y, int z) {
    IFruitProvider provider = getGenome().getFruitProvider();
    Collection<IFruitFamily> suitable = genome.getPrimary().getSuitableFruit();
    if (!suitable.contains(provider.getFamily()))
      return false;

    return provider.trySpawnFruitBlock(getGenome(), world, x, y, z);
  }

  /* INFORMATION */
  @Override
  public ITreeGenome getGenome() {
    return this.genome;
  }

  @Override
  public ITree copy() {
    NBTTagCompound nbttagcompound = new NBTTagCompound();
    this.writeToNBT(nbttagcompound);
    return new Tree(nbttagcompound);
  }

  @Override
  public ITreeGenome getMate() {
    return this.mate;
  }

  @Override
  public boolean isPureBred(EnumTreeChromosome chromosome) {
    return genome.getActiveAllele(chromosome.ordinal()).getUID().equals(genome.getInactiveAllele(chromosome.ordinal()).getUID());
  }

  @Override
  public EnumSet<EnumPlantType> getPlantTypes() {
    EnumSet<EnumPlantType> tolerated = genome.getPlantTypes();
    tolerated.add(genome.getPrimary().getPlantType());
    return tolerated;
  }

  @Override
  public void addTooltip(List<String> list) {

    // No info 4 u!
    if (!isAnalyzed) {
      list.add("<" + StringUtil.localize("gui.unknown") + ">");
      return;
    }

    // You analyzed it? Juicy tooltip coming up!
    IAlleleTreeSpecies primary = genome.getPrimary();
    IAlleleTreeSpecies secondary = genome.getSecondary();
    if (!isPureBred(EnumTreeChromosome.SPECIES))
      list.add("\u00A79" + StringUtil.localize("trees.hybrid").replaceAll("%PRIMARY",primary.getName()).replaceAll("%SECONDARY",secondary.getName()));
    list.add(String.format("\u00A76S: %s, \u00A7cM: %s", genome.getActiveAllele(EnumTreeChromosome.SAPPINESS.ordinal()).getName(), genome.getActiveAllele(EnumTreeChromosome.MATURATION.ordinal()).getName()));
    list.add(String.format("\u00A7dH: %s, \u00A7bG: %sx%s", genome.getActiveAllele(EnumTreeChromosome.HEIGHT.ordinal()).getName(), genome.getGirth(), genome.getGirth()));

    list.add(String.format("\u00A7eS: %s, \u00A7fY: %s", genome.getActiveAllele(EnumTreeChromosome.FERTILITY.ordinal()).getName(), genome.getActiveAllele(EnumTreeChromosome.YIELD.ordinal()).getName()));

    IAlleleBoolean primaryFireproof = (IAlleleBoolean)genome.getActiveAllele(EnumTreeChromosome.FIREPROOF.ordinal());
    if (primaryFireproof.getValue())
      list.add(String.format("\u00A7c%s", StatCollector.translateToLocal("for.gui.fireresist")));

    IAllele fruit = getGenome().getActiveAllele(EnumTreeChromosome.FRUITS.ordinal());
    if(fruit != Allele.fruitNone) {
      String strike = "";
      if (!canBearFruit())
        strike = "\u00A7m";
      list.add(strike + "\u00A7aF: " + StringUtil.localize(genome.getFruitProvider().getDescription()));
    }

  }

  /* REPRODUCTION */
  @Override
  public ITree[] getSaplings(World world, int x, int y, int z, float modifier) {
    ArrayList<ITree> prod = new ArrayList<ITree>();

    float chance = genome.getFertility() * modifier;

    if (world.rand.nextFloat() <= chance)
      if (this.getMate() == null)
        prod.add(PluginArboriculture.treeInterface.getTree(world, new TreeGenome(genome.getChromosomes())));
      else
        prod.add(createOffspring(world, x, y, z));

    return prod.toArray(new ITree[0]);
  }

  private ITree createOffspring(World world, int x, int y, int z) {

    IChromosome[] chromosomes = new IChromosome[genome.getChromosomes().length];
    IChromosome[] parent1 = genome.getChromosomes();
    IChromosome[] parent2 = mate.getChromosomes();

    // Check for mutation. Replace one of the parents with the mutation
    // template if mutation occured.
    IChromosome[] mutated = mutateSpecies(world, x, y, z, genome, mate);
    if (mutated == null)
      mutated = mutateSpecies(world, x, y, z, mate, genome);

    if (mutated != null)
      return new Tree(world, new TreeGenome(mutated));

    for (int i = 0; i < parent1.length; i++)
      if (parent1[i] != null && parent2[i] != null)
        chromosomes[i] = Chromosome.inheritChromosome(world.rand, parent1[i], parent2[i]);

    return new Tree(world, new TreeGenome(chromosomes));
  }

  private IChromosome[] mutateSpecies(World world, int x, int y, int z, IGenome genomeOne, IGenome genomeTwo) {

    IChromosome[] parent1 = genomeOne.getChromosomes();
    IChromosome[] parent2 = genomeTwo.getChromosomes();

    IGenome genome0;
    IGenome genome1;
    IAllele allele0;
    IAllele allele1;

    if (world.rand.nextBoolean()) {
      allele0 = parent1[EnumTreeChromosome.SPECIES.ordinal()].getPrimaryAllele();
      allele1 = parent2[EnumTreeChromosome.SPECIES.ordinal()].getSecondaryAllele();

      genome0 = genomeOne;
      genome1 = genomeTwo;
    } else {
      allele0 = parent2[EnumTreeChromosome.SPECIES.ordinal()].getPrimaryAllele();
      allele1 = parent1[EnumTreeChromosome.SPECIES.ordinal()].getSecondaryAllele();

      genome0 = genomeTwo;
      genome1 = genomeOne;
    }

    for (ITreeMutation mutation : PluginArboriculture.treeInterface.getMutations(true)) {
      float chance = 0;

      // Stop blacklisted species.
      // if (BeeManager.breedingManager.isBlacklisted(mutation.getTemplate()[0].getUID())) {
      // continue;
      // }

      if ((chance = mutation.getChance(world, x, y, z, allele0, allele1, genome0, genome1)) > 0)
        if (world.rand.nextFloat()*100 < chance)
          // IApiaristTracker breedingTracker = BeeManager.breedingManager.getApiaristTracker(world);
          // breedingTracker.registerMutation(mutation);
          return PluginArboriculture.treeInterface.templateAsChromosomes(mutation.getTemplate());
    }

    return null;
  }

  /* PRODUCTION */
  @Override
  public boolean canBearFruit() {
    return genome.getPrimary().getSuitableFruit().contains(genome.getFruitProvider().getFamily());
  }

  @Override
  public ItemStack[] getProduceList() {
    return genome.getFruitProvider().getProducts();
  }

  @Override
  public ItemStack[] getSpecialtyList() {
    return genome.getFruitProvider().getSpecialty();
  }

  @Override
  public ItemStack[] produceStacks(World world, int x, int y, int z, int ripeningTime) {
    return genome.getFruitProvider().getFruits(genome, world, x, y, z, ripeningTime);
  }

}
TOP

Related Classes of forestry.arboriculture.genetics.Tree

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.