blob: c1c55857119a47560dfd7076a940af70e4f71fe5 [file] [log] [blame] [raw]
package ic2.api;
import java.util.HashMap;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.ItemStack;
/**
* Base agriculture crop.
*
* Any crop extending this can be registered using registerCrop to be added into the game.
*/
public abstract class CropCard
{
/**
* Plant name. Will be displayed to the player.
*
* @return Plant name
*/
public abstract String name();
/**
* Your name here, will be shown in "Discovered by:" when analyzing seeds.
*
* @return Your name
*/
public String discoveredBy() {return "Alblaka";}
/**
* Description of your plant. Keep it short, a few characters per line for up to two lines.
* Default is showing attributes of your plant, 2 per line.
*
* @param i line to get, starting from 0
* @return The line
*/
public String desc(int i)
{
String[] att = attributes();
if (att == null || att.length==0) return "";
if (i == 0)
{
String s = att[0];
if (att.length >= 2)
{
s+=", "+att[1];
if (att.length >= 3) s+=",";
}
return s;
}
else
{
if (att.length < 3) return "";
String s = att[2];
if (att.length >= 4) s+=", "+att[3];
return s;
}
}
/**
* Tier of the plant. Ranges from 1 to 16, 0 is Weed.
* Valuable and powerful crops have higher tiers, useless and weak ones have lower tiers.
*
* @return Tier
*/
public abstract int tier();
/**
* Describe the plant through a set of stats, influencing breeding.
* Plants sharing stats and attributes will tend to cross-breed more often.
*
* Stats:
* - 0: Chemistry (Industrial uses based on chemical plant components)
* - 1: Consumable (Food, potion ingredients, stuff meant to be eaten or similarly used)
* - 2: Defensive (Plants with defense capabilities (damaging, explosive, chemical) or special abilities in general)
* - 3: Colorful (How colorful/aesthetically/beautiful is the plant, like dye-plants or plants without actual effects)
* - 4: Weed (Is this plant weed-like and rather unwanted/quick-spreading? Rare super-breed plants should have low values here)
*
* @param n index of the requested stat
* @return The requested value of the stats
*/
public abstract int stat(int n);
/**
* Additional attributes of the plant, also influencing breeding.
* Plants sharing stats and attributes will tend to cross-breed more often.
*
* @return Attributes as an array of strings
*/
public abstract String[] attributes();
/**
* Sprite index the crop is meant to be rendered with.
*
* @param crop reference to TECrop
* @return 0-255, representing the sprite index on the crop's spritesheet.
*/
public abstract int getSpriteIndex(TECrop crop);
/**
* Get the crop's spritesheet.
* Per default crops_0.png of ic2-sprites
* @return Texture file path
*/
public String getTextureFile() {
return "/ic2/sprites/crops_0.png";
}
/**
* Amount of growth points needed to increase the plant's size.
* Default is 200 * tier.
*/
public int growthDuration(TECrop crop)
{
return tier()*200;
}
/**
* Check whether the plant can grow further.
*
* Consider:
* - Humidity, nutrients and air quality
* - Current size
* - Light level
* - Special biomes or conditions, accessible through crop.worldObj
*
* This method will be called upon empty upgraded crops to check whether a neighboring plant can cross onto it! Don't check if the size is greater than 0 and if the ID is real.
*
* @param crop reference to TECrop
* @return Whether the crop can grow
*/
public abstract boolean canGrow(TECrop crop);
/**
* Calculate the influence for the plant to grow based on humidity, nutrients and air.
* Normal behavior is rating the three stats "normal", with each of them ranging from 0-30.
* Basic rule: Assume everything returns 10. All together must equal 30. Add the factors to your likings, for example (humidity*0.7)+(nutrients*0.9)+(air*1.4)
*
* Default is humidity + nutrients + air (no factors).
*
* @param crop reference to TECrop
* @param humidity ground humidity, influenced by hydration
* @param nutrients nutrient quality in ground, based on fertilizers
* @param air air quality, influences by open gardens and less crops surrounding this one
* @return 0-30
*/
public int weightInfluences(TECrop crop, float humidity, float nutrients, float air)
{
return (int) (humidity+nutrients+air);
}
/**
* Used to determine whether the plant can crossbreed with another crop.
* Default is allow crossbreeding if the size is greater or equal than 3.
*
* @param crop crop to crossbreed with
*/
public boolean canCross(TECrop crop)
{
return crop.size >= 3;
}
/**
* Called when the plant is rightclicked by a player.
* Default action is harvesting.
*
* @param crop reference to TECrop
* @param player player rightclicking the crop
* @return Whether the plant has changed
*/
public boolean rightclick(TECrop crop, EntityPlayer player)
{
return crop.harvest(true);
}
/**
* Check whether the crop can be harvested.
*
* @param crop reference to TECrop
* @return Whether the crop can be harvested in its current state.
*/
public abstract boolean canBeHarvested(TECrop crop);
/**
* Base chance for dropping the plant's gains, specify values greater than 1 for multiple drops.
* Default is 0.95^tier.
*
* @return Chance to drop the gains
*/
public float dropGainChance()
{
float base = 1F;
for (int i = 0; i < tier(); i++) {base*=0.95;}
return base;
}
/**
* Item obtained from harvesting the plant.
*
* @param crop reference to TECrop
* @return Item obtained
*/
public abstract ItemStack getGain(TECrop crop);
/**
* Get the size of the plant after harvesting.
* Default is 1.
*
* @param crop reference to TECrop
* @return Plant size after harvesting
*/
public byte getSizeAfterHarvest(TECrop crop) {return 1;}
/**
* Called when the plant is leftclicked by a player.
* Default action is picking the plant.
*
* @param crop reference to TECrop
* @param player player leftclicked the crop
* @return Whether the plant has changed
*/
public boolean leftclick(TECrop crop, EntityPlayer player)
{
return crop.pick(true);
}
/**
* Base chance for dropping seeds when the plant is picked.
* Default is 0.5*0.8^tier with a bigger chance for sizes greater than 2 and absolutely no chance for size 0.
*
* @param crop reference to TECrop
* @return Chance to drop the seeds
*/
public float dropSeedChance(TECrop crop)
{
if (crop.size == 1) return 0;
float base = 0.5F;
if (crop.size == 2) base/=2F;
for (int i = 0; i < tier(); i++) {base*=0.8;}
return base;
}
/**
* Obtain seeds dropped when the plant is picked.
* Multiple drops of the returned ItemStack can occur.
* Default action is generating a seed from this crop.
*
* @param crop reference to TECrop
* @return Seeds
*/
public ItemStack getSeeds(TECrop crop)
{
return crop.generateSeeds(crop.id, crop.statGrowth, crop.statGain, crop.statResistance, crop.scanLevel);
}
/**
* Called when a neighbor block to the crop has changed.
*
* @param crop reference to TECrop
*/
public void onNeighbourChange(TECrop crop){}
/**
* Check if the crop should emit redstone.
*
* @return Whether the crop should emit redstone
*/
public boolean emitRedstone(TECrop crop){return false;}
/**
* Called when the crop is destroyed.
*
* @param crop reference to TECrop
*/
public void onBlockDestroyed(TECrop crop){}
/**
* Get the light value emitted by the plant.
*
* @param crop reference to TECrop
* @return Light value emitted
*/
public int getEmittedLight(TECrop crop) {return 0;}
/**
* Default is true if the entity is an EntityLiving in jumping or sprinting state.
*
* @param crop reference to TECrop
* @param entity entity colliding
* @return Whether trampling calculation should happen, return false if the plant is no longer valid.
*/
public boolean onEntityCollision(TECrop crop, Entity entity)
{
if (entity instanceof EntityLiving)
{
return ((EntityLiving)entity).isSprinting();
}
return false;
}
/**
* Called every time the crop ticks.
* Should be called every 256 ticks or around 13 seconds.
*
* @param crop reference to TECrop
*/
public void tick(TECrop crop) {}
/**
* Check whether this plant spreads weed to surrounding tiles.
* Default is true if the plant has a high growth stat (or is weeds) and size greater or equal than 2.
*
* @param crop reference to TECrop
* @return Whether the plant spreads weed
*/
public boolean isWeed(TECrop crop)
{
return crop.size>=2 && (crop.id==0 || crop.statGrowth>=24);
}
/**
* Get this plant's ID.
*
* @return ID of this CropCard or -1 if it's not registered
*/
public final int getId()
{
for (int i = 0; i < cropCardList.length; i++)
{
if (this == cropCardList[i])
{
return i;
}
}
return -1;
}
private static final CropCard[] cropCardList = new CropCard[256];
/**
* Get the size of the plant list.
*
* @return Plant list size
*/
public static int cropCardListLength() {return cropCardList.length;}
/**
* Return the CropCard assigned to the given ID.
* If the ID is out of bounds, weed should be returned. If the ID is not registered, weed should be returned and a console print will notify.
*
* @param id plant ID
* @return Plant class
*/
public static final CropCard getCrop(int id)
{
if (id < 0 || id >= cropCardList.length)
{// Out of bounds
return cropCardList[0];
}
if (cropCardList[id]==null)
{// Out of bounds
System.out.println("[IndustrialCraft] Something tried to access non-existant cropID #"+id+"!!!");
return cropCardList[0];
}
return cropCardList[id];
}
/**
* Check whether the specified plant ID is already assigned.
* @param id ID to be checked
* @return true if the the given id is inbounds and the registered slot is not null
*/
public static final boolean idExists(int id)
{
return !(id < 0 || id >= cropCardList.length || cropCardList[id]==null);
}
/**
* Auto-assign an ID to a plant and register it.
* Usage of this method is not recommended! Other plants could take your IDs and cause your plants to turn into other plants.
*
* @param crop plant to register
* @return The ID assigned to the plant
*/
public static final short registerCrop(CropCard crop)
{
for (short x = 0; x < cropCardList.length; x++)
{// Iterate through list
if (cropCardList[x]==null)
{// Found empty slot, add crop here
cropCardList[x]=crop;
nameReference.addLocal("item.cropSeed"+x+".name", crop.name()+" Seeds");
return x;
}
}
//No free slot avaible
return -1;
}
/**
* Attempt to register a plant to an ID.
* If the ID is taken, the crop will not be registered and a console print will notify the user.
*
* @param crop plant to register
* @param i ID to register the plant to
* @return Whether the crop was registered
*/
public static final boolean registerCrop(CropCard crop, int i)
{
if (i < 0 || i >= cropCardList.length)
{// Out of bounds
return false;
}
if (cropCardList[i]==null)
{
cropCardList[i]=crop;
nameReference.addLocal("item.cropSeed"+i+".name", crop.name()+" Seeds");
return true;
}
System.out.println("[IndustrialCraft] Cannot add crop:"+crop.name()+" on ID #"+i+", slot already occupied by crop:"+cropCardList[i].name());
return false;
}
/**
* For internal usage only.
*/
public static TECrop nameReference;
private static HashMap<ItemStack, BaseSeed> baseseeds = new HashMap<ItemStack, BaseSeed>();
/**
* Registers a base seed, an item used to plant a crop.
*
* @param stack item
* @param id plant ID
* @param size initial size
* @param growth initial growth stat
* @param gain initial gain stat
* @param resistance initial resistance stat
* @return True if successful
*/
public static boolean registerBaseSeed(ItemStack stack, int id, int size, int growth, int gain, int resistance)
{
for (ItemStack key : baseseeds.keySet())
if (key.itemID==stack.itemID && key.getItemDamage()==stack.getItemDamage()) return false;
baseseeds.put(stack, new BaseSeed(id, size, growth, gain, resistance, stack.stackSize));
return true;
}
/**
* Finds a base seed from the given item.
*
* @return Base seed or null if none found
*/
public static BaseSeed getBaseSeed(ItemStack stack)
{
if (stack == null) return null;
for (ItemStack key : baseseeds.keySet())
{
if (key.itemID == stack.itemID &&
(key.getItemDamage() == -1 || key.getItemDamage() == stack.getItemDamage()))
{
return baseseeds.get(key);
}
}
return null;
}
}