Ported beginnings of Thaumcraft compatibility to 1.8.9

This commit is contained in:
Adubbz 2016-01-09 20:53:06 +11:00
parent a4b78504e6
commit c647fee66e
76 changed files with 6462 additions and 0 deletions

View file

@ -0,0 +1,76 @@
package thaumcraft.api;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.blocks.BlocksTC;
import thaumcraft.api.items.ItemsTC;
public class OreDictionaryEntries {
/**
* I included this in the API to make it simpler to see what items and blocks are ore dictionaried
*/
public static void initializeOreDictionary() {
OreDictionary.registerOre("oreAmber", new ItemStack(BlocksTC.oreAmber));
OreDictionary.registerOre("oreCinnabar", new ItemStack(BlocksTC.oreCinnabar));
OreDictionary.registerOre("logWood", new ItemStack(BlocksTC.log,1,0));
OreDictionary.registerOre("logWood", new ItemStack(BlocksTC.log,1,3));
OreDictionary.registerOre("plankWood", new ItemStack(BlocksTC.plank,1,0));
OreDictionary.registerOre("plankWood", new ItemStack(BlocksTC.plank,1,1));
OreDictionary.registerOre("slabWood", new ItemStack(BlocksTC.slabWood,1,0));
OreDictionary.registerOre("slabWood", new ItemStack(BlocksTC.slabWood,1,1));
OreDictionary.registerOre("treeSapling", new ItemStack(BlocksTC.sapling,1,0));
OreDictionary.registerOre("treeSapling", new ItemStack(BlocksTC.sapling,1,1));
OreDictionary.registerOre("shardAir", new ItemStack(ItemsTC.shard,1,0));
OreDictionary.registerOre("shardFire", new ItemStack(ItemsTC.shard,1,1));
OreDictionary.registerOre("shardWater", new ItemStack(ItemsTC.shard,1,2));
OreDictionary.registerOre("shardEarth", new ItemStack(ItemsTC.shard,1,3));
OreDictionary.registerOre("shardOrder", new ItemStack(ItemsTC.shard,1,4));
OreDictionary.registerOre("shardEntropy", new ItemStack(ItemsTC.shard,1,5));
OreDictionary.registerOre("shardTainted", new ItemStack(ItemsTC.shard,1,6));
OreDictionary.registerOre("shardBalanced", new ItemStack(ItemsTC.shard,1,7));
OreDictionary.registerOre("nitor", new ItemStack(BlocksTC.nitor,1,OreDictionary.WILDCARD_VALUE));
OreDictionary.registerOre("gemAmber", new ItemStack(ItemsTC.amber));
OreDictionary.registerOre("quicksilver", new ItemStack(ItemsTC.quicksilver));
OreDictionary.registerOre("nuggetGold", new ItemStack(ItemsTC.coin));
OreDictionary.registerOre("nuggetIron", new ItemStack(ItemsTC.nuggets,1,0));
OreDictionary.registerOre("nuggetCopper", new ItemStack(ItemsTC.nuggets,1,1));
OreDictionary.registerOre("nuggetTin", new ItemStack(ItemsTC.nuggets,1,2));
OreDictionary.registerOre("nuggetSilver", new ItemStack(ItemsTC.nuggets,1,3));
OreDictionary.registerOre("nuggetLead", new ItemStack(ItemsTC.nuggets,1,4));
OreDictionary.registerOre("nuggetQuicksilver", new ItemStack(ItemsTC.nuggets,1,5));
OreDictionary.registerOre("nuggetThaumium", new ItemStack(ItemsTC.nuggets,1,6));
OreDictionary.registerOre("nuggetVoid", new ItemStack(ItemsTC.nuggets,1,7));
OreDictionary.registerOre("nuggetBrass", new ItemStack(ItemsTC.nuggets,1,8));
OreDictionary.registerOre("ingotThaumium", new ItemStack(ItemsTC.ingots,1,0));
OreDictionary.registerOre("ingotVoid", new ItemStack(ItemsTC.ingots,1,1));
OreDictionary.registerOre("ingotBrass", new ItemStack(ItemsTC.ingots,1,2));
OreDictionary.registerOre("blockThaumium", new ItemStack(BlocksTC.metal,1,0));
OreDictionary.registerOre("blockVoid", new ItemStack(BlocksTC.metal,1,1));
OreDictionary.registerOre("blockBrass", new ItemStack(BlocksTC.metal,1,4));
OreDictionary.registerOre("plateIron", new ItemStack(ItemsTC.plate,1,1));
OreDictionary.registerOre("gearBrass", new ItemStack(ItemsTC.gear,1,0));
OreDictionary.registerOre("plateBrass", new ItemStack(ItemsTC.plate,1,0));
OreDictionary.registerOre("gearThaumium", new ItemStack(ItemsTC.gear,1,1));
OreDictionary.registerOre("plateThaumium", new ItemStack(ItemsTC.plate,1,2));
OreDictionary.registerOre("gearVoid", new ItemStack(ItemsTC.gear,1,2));
OreDictionary.registerOre("plateVoid", new ItemStack(ItemsTC.plate,1,3));
OreDictionary.registerOre("clusterIron", new ItemStack(ItemsTC.clusters,1,0));
OreDictionary.registerOre("clusterGold", new ItemStack(ItemsTC.clusters,1,1));
OreDictionary.registerOre("clusterCopper", new ItemStack(ItemsTC.clusters,1,2));
OreDictionary.registerOre("clusterTin", new ItemStack(ItemsTC.clusters,1,3));
OreDictionary.registerOre("clusterSilver", new ItemStack(ItemsTC.clusters,1,4));
OreDictionary.registerOre("clusterLead", new ItemStack(ItemsTC.clusters,1,5));
OreDictionary.registerOre("clusterCinnabar", new ItemStack(ItemsTC.clusters,1,6));
}
}

View file

@ -0,0 +1,650 @@
package thaumcraft.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectHelper;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.crafting.CrucibleRecipe;
import thaumcraft.api.crafting.InfusionEnchantmentRecipe;
import thaumcraft.api.crafting.InfusionRecipe;
import thaumcraft.api.crafting.ShapedArcaneRecipe;
import thaumcraft.api.crafting.ShapelessArcaneRecipe;
import thaumcraft.api.internal.DummyInternalMethodHandler;
import thaumcraft.api.internal.IInternalMethodHandler;
import thaumcraft.api.internal.WeightedRandomLoot;
import thaumcraft.api.research.ResearchCategories;
import thaumcraft.api.research.ResearchCategoryList;
import thaumcraft.api.research.ResearchHelper;
import thaumcraft.api.research.ResearchItem;
import thaumcraft.api.research.ResearchPage;
/**
* @author Azanor
*
*
* IMPORTANT: If you are adding your own aspects to items it is a good idea to do it AFTER Thaumcraft adds its aspects, otherwise odd things may happen.
*
*/
public class ThaumcraftApi {
//Internal (Do not alter this unless you like pretty explosions)
//Calling methods from this will only work properly once Thaumcraft is past the FMLPreInitializationEvent phase.
public static IInternalMethodHandler internalMethods = new DummyInternalMethodHandler();
//RESEARCH/////////////////////////////////////////
public static ArrayList<EntityTags> scanEntities = new ArrayList<EntityTags>();
public static class EntityTagsNBT {
public EntityTagsNBT(String name, Object value) {
this.name = name;
this.value = value;
}
public String name;
public Object value;
}
public static class EntityTags {
public EntityTags(String entityName, AspectList aspects, EntityTagsNBT... nbts) {
this.entityName = entityName;
this.nbts = nbts;
this.aspects = aspects;
}
public String entityName;
public EntityTagsNBT[] nbts;
public AspectList aspects;
}
/**
* This is used to add aspects to entities which you can then scan using a thaumometer.
* Also used to calculate vis drops from mobs.
* @param entityName
* @param aspects
* @param nbt you can specify certain nbt keys and their values
* to differentiate between mobs. <br>For example the normal and wither skeleton:
* <br>ThaumcraftApi.registerEntityTag("Skeleton", (new AspectList()).add(Aspect.DEATH, 5));
* <br>ThaumcraftApi.registerEntityTag("Skeleton", (new AspectList()).add(Aspect.DEATH, 8), new NBTTagByte("SkeletonType",(byte) 1));
*/
public static void registerEntityTag(String entityName, AspectList aspects, EntityTagsNBT... nbt ) {
scanEntities.add(new EntityTags(entityName,aspects,nbt));
}
//RECIPES/////////////////////////////////////////
private static ArrayList craftingRecipes = new ArrayList();
private static HashMap<Object,ItemStack> smeltingBonus = new HashMap<Object,ItemStack>();
/**
* This method is used to determine what bonus items are generated when the infernal furnace smelts items
* @param in The input of the smelting operation. e.g. new ItemStack(Block.oreGold)
* @param out The bonus item that can be produced from the smelting operation e.g. new ItemStack(nuggetGold,0,0).
* Stacksize should be 0 unless you want to guarantee that at least 1 item is always produced.
*/
public static void addSmeltingBonus(ItemStack in, ItemStack out) {
smeltingBonus.put(
Arrays.asList(in.getItem(),in.getItemDamage()),
new ItemStack(out.getItem(),0,out.getItemDamage()));
}
/**
* This method is used to determine what bonus items are generated when the infernal furnace smelts items
* @param in The ore dictionary input of the smelting operation. e.g. "oreGold"
* @param out The bonus item that can be produced from the smelting operation e.g. new ItemStack(nuggetGold,0,0).
* Stacksize should be 0 unless you want to guarantee that at least 1 item is always produced.
*/
public static void addSmeltingBonus(String in, ItemStack out) {
smeltingBonus.put( in, new ItemStack(out.getItem(),0,out.getItemDamage()));
}
/**
* Returns the bonus item produced from a smelting operation in the infernal furnace
* @param in The input of the smelting operation. e.g. new ItemStack(oreGold)
* @return the The bonus item that can be produced
*/
public static ItemStack getSmeltingBonus(ItemStack in) {
ItemStack out = smeltingBonus.get(Arrays.asList(in.getItem(),in.getItemDamage()));
if (out==null) {
out = smeltingBonus.get(Arrays.asList(in.getItem(),OreDictionary.WILDCARD_VALUE));
}
if (out==null) {
for (int id:OreDictionary.getOreIDs(in)) {
String od = OreDictionary.getOreName( id);
out = smeltingBonus.get(od);
if (out!=null) break;
}
}
return out;
}
public static List getCraftingRecipes() {
return craftingRecipes;
}
/**
* @param research the research key required for this recipe to work. Leave blank if it will work without research
* @param result the recipe output
* @param aspects the vis cost per aspect.
* @param recipe The recipe. Format is exactly the same as vanilla recipes. Input itemstacks are NBT sensitive.
*/
public static ShapedArcaneRecipe addArcaneCraftingRecipe(String research, ItemStack result, AspectList aspects, Object ... recipe)
{
ShapedArcaneRecipe r= new ShapedArcaneRecipe(research, result, aspects, recipe);
craftingRecipes.add(r);
CraftingManager.getInstance().addRecipe(r);
return r;
}
/**
* @param research the research keys required for this recipe to work. Leave blank if it will work without research
* @param result the recipe output
* @param aspects the vis cost per aspect.
* @param recipe The recipe. Format is exactly the same as vanilla recipes. Input itemstacks are NBT sensitive.
*/
public static ShapedArcaneRecipe addArcaneCraftingRecipe(String[] research, ItemStack result, AspectList aspects, Object ... recipe)
{
ShapedArcaneRecipe r= new ShapedArcaneRecipe(research, result, aspects, recipe);
craftingRecipes.add(r);
CraftingManager.getInstance().addRecipe(r);
return r;
}
/**
* @param research the research key required for this recipe to work. Leave blank if it will work without research
* @param result the recipe output
* @param aspects the vis cost per aspect
* @param recipe The recipe. Format is exactly the same as vanilla shapeless recipes. Input itemstacks are NBT sensitive.
*/
public static ShapelessArcaneRecipe addShapelessArcaneCraftingRecipe(String research, ItemStack result, AspectList aspects, Object ... recipe)
{
ShapelessArcaneRecipe r = new ShapelessArcaneRecipe(research, result, aspects, recipe);
craftingRecipes.add(r);
CraftingManager.getInstance().addRecipe(r);
return r;
}
/**
* @param research the research keys required for this recipe to work. Leave blank if it will work without research
* @param result the recipe output
* @param aspects the vis cost per aspect
* @param recipe The recipe. Format is exactly the same as vanilla shapeless recipes. Input itemstacks are NBT sensitive.
*/
public static ShapelessArcaneRecipe addShapelessArcaneCraftingRecipe(String[] research, ItemStack result, AspectList aspects, Object ... recipe)
{
ShapelessArcaneRecipe r = new ShapelessArcaneRecipe(research, result, aspects, recipe);
craftingRecipes.add(r);
CraftingManager.getInstance().addRecipe(r);
return r;
}
/**
* @param research the research key required for this recipe to work. Leave blank if it will work without research
* @param result the recipe output. It can either be an itemstack or an nbt compound tag that will be added to the central item
* @param instability a number that represents the N in 1000 chance for the infusion altar to spawn an
* instability effect each second while the crafting is in progress
* @param aspects the essentia cost per aspect.
* @param aspects input the central item to be infused. If string is passed it will look up oredictionary entries
* @param recipe An array of items required to craft this. Input itemstacks are NBT sensitive.
* If string is passed it will look up oredictionary entries.
*/
public static InfusionRecipe addInfusionCraftingRecipe(String research,
Object result, int instability, AspectList aspects, Object input, Object[] recipe)
{
if (!(result instanceof ItemStack || result instanceof Object[])) return null;
InfusionRecipe r= new InfusionRecipe(research, result, instability, aspects, input, recipe);
craftingRecipes.add(r);
return r;
}
/**
* @param research the research keys required for this recipe to work. Leave blank if it will work without research
* @param result the recipe output. It can either be an itemstack or an nbt compound tag that will be added to the central item
* @param instability a number that represents the N in 1000 chance for the infusion altar to spawn an
* instability effect each second while the crafting is in progress
* @param aspects the essentia cost per aspect.
* @param aspects input the central item to be infused. If string is passed it will look up oredictionary entries
* @param recipe An array of items required to craft this. Input itemstacks are NBT sensitive.
* If string is passed it will look up oredictionary entries.
*/
public static InfusionRecipe addInfusionCraftingRecipe(String[] research,
Object result, int instability, AspectList aspects, Object input, Object[] recipe)
{
if (!(result instanceof ItemStack || result instanceof Object[])) return null;
InfusionRecipe r= new InfusionRecipe(research, result, instability, aspects, input, recipe);
craftingRecipes.add(r);
return r;
}
/**
* @param research the research key required for this recipe to work. Leave blank if it will work without research
* @param enchantment the enchantment that will be applied to the item
* @param instability a number that represents the N in 1000 chance for the infusion altar to spawn an
* instability effect each second while the crafting is in progress
* @param aspects the essentia cost per aspect.
* @param recipe An array of items required to craft this. Input itemstacks are NBT sensitive.
* If string is passed it will look up oredictionary entries.
*/
@Deprecated
public static InfusionEnchantmentRecipe addInfusionEnchantmentRecipe(String research, Enchantment enchantment, int instability, AspectList aspects, Object[] recipe)
{
InfusionEnchantmentRecipe r= new InfusionEnchantmentRecipe(research, enchantment, instability, aspects, recipe);
craftingRecipes.add(r);
return r;
}
/**
* @param stack the recipe result
* @return the recipe
*/
public static InfusionRecipe getInfusionRecipe(ItemStack res) {
for (Object r:getCraftingRecipes()) {
if (r instanceof InfusionRecipe) {
if (((InfusionRecipe)r).getRecipeOutput() instanceof ItemStack) {
if (((ItemStack) ((InfusionRecipe)r).getRecipeOutput()).isItemEqual(res))
return (InfusionRecipe)r;
}
}
}
return null;
}
/**
* @param key the research key required for this recipe to work.
* @param result the output result
* @param catalyst an itemstack of the catalyst or a string if it is an ore dictionary item
* @param cost the vis cost
* @param tags the aspects required to craft this
*/
public static CrucibleRecipe addCrucibleRecipe(String key, ItemStack result, Object catalyst, AspectList tags) {
CrucibleRecipe rc = new CrucibleRecipe(key, result, catalyst, tags);
getCraftingRecipes().add(rc);
return rc;
}
/**
* @param stack the recipe result
* @return the recipe
*/
public static CrucibleRecipe getCrucibleRecipe(ItemStack stack) {
for (Object r:getCraftingRecipes()) {
if (r instanceof CrucibleRecipe) {
if (((CrucibleRecipe)r).getRecipeOutput().isItemEqual(stack))
return (CrucibleRecipe)r;
}
}
return null;
}
/**
* @param hash the unique recipe code
* @return the recipe
*/
public static CrucibleRecipe getCrucibleRecipeFromHash(int hash) {
for (Object r:getCraftingRecipes()) {
if (r instanceof CrucibleRecipe) {
if (((CrucibleRecipe)r).hash==hash)
return (CrucibleRecipe)r;
}
}
return null;
}
/**
* Used by the thaumonomicon drilldown feature.
* @param stack the item
* @return the thaumcraft recipe key that produces that item.
*/
private static HashMap<int[],Object[]> keyCache = new HashMap<int[],Object[]>();
public static Object[] getCraftingRecipeKey(EntityPlayer player, ItemStack stack) {
int[] key = new int[] {Item.getIdFromItem(stack.getItem()),stack.getItemDamage()};
if (keyCache.containsKey(key)) {
if (keyCache.get(key)==null) return null;
if (ResearchHelper.isResearchComplete(player.getName(), (String)(keyCache.get(key))[0]))
return keyCache.get(key);
else
return null;
}
for (ResearchCategoryList rcl:ResearchCategories.researchCategories.values()) {
for (ResearchItem ri:rcl.research.values()) {
if (ri.getPages()==null) continue;
for (int a=0;a<ri.getPages().length;a++) {
ResearchPage page = ri.getPages()[a];
if (page.recipe!=null && page.recipe instanceof CrucibleRecipe[]) {
CrucibleRecipe[] crs = (CrucibleRecipe[]) page.recipe;
for (CrucibleRecipe cr:crs) {
if (cr.getRecipeOutput().isItemEqual(stack)) {
keyCache.put(key,new Object[] {ri.key,a});
if (ResearchHelper.isResearchComplete(player.getName(), ri.key))
return new Object[] {ri.key,a};
}
}
} else
if (page.recipe!=null && page.recipe instanceof InfusionRecipe[]) {
InfusionRecipe[] crs = (InfusionRecipe[]) page.recipe;
for (InfusionRecipe cr:crs) {
if (cr.getRecipeOutput() instanceof ItemStack && ((ItemStack) cr.getRecipeOutput()).isItemEqual(stack)) {
keyCache.put(key,new Object[] {ri.key,a});
if (ResearchHelper.isResearchComplete(player.getName(), ri.key))
return new Object[] {ri.key,a};
}
}
} else
if (page.recipe!=null && page.recipe instanceof IRecipe[]) {
IRecipe[] crs = (IRecipe[]) page.recipe;
for (IRecipe cr:crs) {
if ( cr.getRecipeOutput().isItemEqual(stack)) {
keyCache.put(key,new Object[] {ri.key,a});
if (ResearchHelper.isResearchComplete(player.getName(), ri.key))
return new Object[] {ri.key,a};
}
}
} else
if (page.recipeOutput!=null && stack !=null &&
(page.recipeOutput instanceof ItemStack &&
((ItemStack)page.recipeOutput).isItemEqual(stack)) ||
(page.recipeOutput instanceof String &&
ThaumcraftApiHelper.containsMatch(true,
new ItemStack[]{stack}, OreDictionary.getOres((String)page.recipeOutput))
)) {
keyCache.put(key,new Object[] {ri.key,a});
if (ResearchHelper.isResearchComplete(player.getName(), ri.key))
return new Object[] {ri.key,a};
else
return null;
}
}
}
}
keyCache.put(key,null);
return null;
}
//ASPECTS////////////////////////////////////////
public static ConcurrentHashMap<List,AspectList> objectTags = new ConcurrentHashMap<List,AspectList>();
public static ConcurrentHashMap<List,int[]> groupedObjectTags = new ConcurrentHashMap<List,int[]>();
/**
* Checks to see if the passed item/block already has aspects associated with it.
* @param id
* @param meta
* @return
*/
public static boolean exists(Item item, int meta) {
AspectList tmp = ThaumcraftApi.objectTags.get(Arrays.asList(item,meta));
if (tmp==null) {
tmp = ThaumcraftApi.objectTags.get(Arrays.asList(item,OreDictionary.WILDCARD_VALUE));
if (meta==OreDictionary.WILDCARD_VALUE && tmp==null) {
int index=0;
do {
tmp = ThaumcraftApi.objectTags.get(Arrays.asList(item,index));
index++;
} while (index<16 && tmp==null);
}
if (tmp==null) return false;
}
return true;
}
/**
* Used to assign apsects to the given item/block. Here is an example of the declaration for cobblestone:<p>
* <i>ThaumcraftApi.registerObjectTag(new ItemStack(Blocks.cobblestone), (new AspectList()).add(Aspect.ENTROPY, 1).add(Aspect.EARTH, 1));</i>
* @param item the item passed. Pass OreDictionary.WILDCARD_VALUE if all damage values of this item/block should have the same aspects
* @param aspects A ObjectTags object of the associated aspects
*/
public static void registerObjectTag(ItemStack item, AspectList aspects) {
if (aspects==null) aspects=new AspectList();
try {
objectTags.put(Arrays.asList(item.getItem(),item.getItemDamage()), aspects);
} catch (Exception e) {}
}
/**
* Used to assign apsects to the given item/block. Here is an example of the declaration for cobblestone:<p>
* <i>ThaumcraftApi.registerObjectTag(new ItemStack(Blocks.cobblestone), new int[]{0,1}, (new AspectList()).add(Aspect.ENTROPY, 1).add(Aspect.EARTH, 1));</i>
* @param item
* @param meta A range of meta values if you wish to lump several item meta's together as being the "same" item (i.e. stair orientations)
* @param aspects A ObjectTags object of the associated aspects
*/
public static void registerObjectTag(ItemStack item, int[] meta, AspectList aspects) {
if (aspects==null) aspects=new AspectList();
try {
objectTags.put(Arrays.asList(item.getItem(),meta[0]), aspects);
for (int m:meta) {
groupedObjectTags.put(Arrays.asList(item.getItem(),m), meta);
}
} catch (Exception e) {}
}
/**
* Used to assign apsects to the given ore dictionary item.
* @param oreDict the ore dictionary name
* @param aspects A ObjectTags object of the associated aspects
*/
public static void registerObjectTag(String oreDict, AspectList aspects) {
if (aspects==null) aspects=new AspectList();
List<ItemStack> ores = OreDictionary.getOres(oreDict);
if (ores!=null && ores.size()>0) {
for (ItemStack ore:ores) {
try {
objectTags.put(Arrays.asList(ore.getItem(), ore.getItemDamage()), aspects);
} catch (Exception e) {}
}
}
}
/**
* Used to assign aspects to the given item/block.
* Attempts to automatically generate aspect tags by checking registered recipes.
* Here is an example of the declaration for pistons:<p>
* <i>ThaumcraftApi.registerComplexObjectTag(new ItemStack(Blocks.piston), (new AspectList()).add(Aspect.MECHANISM, 2).add(Aspect.MOTION, 4));</i>
* IMPORTANT - this should only be used if you are not happy with the default aspects the object would be assigned.
* @param item, pass OreDictionary.WILDCARD_VALUE to meta if all damage values of this item/block should have the same aspects
* @param aspects A ObjectTags object of the associated aspects
*/
public static void registerComplexObjectTag(ItemStack item, AspectList aspects ) {
if (!exists(item.getItem(),item.getItemDamage())) {
AspectList tmp = AspectHelper.generateTags(item.getItem(), item.getItemDamage());
if (tmp != null && tmp.size()>0) {
for(Aspect tag:tmp.getAspects()) {
aspects.add(tag, tmp.getAmount(tag));
}
}
registerObjectTag(item,aspects);
} else {
AspectList tmp = AspectHelper.getObjectAspects(item);
for(Aspect tag:aspects.getAspects()) {
tmp.merge(tag, tmp.getAmount(tag));
}
registerObjectTag(item,tmp);
}
}
// WARP
private static HashMap<Object,Integer> warpMap = new HashMap<Object,Integer>();
/**
* This method is used to determine how much warp is gained if the item is crafted. The warp
* added is "sticky" warp
* @param craftresult The item crafted
* @param amount how much warp is gained
*/
public static void addWarpToItem(ItemStack craftresult, int amount) {
warpMap.put(Arrays.asList(craftresult.getItem(),craftresult.getItemDamage()),amount);
}
/**
* This method is used to determine how much permanent warp is gained if the research is completed
* @param in The item crafted
* @param amount how much warp is gained
*/
public static void addWarpToResearch(String research, int amount) {
warpMap.put(research, amount);
}
/**
* Returns how much warp is gained from the item or research passed in
* @param in itemstack or string
* @return how much warp it will give
*/
public static int getWarp(Object in) {
if (in==null) return 0;
if (in instanceof ItemStack && warpMap.containsKey(Arrays.asList(((ItemStack)in).getItem(),((ItemStack)in).getItemDamage()))) {
return warpMap.get(Arrays.asList(((ItemStack)in).getItem(),((ItemStack)in).getItemDamage()));
} else
if (in instanceof String && warpMap.containsKey((String)in)) {
return warpMap.get((String)in);
}
return 0;
}
// LOOT BAGS
/**
* Used to add possible loot to treasure bags. As a reference, the weight of gold coins are 2000
* and a diamond is 50.
* The weights are the same for all loot bag types - the only difference is how many items the bag
* contains.
* @param item
* @param weight
* @param bagTypes array of which type of bag to add this loot to. Multiple types can be specified
* 0 = common, 1 = uncommon, 2 = rare
*/
public static void addLootBagItem(ItemStack item, int weight, int... bagTypes) {
if (bagTypes==null || bagTypes.length==0)
WeightedRandomLoot.lootBagCommon.add(new WeightedRandomLoot(item,weight));
else {
for (int rarity:bagTypes) {
switch(rarity) {
case 0: WeightedRandomLoot.lootBagCommon.add(new WeightedRandomLoot(item,weight)); break;
case 1: WeightedRandomLoot.lootBagUncommon.add(new WeightedRandomLoot(item,weight)); break;
case 2: WeightedRandomLoot.lootBagRare.add(new WeightedRandomLoot(item,weight)); break;
}
}
}
}
// PORTABLE HOLE BLACKLIST
/**
* You can blacklist blocks that may not be portable holed through using the "portableHoleBlacklist"
* string message using FMLInterModComms in your @Mod.Init method.
*
* Simply add the mod and block name you don't want the portable hole to go through with a
* 'modid:blockname' designation. For example: "thaumcraft:log" or "minecraft:plank"
*
* You can also specify blockstates by adding ';' delimited 'name=value' pairs.
* For example: "thaumcraft:log;variant=greatwood;variant=silverwood"
*
* You can also give an ore dictionary entry instead: For example: "logWood"
*/
// CROPS
/**
* To define mod crops you need to use FMLInterModComms in your @Mod.Init method.
* There are two 'types' of crops you can add. Standard crops and clickable crops.
*
* Standard crops work like normal vanilla crops - they grow until a certain metadata
* value is reached and you harvest them by destroying the block and collecting the blocks.
* You need to create and ItemStack that tells the golem what block id and metadata represents
* the crop when fully grown. Sending a metadata of [OreDictionary.WILDCARD_VALUE] will mean the metadata won't get
* checked.
* Example for vanilla wheat:
* FMLInterModComms.sendMessage("Thaumcraft", "harvestStandardCrop", new ItemStack(Block.crops,1,7));
*
* Clickable crops are crops that you right click to gather their bounty instead of destroying them.
* As for standard crops, you need to create and ItemStack that tells the golem what block id
* and metadata represents the crop when fully grown. The golem will trigger the blocks onBlockActivated method.
* Sending a metadata of [OreDictionary.WILDCARD_VALUE] will mean the metadata won't get checked.
* Example (this will technically do nothing since clicking wheat does nothing, but you get the idea):
* FMLInterModComms.sendMessage("Thaumcraft", "harvestClickableCrop", new ItemStack(Block.crops,1,7));
*
* Stacked crops (like reeds) are crops that you wish the bottom block should remain after harvesting.
* As for standard crops, you need to create and ItemStack that tells the golem what block id
* and metadata represents the crop when fully grown. Sending a metadata of [OreDictionary.WILDCARD_VALUE] will mean the actualy md won't get
* checked. If it has the order upgrade it will only harvest if the crop is more than one block high.
* Example:
* FMLInterModComms.sendMessage("Thaumcraft", "harvestStackedCrop", new ItemStack(Block.reed,1,7));
*/
// NATIVE CLUSTERS
/**
* You can define certain ores that will have a chance to produce native clusters via FMLInterModComms
* in your @Mod.Init method using the "nativeCluster" string message.
* The format should be:
* "[ore item/block id],[ore item/block metadata],[cluster item/block id],[cluster item/block metadata],[chance modifier float]"
*
* NOTE: The chance modifier is a multiplier applied to the default chance for that cluster to be produced (default 27.5% for a pickaxe of the core)
*
* Example for vanilla iron ore to produce one of my own native iron clusters (assuming default id's) at double the default chance:
* FMLInterModComms.sendMessage("Thaumcraft", "nativeCluster","15,0,25016,16,2.0");
*/
// LAMP OF GROWTH BLACKLIST
/**
* You can blacklist crops that should not be effected by the Lamp of Growth via FMLInterModComms
* in your @Mod.Init method using the "lampBlacklist" itemstack message.
* Sending a metadata of [OreDictionary.WILDCARD_VALUE] will mean the metadata won't get checked.
* Example for vanilla wheat:
* FMLInterModComms.sendMessage("Thaumcraft", "lampBlacklist", new ItemStack(Block.crops,1,OreDictionary.WILDCARD_VALUE));
*/
// DIMENSION BLACKLIST
/**
* You can blacklist a dimension to not spawn certain thaumcraft features
* in your @Mod.Init method using the "dimensionBlacklist" string message in the format "[dimension]:[level]"
* The level values are as follows:
* [0] stop all tc spawning and generation
* [1] allow ore and node generation (and node special features)
* [2] allow mob spawning
* [3] allow ore and node gen + mob spawning (and node special features)
* Example:
* FMLInterModComms.sendMessage("Thaumcraft", "dimensionBlacklist", "15:1");
*/
// BIOME BLACKLIST
/**
* You can blacklist a biome to not spawn certain thaumcraft features
* in your @Mod.Init method using the "biomeBlacklist" string message in the format "[biome id]:[level]"
* The level values are as follows:
* [0] stop all tc spawning and generation
* [1] allow ore and node generation (and node special features)
* [2] allow mob spawning
* [3] allow ore and node gen + mob spawning (and node special features)
* Example:
* FMLInterModComms.sendMessage("Thaumcraft", "biomeBlacklist", "180:2");
*/
// CHAMPION MOB WHITELIST
/**
* You can whitelist an entity class so it can rarely spawn champion versions in your @Mod.Init method using
* the "championWhiteList" string message in the format "[Entity]:[level]"
* The entity must extend EntityMob.
* [Entity] is in a similar format to what is used for mob spawners and such (see EntityList.class for vanilla examples).
* The [level] value indicate how rare the champion version will be - the higher the number the more common.
* The number roughly equals the [n] in 100 chance of a mob being a champion version.
* You can give 0 or negative numbers to allow champions to spawn with a very low chance only in particularly dangerous places.
* However anything less than about -2 will probably result in no spawns at all.
* Example:
* FMLInterModComms.sendMessage("Thaumcraft", "championWhiteList", "Thaumcraft.Wisp:1");
*/
}

View file

@ -0,0 +1,329 @@
package thaumcraft.api;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.aspects.IEssentiaTransport;
public class ThaumcraftApiHelper {
public static boolean areItemsEqual(ItemStack s1,ItemStack s2)
{
if (s1.isItemStackDamageable() && s2.isItemStackDamageable())
{
return s1.getItem() == s2.getItem();
} else
return s1.getItem() == s2.getItem() && s1.getItemDamage() == s2.getItemDamage();
}
/**
* Notifies thaumcraft that something with regards to runic shielding has changed and that it should
* rescan worn items to determine what the max shielding value is.
* It automatically rescans once every 5 seconds, but this makes it happen sooner.
* @param entity
*/
public static void markRunicDirty(Entity entity) {
ThaumcraftApi.internalMethods.markRunicDirty(entity);
}
public static boolean containsMatch(boolean strict, ItemStack[] inputs, List<ItemStack> targets)
{
for (ItemStack input : inputs)
{
for (ItemStack target : targets)
{
if (OreDictionary.itemMatches(target, input, strict))
{
return true;
}
}
}
return false;
}
public static boolean areItemStacksEqualForCrafting(ItemStack stack0, Object in)
{
if (stack0==null && in!=null) return false;
if (stack0!=null && in==null) return false;
if (stack0==null && in==null) return true;
if (in instanceof String) {
List<ItemStack> l = OreDictionary.getOres((String) in);
return containsMatch(false, new ItemStack[]{stack0}, l);
}
if (in instanceof ItemStack) {
//nbt
boolean t1=areItemStackTagsEqualForCrafting(stack0, (ItemStack) in);
if (!t1) return false;
return OreDictionary.itemMatches((ItemStack) in, stack0, false);
}
return false;
}
public static boolean areItemStackTagsEqualForCrafting(ItemStack slotItem,ItemStack recipeItem)
{
if (recipeItem == null || slotItem == null) return false;
if (recipeItem.getTagCompound()!=null && slotItem.getTagCompound()==null ) return false;
if (recipeItem.getTagCompound()==null ) return true;
Iterator iterator = recipeItem.getTagCompound().getKeySet().iterator();
while (iterator.hasNext())
{
String s = (String)iterator.next();
if (slotItem.getTagCompound().hasKey(s)) {
if (!slotItem.getTagCompound().getTag(s).toString().equals(
recipeItem.getTagCompound().getTag(s).toString())) {
return false;
}
} else {
return false;
}
}
return true;
}
public static TileEntity getConnectableTile(World world, BlockPos pos, EnumFacing face) {
TileEntity te = world.getTileEntity(pos.offset(face));
if (te instanceof IEssentiaTransport && ((IEssentiaTransport)te).isConnectable(face.getOpposite()))
return te;
else
return null;
}
public static TileEntity getConnectableTile(IBlockAccess world, BlockPos pos, EnumFacing face) {
TileEntity te = world.getTileEntity(pos.offset(face));
if (te instanceof IEssentiaTransport && ((IEssentiaTransport)te).isConnectable(face.getOpposite()))
return te;
else
return null;
}
// private static HashMap<Integer, AspectList> allAspects= new HashMap<Integer, AspectList>();
// private static HashMap<Integer, AspectList> allCompoundAspects= new HashMap<Integer, AspectList>();
//
// public static AspectList getAllAspects(int amount) {
// if (allAspects.get(amount)==null) {
// AspectList al = new AspectList();
// for (Aspect aspect:Aspect.aspects.values()) {
// al.add(aspect, amount);
// }
// allAspects.put(amount, al);
// }
// return allAspects.get(amount);
// }
//
// public static AspectList getAllCompoundAspects(int amount) {
// if (allCompoundAspects.get(amount)==null) {
// AspectList al = new AspectList();
// for (Aspect aspect:Aspect.getCompoundAspects()) {
// al.add(aspect, amount);
// }
// allCompoundAspects.put(amount, al);
// }
// return allCompoundAspects.get(amount);
// }
public static MovingObjectPosition rayTraceIgnoringSource(World world, Vec3 v1, Vec3 v2,
boolean bool1, boolean bool2, boolean bool3)
{
if (!Double.isNaN(v1.xCoord) && !Double.isNaN(v1.yCoord) && !Double.isNaN(v1.zCoord))
{
if (!Double.isNaN(v2.xCoord) && !Double.isNaN(v2.yCoord) && !Double.isNaN(v2.zCoord))
{
int i = MathHelper.floor_double(v2.xCoord);
int j = MathHelper.floor_double(v2.yCoord);
int k = MathHelper.floor_double(v2.zCoord);
int l = MathHelper.floor_double(v1.xCoord);
int i1 = MathHelper.floor_double(v1.yCoord);
int j1 = MathHelper.floor_double(v1.zCoord);
IBlockState block = world.getBlockState(new BlockPos(l, i1, j1));
MovingObjectPosition movingobjectposition2 = null;
int k1 = 200;
while (k1-- >= 0)
{
if (Double.isNaN(v1.xCoord) || Double.isNaN(v1.yCoord) || Double.isNaN(v1.zCoord))
{
return null;
}
if (l == i && i1 == j && j1 == k)
{
continue;
}
boolean flag6 = true;
boolean flag3 = true;
boolean flag4 = true;
double d0 = 999.0D;
double d1 = 999.0D;
double d2 = 999.0D;
if (i > l)
{
d0 = (double)l + 1.0D;
}
else if (i < l)
{
d0 = (double)l + 0.0D;
}
else
{
flag6 = false;
}
if (j > i1)
{
d1 = (double)i1 + 1.0D;
}
else if (j < i1)
{
d1 = (double)i1 + 0.0D;
}
else
{
flag3 = false;
}
if (k > j1)
{
d2 = (double)j1 + 1.0D;
}
else if (k < j1)
{
d2 = (double)j1 + 0.0D;
}
else
{
flag4 = false;
}
double d3 = 999.0D;
double d4 = 999.0D;
double d5 = 999.0D;
double d6 = v2.xCoord - v1.xCoord;
double d7 = v2.yCoord - v1.yCoord;
double d8 = v2.zCoord - v1.zCoord;
if (flag6)
{
d3 = (d0 - v1.xCoord) / d6;
}
if (flag3)
{
d4 = (d1 - v1.yCoord) / d7;
}
if (flag4)
{
d5 = (d2 - v1.zCoord) / d8;
}
if (d3 == -0.0D)
{
d3 = -1.0E-4D;
}
if (d4 == -0.0D)
{
d4 = -1.0E-4D;
}
if (d5 == -0.0D)
{
d5 = -1.0E-4D;
}
EnumFacing enumfacing;
if (d3 < d4 && d3 < d5)
{
enumfacing = i > l ? EnumFacing.WEST : EnumFacing.EAST;
v1 = new Vec3(d0, v1.yCoord + d7 * d3, v1.zCoord + d8 * d3);
}
else if (d4 < d5)
{
enumfacing = j > i1 ? EnumFacing.DOWN : EnumFacing.UP;
v1 = new Vec3(v1.xCoord + d6 * d4, d1, v1.zCoord + d8 * d4);
}
else
{
enumfacing = k > j1 ? EnumFacing.NORTH : EnumFacing.SOUTH;
v1 = new Vec3(v1.xCoord + d6 * d5, v1.yCoord + d7 * d5, d2);
}
l = MathHelper.floor_double(v1.xCoord) - (enumfacing == EnumFacing.EAST ? 1 : 0);
i1 = MathHelper.floor_double(v1.yCoord) - (enumfacing == EnumFacing.UP ? 1 : 0);
j1 = MathHelper.floor_double(v1.zCoord) - (enumfacing == EnumFacing.SOUTH ? 1 : 0);
IBlockState block1 = world.getBlockState(new BlockPos(l, i1, j1));
if (!bool2 || block1.getBlock().getCollisionBoundingBox(world, new BlockPos(l, i1, j1), block1) != null)
{
if (block1.getBlock().canCollideCheck(block1, bool1))
{
MovingObjectPosition movingobjectposition1 = block1.getBlock().collisionRayTrace(world, new BlockPos(l, i1, j1), v1, v2);
if (movingobjectposition1 != null)
{
return movingobjectposition1;
}
}
else
{
movingobjectposition2 = new MovingObjectPosition(MovingObjectPosition.MovingObjectType.MISS, v1, enumfacing, new BlockPos(l, i1, j1));
}
}
}
return bool3 ? movingobjectposition2 : null;
}
else
{
return null;
}
}
else
{
return null;
}
}
public static Object getNBTDataFromId(NBTTagCompound nbt, byte id, String key) {
switch (id) {
case 1: return nbt.getByte(key);
case 2: return nbt.getShort(key);
case 3: return nbt.getInteger(key);
case 4: return nbt.getLong(key);
case 5: return nbt.getFloat(key);
case 6: return nbt.getDouble(key);
case 7: return nbt.getByteArray(key);
case 8: return nbt.getString(key);
case 9: return nbt.getTagList(key, (byte) 10);
case 10: return nbt.getTag(key);
case 11: return nbt.getIntArray(key);
default: return null;
}
}
}

View file

@ -0,0 +1,9 @@
package thaumcraft.api;
public class ThaumcraftEnchantments {
//Enchantment references
public static int HASTE;
public static int REPAIR;
}

View file

@ -0,0 +1,52 @@
package thaumcraft.api;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraftforge.common.util.EnumHelper;
public class ThaumcraftMaterials {
public static ToolMaterial TOOLMAT_THAUMIUM = EnumHelper.addToolMaterial("THAUMIUM", 3, 500, 7F, 2.5f, 22);
public static ToolMaterial TOOLMAT_VOID = EnumHelper.addToolMaterial("VOID", 4, 150, 8F, 3, 10);
public static ToolMaterial TOOLMAT_ELEMENTAL = EnumHelper.addToolMaterial("THAUMIUM_ELEMENTAL", 3, 1500, 9F, 3, 18);
public static ArmorMaterial ARMORMAT_THAUMIUM = EnumHelper.addArmorMaterial("THAUMIUM","THAUMIUM", 25, new int[] { 2, 6, 5, 2 }, 25);
public static ArmorMaterial ARMORMAT_SPECIAL = EnumHelper.addArmorMaterial("SPECIAL","SPECIAL", 25, new int[] { 1, 3, 2, 1 }, 25);
public static ArmorMaterial ARMORMAT_VOID = EnumHelper.addArmorMaterial("VOID","VOID", 10, new int[] { 3, 7, 6, 3 }, 10);
public static final Material MATERIAL_TAINT = new MaterialTaint();
public static class MaterialTaint extends Material
{
public MaterialTaint()
{
super(MapColor.purpleColor);
setNoPushMobility();
}
@Override
public boolean blocksMovement()
{
return true;
}
@Override
protected Material setNoPushMobility()
{
this.mobilityFlag = 1;
return this;
}
private int mobilityFlag;
@Override
public int getMaterialMobility()
{
return this.mobilityFlag;
}
}
}

View file

@ -0,0 +1,206 @@
package thaumcraft.api.aspects;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import org.apache.commons.lang3.text.WordUtils;
import thaumcraft.api.research.ScanAspect;
import thaumcraft.api.research.ScanningManager;
public class Aspect {
String tag;
Aspect[] components;
int color;
private String chatcolor;
ResourceLocation image;
int blend;
/**
* For easy reference of what compounds are made up of
*/
public static HashMap<Integer,Aspect> mixList = new HashMap<Integer,Aspect>();
/**
* Use this constructor to register your own aspects.
* @param tag the key that will be used to reference this aspect, as well as its latin display name
* @param color color to display the tag in
* @param components the aspects this one is formed from
* @param image ResourceLocation pointing to a 32x32 icon of the aspect
* @param blend GL11 blendmode (1 or 771). Used for rendering nodes. Default is 1
*/
public Aspect(String tag, int color, Aspect[] components, ResourceLocation image, int blend) {
if (aspects.containsKey(tag)) throw new IllegalArgumentException(tag+" already registered!");
this.tag = tag;
this.components = components;
this.color = color;
this.image = image;
this.blend = blend;
aspects.put(tag, this);
ScanningManager.addScannableThing(new ScanAspect("!"+tag,this));
if (components!=null) {
int h = (components[0].getTag()+components[1].getTag()).hashCode();
mixList.put(h, this);
}
}
/**
* Shortcut constructor I use for the default aspects - you shouldn't be using this.
*/
public Aspect(String tag, int color, Aspect[] components) {
this(tag,color,components,new ResourceLocation("thaumcraft","textures/aspects/"+tag.toLowerCase()+".png"),1);
}
/**
* Shortcut constructor I use for the default aspects - you shouldn't be using this.
*/
public Aspect(String tag, int color, Aspect[] components, int blend) {
this(tag,color,components,new ResourceLocation("thaumcraft","textures/aspects/"+tag.toLowerCase()+".png"),blend);
}
/**
* Shortcut constructor I use for the primal aspects -
* you shouldn't use this as making your own primal aspects will break all the things.
*/
public Aspect(String tag, int color, String chatcolor, int blend) {
this(tag,color,(Aspect[])null, blend);
this.setChatcolor(chatcolor);
}
public int getColor() {
return color;
}
public String getName() {
return WordUtils.capitalizeFully(tag);
}
public String getLocalizedDescription() {
return StatCollector.translateToLocal("tc.aspect."+tag);
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public Aspect[] getComponents() {
return components;
}
public void setComponents(Aspect[] components) {
this.components = components;
}
public ResourceLocation getImage() {
return image;
}
public static Aspect getAspect(String tag) {
return aspects.get(tag);
}
public int getBlend() {
return blend;
}
public void setBlend(int blend) {
this.blend = blend;
}
public boolean isPrimal() {
return getComponents()==null || getComponents().length!=2;
}
///////////////////////////////
public static ArrayList<Aspect> getPrimalAspects() {
ArrayList<Aspect> primals = new ArrayList<Aspect>();
Collection<Aspect> pa = aspects.values();
for (Aspect aspect:pa) {
if (aspect.isPrimal()) primals.add(aspect);
}
return primals;
}
public static ArrayList<Aspect> getCompoundAspects() {
ArrayList<Aspect> compounds = new ArrayList<Aspect>();
Collection<Aspect> pa = aspects.values();
for (Aspect aspect:pa) {
if (!aspect.isPrimal()) compounds.add(aspect);
}
return compounds;
}
public String getChatcolor() {
return chatcolor;
}
public void setChatcolor(String chatcolor) {
this.chatcolor = chatcolor;
}
///////////////////////////////
public static LinkedHashMap<String,Aspect> aspects = new LinkedHashMap<String,Aspect>();
//PRIMAL
public static final Aspect AIR = new Aspect("aer",0xffff7e,"e",1);
public static final Aspect EARTH = new Aspect("terra",0x56c000,"2",1);
public static final Aspect FIRE = new Aspect("ignis",0xff5a01,"c",1);
public static final Aspect WATER = new Aspect("aqua",0x3cd4fc,"3",1);
public static final Aspect ORDER = new Aspect("ordo",0xd5d4ec,"7",1);
public static final Aspect ENTROPY = new Aspect("perditio",0x404040,"8",771);
//SECONDARY (PRIMAL + PRIMAL)
public static final Aspect VOID = new Aspect("vacuos",0x888888, new Aspect[] {AIR, ENTROPY},771);
public static final Aspect LIGHT = new Aspect("lux",0xfff663, new Aspect[] {AIR, FIRE});
public static final Aspect MOTION = new Aspect("motus",0xcdccf4, new Aspect[] {AIR, ORDER});
public static final Aspect COLD = new Aspect("gelum",0xe1ffff, new Aspect[] {FIRE, ENTROPY});
public static final Aspect CRYSTAL = new Aspect("vitreus",0x80ffff, new Aspect[] {EARTH, AIR});
public static final Aspect METAL = new Aspect("metallum",0xb5b5cd, new Aspect[] {EARTH, ORDER});
public static final Aspect LIFE = new Aspect("victus",0xde0005, new Aspect[] {EARTH, WATER});
public static final Aspect DEATH = new Aspect("mortuus",0x887788, new Aspect[] {WATER, ENTROPY});
public static final Aspect ENERGY = new Aspect("potentia",0xc0ffff, new Aspect[] {ORDER, FIRE});
public static final Aspect EXCHANGE = new Aspect("permutatio",0x578357, new Aspect[] {ENTROPY, ORDER});
// public static final Aspect WEATHER = new Aspect("tempestas",0xFFFFFF, new Aspect[] {AIR, WATER});
// public static final Aspect ?? = new Aspect("??",0xcdccf4, new Aspect[] {FIRE, EARTH});
// public static final Aspect ?? = new Aspect("??",0xcdccf4, new Aspect[] {FIRE, WATER});
// public static final Aspect ?? = new Aspect("??",0xcdccf4, new Aspect[] {ORDER, WATER});
// public static final Aspect ?? = new Aspect("??",0xcdccf4, new Aspect[] {EARTH, ENTROPY});
//TERTIARY
public static final Aspect AURA = new Aspect("auram",0xffc0ff, new Aspect[] {ENERGY, AIR});
public static final Aspect FLUX = new Aspect("vitium",0x800080, new Aspect[] {ENTROPY, ENERGY});
public static final Aspect DARKNESS = new Aspect("tenebrae",0x222222, new Aspect[] {VOID, LIGHT});
public static final Aspect ELDRITCH = new Aspect("alienis",0x805080, new Aspect[] {VOID, DARKNESS});
public static final Aspect FLIGHT = new Aspect("volatus",0xe7e7d7, new Aspect[] {AIR, MOTION});
public static final Aspect PLANT = new Aspect("herba",0x01ac00, new Aspect[] {LIFE, EARTH});
public static final Aspect TOOL = new Aspect("instrumentum",0x4040ee, new Aspect[] {METAL, ENERGY});
public static final Aspect CRAFT = new Aspect("fabrico",0x809d80, new Aspect[] {EXCHANGE, TOOL});
public static final Aspect MECHANISM = new Aspect("machina",0x8080a0, new Aspect[] {MOTION, TOOL});
public static final Aspect TRAP = new Aspect("vinculum",0x9a8080, new Aspect[] {MOTION, ENTROPY});
public static final Aspect SOUL = new Aspect("spiritus",0xebebfb, new Aspect[] {LIFE, DEATH});
public static final Aspect MIND = new Aspect("cognitio",0xffc2b3, new Aspect[] {FIRE, SOUL});
public static final Aspect SENSES = new Aspect("sensus",0x0fd9ff, new Aspect[] {AIR, SOUL});
public static final Aspect AVERSION = new Aspect("aversio",0xc05050, new Aspect[] {SOUL, ENTROPY});
public static final Aspect PROTECT = new Aspect("praemunio",0x00c0c0, new Aspect[] {SOUL, EARTH});
public static final Aspect DESIRE = new Aspect("desiderium",0xe6be44, new Aspect[] {SOUL, VOID});
public static final Aspect UNDEAD = new Aspect("exanimis",0x3a4000, new Aspect[] {MOTION, DEATH});
public static final Aspect BEAST = new Aspect("bestia",0x9f6409, new Aspect[] {MOTION, LIFE});
public static final Aspect MAN = new Aspect("humanus",0xffd7c0, new Aspect[] {SOUL, LIFE});
}

View file

@ -0,0 +1,178 @@
package thaumcraft.api.aspects;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.ThaumcraftApi.EntityTagsNBT;
import thaumcraft.api.ThaumcraftApiHelper;
public class AspectHelper {
public static AspectList cullTags(AspectList temp) {
AspectList temp2 = new AspectList();
for (Aspect tag:temp.getAspects()) {
if (tag!=null)
temp2.add(tag, temp.getAmount(tag));
}
while (temp2!=null && temp2.size()>6) {
Aspect lowest = null;
float low = Short.MAX_VALUE;
for (Aspect tag:temp2.getAspects()) {
if (tag==null) continue;
float ta=temp2.getAmount(tag);
if (tag.isPrimal()) {
ta *= .9f;
} else {
if (!tag.getComponents()[0].isPrimal()) {
ta *= 1.1f;
if (!tag.getComponents()[0].getComponents()[0].isPrimal()) {
ta *= 1.05f;
}
if (!tag.getComponents()[0].getComponents()[1].isPrimal()) {
ta *= 1.05f;
}
}
if (!tag.getComponents()[1].isPrimal()) {
ta *= 1.1f;
if (!tag.getComponents()[1].getComponents()[0].isPrimal()) {
ta *= 1.05f;
}
if (!tag.getComponents()[1].getComponents()[1].isPrimal()) {
ta *= 1.05f;
}
}
}
if (ta<low) {
low = ta;
lowest = tag;
}
}
temp2.aspects.remove(lowest);
}
return temp2;
}
public static AspectList getObjectAspects(ItemStack is) {
return ThaumcraftApi.internalMethods.getObjectAspects(is);
}
public static AspectList generateTags(Item item, int meta) {
return ThaumcraftApi.internalMethods.generateTags(item, meta);
}
public static AspectList getEntityAspects(Entity entity) {
AspectList tags = null;
if (entity instanceof EntityPlayer) {
tags = new AspectList();
tags.add(Aspect.MAN, 4);
Random rand = new Random(((EntityPlayer)entity).getName().hashCode());
Aspect[] posa = Aspect.aspects.values().toArray(new Aspect[]{});
tags.add(posa[rand.nextInt(posa.length)], 4);
tags.add(posa[rand.nextInt(posa.length)], 4);
tags.add(posa[rand.nextInt(posa.length)], 4);
} else {
f1:
for (ThaumcraftApi.EntityTags et:ThaumcraftApi.scanEntities) {
if (!et.entityName.equals(EntityList.getEntityString(entity))) continue;
if (et.nbts==null || et.nbts.length==0) {
tags = et.aspects;
} else {
NBTTagCompound tc = new NBTTagCompound();
entity.writeToNBT(tc);
for (EntityTagsNBT nbt:et.nbts) {
if (tc.hasKey(nbt.name)) {
if (!ThaumcraftApiHelper.getNBTDataFromId(tc, tc.getTagId(nbt.name), nbt.name).equals(nbt.value)) continue f1;
} else {
continue f1;
}
}
tags = et.aspects;
}
}
}
return tags;
}
public static Aspect getCombinationResult(Aspect aspect1, Aspect aspect2) {
Collection<Aspect> aspects = Aspect.aspects.values();
for (Aspect aspect:aspects) {
if (aspect.getComponents()!=null && (
(aspect.getComponents()[0]==aspect1 && aspect.getComponents()[1]==aspect2) ||
(aspect.getComponents()[0]==aspect2 && aspect.getComponents()[1]==aspect1))) {
return aspect;
}
}
return null;
}
public static Aspect getRandomPrimal(Random rand, Aspect aspect) {
ArrayList<Aspect> list = new ArrayList<Aspect>();
if (aspect!=null) {
AspectList temp = new AspectList();
temp.add(aspect, 1);
AspectList temp2 = AspectHelper.reduceToPrimals(temp);
for (Aspect a:temp2.getAspects()) {
for (int b=0;b<temp2.getAmount(a);b++) {
list.add(a);
}
}
}
return list.size()>0?list.get(rand.nextInt(list.size())):null;
}
public static AspectList reduceToPrimals(AspectList in) {
AspectList out = new AspectList();
for (Aspect aspect:in.getAspects()) {
if (aspect!=null) {
if (aspect.isPrimal()) {
out.add(aspect, in.getAmount(aspect));
} else {
AspectList temp = new AspectList();
temp.add(aspect.getComponents()[0],in.getAmount(aspect));
temp.add(aspect.getComponents()[1],in.getAmount(aspect));
AspectList temp2 = reduceToPrimals(temp);
for (Aspect a:temp2.getAspects()) {
out.add(a, temp2.getAmount(a));
}
}
}
}
return out;
}
public static AspectList getPrimalAspects(AspectList in) {
AspectList t = new AspectList();
t.add(Aspect.AIR, in.getAmount(Aspect.AIR));
t.add(Aspect.FIRE, in.getAmount(Aspect.FIRE));
t.add(Aspect.WATER, in.getAmount(Aspect.WATER));
t.add(Aspect.EARTH, in.getAmount(Aspect.EARTH));
t.add(Aspect.ORDER, in.getAmount(Aspect.ORDER));
t.add(Aspect.ENTROPY, in.getAmount(Aspect.ENTROPY));
return t;
}
public static AspectList getAuraAspects(AspectList in) {
AspectList t = new AspectList();
t.add(Aspect.AIR, in.getAmount(Aspect.AIR));
t.add(Aspect.FIRE, in.getAmount(Aspect.FIRE));
t.add(Aspect.WATER, in.getAmount(Aspect.WATER));
t.add(Aspect.EARTH, in.getAmount(Aspect.EARTH));
t.add(Aspect.ORDER, in.getAmount(Aspect.ORDER));
t.add(Aspect.ENTROPY, in.getAmount(Aspect.ENTROPY));
t.add(Aspect.FLUX, in.getAmount(Aspect.FLUX));
return t;
}
}

View file

@ -0,0 +1,278 @@
package thaumcraft.api.aspects;
import java.io.Serializable;
import java.util.LinkedHashMap;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
public class AspectList implements Serializable {
public LinkedHashMap<Aspect,Integer> aspects = new LinkedHashMap<Aspect,Integer>();//aspects associated with this object
/**
* this creates a new aspect list with preloaded values based off the aspects of the given item.
* @param the itemstack of the given item
*/
public AspectList(ItemStack stack) {
try {
AspectList temp = AspectHelper.getObjectAspects(stack);
if (temp!=null)
for (Aspect tag:temp.getAspects()) {
add(tag,temp.getAmount(tag));
}
} catch (Exception e) {}
}
public AspectList() {
}
public AspectList copy() {
AspectList out = new AspectList();
for (Aspect a:this.getAspects())
out.add(a, this.getAmount(a));
return out;
}
/**
* @return the amount of different aspects in this collection
*/
public int size() {
return aspects.size();
}
/**
* @return the amount of total vis in this collection
*/
public int visSize() {
int q = 0;
for (Aspect as:aspects.keySet()) {
q+=this.getAmount(as);
}
return q;
}
/**
* @return an array of all the aspects in this collection
*/
public Aspect[] getAspects() {
Aspect[] q = new Aspect[1];
return aspects.keySet().toArray(q);
}
/**
* @return an array of all the aspects in this collection sorted by name
*/
public Aspect[] getAspectsSortedByName() {
try {
Aspect[] out = aspects.keySet().toArray(new Aspect[]{});
boolean change=false;
do {
change=false;
for(int a=0;a<out.length-1;a++) {
Aspect e1 = out[a];
Aspect e2 = out[a+1];
if (e1!=null && e2!=null && e1.getTag().compareTo(e2.getTag())>0) {
out[a] = e2;
out[a+1] = e1;
change = true;
break;
}
}
} while (change==true);
return out;
} catch (Exception e) {
return this.getAspects();
}
}
/**
* @return an array of all the aspects in this collection sorted by amount
*/
public Aspect[] getAspectsSortedByAmount() {
try {
Aspect[] out = aspects.keySet().toArray(new Aspect[1]);
boolean change=false;
do {
change=false;
for(int a=0;a<out.length-1;a++) {
int e1 = getAmount(out[a]);
int e2 = getAmount(out[a+1]);
if (e1>0 && e2>0 && e2>e1) {
Aspect ea = out[a];
Aspect eb = out[a+1];
out[a] = eb;
out[a+1] = ea;
change = true;
break;
}
}
} while (change==true);
return out;
} catch (Exception e) {
return this.getAspects();
}
}
/**
* @param key
* @return the amount associated with the given aspect in this collection
*/
public int getAmount(Aspect key) {
return aspects.get(key)==null?0:aspects.get(key);
}
/**
* Reduces the amount of an aspect in this collection by the given amount.
* @param key
* @param amount
* @return
*/
public boolean reduce(Aspect key, int amount) {
if (getAmount(key)>=amount) {
int am = getAmount(key)-amount;
aspects.put(key, am);
return true;
}
return false;
}
/**
* Reduces the amount of an aspect in this collection by the given amount.
* If reduced to 0 or less the aspect will be removed completely.
* @param key
* @param amount
* @return
*/
public AspectList remove(Aspect key, int amount) {
int am = getAmount(key)-amount;
if (am<=0) aspects.remove(key); else
this.aspects.put(key, am);
return this;
}
/**
* Simply removes the aspect from the list
* @param key
* @param amount
* @return
*/
public AspectList remove(Aspect key) {
aspects.remove(key);
return this;
}
/**
* Adds this aspect and amount to the collection.
* If the aspect exists then its value will be increased by the given amount.
* @param aspect
* @param amount
* @return
*/
public AspectList add(Aspect aspect, int amount) {
if (this.aspects.containsKey(aspect)) {
int oldamount = this.aspects.get(aspect);
amount+=oldamount;
}
this.aspects.put( aspect, amount );
return this;
}
/**
* Adds this aspect and amount to the collection.
* If the aspect exists then only the highest of the old or new amount will be used.
* @param aspect
* @param amount
* @return
*/
public AspectList merge(Aspect aspect, int amount) {
if (this.aspects.containsKey(aspect)) {
int oldamount = this.aspects.get(aspect);
if (amount<oldamount) amount=oldamount;
}
this.aspects.put( aspect, amount );
return this;
}
public AspectList add(AspectList in) {
for (Aspect a:in.getAspects())
this.add(a, in.getAmount(a));
return this;
}
public AspectList merge(AspectList in) {
for (Aspect a:in.getAspects())
this.merge(a, in.getAmount(a));
return this;
}
/**
* Reads the list of aspects from nbt
* @param nbttagcompound
* @return
*/
public void readFromNBT(NBTTagCompound nbttagcompound)
{
aspects.clear();
NBTTagList tlist = nbttagcompound.getTagList("Aspects",(byte)10);
for (int j = 0; j < tlist.tagCount(); j++) {
NBTTagCompound rs = (NBTTagCompound) tlist.getCompoundTagAt(j);
if (rs.hasKey("key")) {
add( Aspect.getAspect(rs.getString("key")),
rs.getInteger("amount"));
}
}
}
public void readFromNBT(NBTTagCompound nbttagcompound, String label)
{
aspects.clear();
NBTTagList tlist = nbttagcompound.getTagList(label,(byte)10);
for (int j = 0; j < tlist.tagCount(); j++) {
NBTTagCompound rs = (NBTTagCompound) tlist.getCompoundTagAt(j);
if (rs.hasKey("key")) {
add( Aspect.getAspect(rs.getString("key")),
rs.getInteger("amount"));
}
}
}
/**
* Writes the list of aspects to nbt
* @param nbttagcompound
* @return
*/
public void writeToNBT(NBTTagCompound nbttagcompound)
{
NBTTagList tlist = new NBTTagList();
nbttagcompound.setTag("Aspects", tlist);
for (Aspect aspect : getAspects())
if (aspect != null) {
NBTTagCompound f = new NBTTagCompound();
f.setString("key", aspect.getTag());
f.setInteger("amount", getAmount(aspect));
tlist.appendTag(f);
}
}
public void writeToNBT(NBTTagCompound nbttagcompound, String label)
{
NBTTagList tlist = new NBTTagList();
nbttagcompound.setTag(label, tlist);
for (Aspect aspect : getAspects())
if (aspect != null) {
NBTTagCompound f = new NBTTagCompound();
f.setString("key", aspect.getTag());
f.setInteger("amount", getAmount(aspect));
tlist.appendTag(f);
}
}
}

View file

@ -0,0 +1,58 @@
package thaumcraft.api.aspects;
import java.lang.reflect.Method;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fml.common.FMLLog;
public class AspectSourceHelper {
static Method drainEssentia;
static Method findEssentia;
/**
* This method is what is used to drain essentia from jars and other sources for things like
* infusion crafting or powering the arcane furnace. A record of possible sources are kept track of
* and refreshed as needed around the calling tile entity. This also renders the essentia trail particles.
* Only 1 essentia is drained at a time
* @param tile the tile entity that is draining the essentia
* @param aspect the aspect that you are looking for
* @param direction the direction from which you wish to drain. EnumFacing.Unknown simply seeks in all directions.
* @param range how many blocks you wish to search for essentia sources.
* @return boolean returns true if essentia was found and removed from a source.
*/
public static boolean drainEssentia(TileEntity tile, Aspect aspect, EnumFacing direction, int range) {
try {
if(drainEssentia == null) {
Class fake = Class.forName("thaumcraft.common.lib.events.EssentiaHandler");
drainEssentia = fake.getMethod("drainEssentia", TileEntity.class, Aspect.class, EnumFacing.class, int.class);
}
return (Boolean) drainEssentia.invoke(null, tile, aspect, direction, range);
} catch(Exception ex) {
FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.lib.events.EssentiaHandler method drainEssentia");
}
return false;
}
/**
* This method returns if there is any essentia of the passed type that can be drained. It in no way checks how
* much there is, only if an essentia container nearby contains at least 1 point worth.
* @param tile the tile entity that is checking the essentia
* @param aspect the aspect that you are looking for
* @param direction the direction from which you wish to drain. EnumFacing.Unknown simply seeks in all directions.
* @param range how many blocks you wish to search for essentia sources.
* @return boolean returns true if essentia was found and removed from a source.
*/
public static boolean findEssentia(TileEntity tile, Aspect aspect, EnumFacing direction, int range) {
try {
if(findEssentia == null) {
Class fake = Class.forName("thaumcraft.common.lib.events.EssentiaHandler");
findEssentia = fake.getMethod("findEssentia", TileEntity.class, Aspect.class, EnumFacing.class, int.class);
}
return (Boolean) findEssentia.invoke(null, tile, aspect, direction, range);
} catch(Exception ex) {
FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.lib.events.EssentiaHandler method findEssentia");
}
return false;
}
}

View file

@ -0,0 +1,80 @@
package thaumcraft.api.aspects;
/**
*
* @author azanor
*
* Used by blocks like the crucible and alembic to hold their aspects.
* Tiles extending this interface will have their aspects show up when viewed by goggles of revealing
*
*/
public interface IAspectContainer {
public AspectList getAspects();
public void setAspects(AspectList aspects);
/**
* This method is used to determine of a specific aspect can be added to this container.
* @param tag
* @return true or false
*/
public boolean doesContainerAccept(Aspect tag);
/**
* This method is used to add a certain amount of an aspect to the tile entity.
* @param tag
* @param amount
* @return the amount of aspect left over that could not be added.
*/
public int addToContainer(Aspect tag, int amount);
/**
* Removes a certain amount of a specific aspect from the tile entity
* @param tag
* @param amount
* @return true if that amount of aspect was available and was removed
*/
public boolean takeFromContainer(Aspect tag, int amount);
/**
* removes a bunch of different aspects and amounts from the tile entity.
* @param ot the ObjectTags object that contains the aspects and their amounts.
* @return true if all the aspects and their amounts were available and successfully removed
*
* Going away in the next major patch
*/
@Deprecated
public boolean takeFromContainer(AspectList ot);
/**
* Checks if the tile entity contains the listed amount (or more) of the aspect
* @param tag
* @param amount
* @return
*/
public boolean doesContainerContainAmount(Aspect tag,int amount);
/**
* Checks if the tile entity contains all the listed aspects and their amounts
* @param ot the ObjectTags object that contains the aspects and their amounts.
* @return
*
* Going away in the next major patch
*/
@Deprecated
public boolean doesContainerContain(AspectList ot);
/**
* Returns how much of the aspect this tile entity contains
* @param tag
* @return the amount of that aspect found
*/
public int containerContains(Aspect tag);
}

View file

@ -0,0 +1,16 @@
package thaumcraft.api.aspects;
/**
* @author Azanor
*
* This interface is implemented by tile entites (or possibly anything else) like jars
* so that they can act as an essentia source for blocks like the infusion altar.
*
*/
public interface IAspectSource extends IAspectContainer {
}

View file

@ -0,0 +1,45 @@
package thaumcraft.api.aspects;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
/**
*
* @author azanor
*
* Used by wispy essences and essentia phials to hold their aspects.
* Useful for similar item containers that store their aspect information in nbt form so TC
* automatically picks up the aspects they contain.
*
*/
public interface IEssentiaContainerItem {
public AspectList getAspects(ItemStack itemstack);
public void setAspects(ItemStack itemstack, AspectList aspects);
/**
* Return true if the contained aspect should not be used to calculate the actual item aspects. For example: jar labels.
*/
public boolean ignoreContainedAspects();
}
//Example implementation
/*
@Override
public AspectList getAspects(ItemStack itemstack) {
if (itemstack.hasTagCompound()) {
AspectList aspects = new AspectList();
aspects.readFromNBT(itemstack.getTagCompound());
return aspects.size()>0?aspects:null;
}
return null;
}
@Override
public void setAspects(ItemStack itemstack, AspectList aspects) {
if (!itemstack.hasTagCompound()) itemstack.setTagCompound(new NBTTagCompound());
aspects.writeToNBT(itemstack.getTagCompound());
}
@Override
public boolean ignoreContainedAspects() {return false;}
*/

View file

@ -0,0 +1,92 @@
package thaumcraft.api.aspects;
import net.minecraft.util.EnumFacing;
/**
* @author Azanor
* This interface is used by tiles that use or transport vis.
* Only tiles that implement this interface will be able to connect to vis conduits or other thaumic devices
*/
public interface IEssentiaTransport {
/**
* Is this tile able to connect to other vis users/sources on the specified side?
* @param face
* @return
*/
public boolean isConnectable(EnumFacing face);
/**
* Is this side used to input essentia?
* @param face
* @return
*/
boolean canInputFrom(EnumFacing face);
/**
* Is this side used to output essentia?
* @param face
* @return
*/
boolean canOutputTo(EnumFacing face);
/**
* Sets the amount of suction this block will apply
* @param suction
*/
public void setSuction(Aspect aspect, int amount);
/**
* Returns the type of suction this block is applying.
* @param loc
* the location from where the suction is being checked
* @return
* a return type of null indicates the suction is untyped and the first thing available will be drawn
*/
public Aspect getSuctionType(EnumFacing face);
/**
* Returns the strength of suction this block is applying.
* @param loc
* the location from where the suction is being checked
* @return
*/
public int getSuctionAmount(EnumFacing face);
/**
* remove the specified amount of essentia from this transport tile
* @return how much was actually taken
*/
public int takeEssentia(Aspect aspect, int amount, EnumFacing face);
/**
* add the specified amount of essentia to this transport tile
* @return how much was actually added
*/
public int addEssentia(Aspect aspect, int amount, EnumFacing face);
/**
* What type of essentia this contains
* @param face
* @return
*/
public Aspect getEssentiaType(EnumFacing face);
/**
* How much essentia this block contains
* @param face
* @return
*/
public int getEssentiaAmount(EnumFacing face);
/**
* Essentia will not be drawn from this container unless the suction exceeds this amount.
* @return the amount
*/
public int getMinimumSuction();
}

View file

@ -0,0 +1,81 @@
package thaumcraft.api.aura;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.Aspect;
public class AuraHelper {
/**
* Consume vis from the aura at the given location
* @param world
* @param pos
* @param aspect
* @param amount
* @return has anything been consumed
*/
public static boolean drainAura(World world, BlockPos pos, Aspect aspect, int amount) {
return ThaumcraftApi.internalMethods.drainAura(world,pos, aspect, amount);
}
/**
* Consume vis from the aura at the given location
* @param world
* @param pos
* @param aspect
* @param amount
* @return how much was actually drained
*/
public static int drainAuraAvailable(World world, BlockPos pos, Aspect aspect, int amount) {
return ThaumcraftApi.internalMethods.drainAuraAvailable(world,pos, aspect, amount);
}
/**
* Adds vis to the aura at the given location. This does not actually increase the aura instantly -
* it merely adds a recharge ticked to the chunk that will add to the aura there the next time it is processed.
*
* @param world
* @param pos
* @param aspect
* @param amount
*/
public static void addAura(World world, BlockPos pos, Aspect aspect, int amount) {
ThaumcraftApi.internalMethods.addAura(world,pos, aspect, amount);
}
/**
* Get how much of a given aspect is in the aura at the given location.
* @param world
* @param pos
* @param aspect
* @return
*/
public static int getAura(World world, BlockPos pos, Aspect aspect) {
return ThaumcraftApi.internalMethods.getAura(world,pos, aspect);
}
/**
* Gets the general aura baseline at the given location
* @param world
* @param pos
* @return
*/
public static int getAuraBase(World world, BlockPos pos) {
return ThaumcraftApi.internalMethods.getAuraBase(world,pos);
}
/**
* Adds flux to the aura at the specified block position.
* @param world
* @param pos
* @param amount how much flux to add
* @param showEffect if set to true, a flux goo splash effect and sound will also be displayed. Use in moderation.
*/
public static void pollute(World world, BlockPos pos, int amount, boolean showEffect) {
ThaumcraftApi.internalMethods.pollute(world,pos,amount,showEffect);
}
}

View file

@ -0,0 +1,132 @@
package thaumcraft.api.blocks;
import net.minecraft.block.Block;
public class BlocksTC {
// World
public static Block oreAmber;
public static Block oreCinnabar;
public static Block log;
public static Block leaf;
public static Block sapling;
public static Block shimmerleaf;
public static Block cinderpearl;
public static Block vishroom;
public static Block plank;
public static Block stone;
public static Block translucent;
public static Block stairsArcane;
public static Block stairsArcaneBrick;
public static Block stairsAncient;
public static Block stairsSilverwood;
public static Block stairsGreatwood;
public static Block stairsEldritch;
public static Block slabWood;
public static Block slabStone;
public static Block doubleSlabWood;
public static Block doubleSlabStone;
public static Block taintBlock;
public static Block taintFibre;
public static Block taintDust;
public static Block taintLog;
public static Block taintFeature;
public static Block lootCrate;
public static Block lootUrn;
public static Block eldritch;
public static Block crystalAir;
public static Block crystalFire;
public static Block crystalWater;
public static Block crystalEarth;
public static Block crystalOrder;
public static Block crystalEntropy;
public static Block crystalTaint;
// Doodads
public static Block tableWood;
public static Block tableStone;
/** THAUMIUM, VOID, ALCHEMICAL, ADVANCED_ALCHEMICAL, BRASS */
public static Block metal;
public static Block candle;
public static Block nitor;
public static Block bloom;
public static Block pedestal;
public static Block itemGrate;
public static Block fleshBlock;
public static Block banner;
public static Block pavingStone;
public static Block pillar;
public static Block redstoneRelay;
// Machines
public static Block arcaneEar;
public static Block levitator;
public static Block dioptra;
public static Block crucible;
public static Block arcaneWorkbench;
public static Block arcaneWorkbenchCharger;
public static Block wandWorkbench;
public static Block rechargePedestal;
public static Block researchTable;
public static Block tube;
public static Block centrifuge;
public static Block crystallizer;
public static Block hungryChest;
public static Block jar;
public static Block bellows;
public static Block smelterBasic;
public static Block smelterThaumium;
public static Block smelterVoid;
public static Block smelterAux;
public static Block smelterVent;
public static Block alembic;
public static Block infusionMatrix;
public static Block infernalFurnace;
public static Block arcaneBore;
public static Block arcaneBoreBase;
public static Block thaumatorium;
public static Block brainBox;
public static Block mirror;
public static Block mirrorEssentia;
public static Block auraTotem;
public static Block spa;
public static Block waterJug;
public static Block lampArcane;
public static Block lampFertility;
public static Block lampGrowth;
// Fluids
public static Block fluxGoo;
public static Block purifyingFluid;
public static Block liquidDeath;
// Misc
public static Block hole;
public static Block vacuum;
public static Block effect;
public static Block barrier;
public static Block placeholder;
}

View file

@ -0,0 +1,23 @@
package thaumcraft.api.blocks;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
/**
*
* @author Azanor
*
* Tile entities or blocks that extend this interface can have jar labels applied to them
*
*/
public interface ILabelable {
/**
* This method is used by the block or tileentity to do whatever needs doing.
* @return if true then label will be subtracted from player inventory
*/
public boolean applyLabel(EntityPlayer player, BlockPos pos, EnumFacing side, ItemStack labelstack);
}

View file

@ -0,0 +1,81 @@
package thaumcraft.api.blocks;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
/**
*
* @author azanor
*
* Custom tile entity class I use for most of my tile entities. Setup in such a way that only
* the nbt data within readCustomNBT / writeCustomNBT will be sent to the client when the tile
* updates. Apart from all the normal TE data that gets sent that is.
*
*/
public class TileThaumcraft extends TileEntity {
//NBT stuff
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
readCustomNBT(nbt);
}
public void readCustomNBT(NBTTagCompound nbt)
{
//TODO
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
writeCustomNBT(nbt);
}
public void writeCustomNBT(NBTTagCompound nbt)
{
//TODO
}
//Client Packet stuff
@Override
public Packet getDescriptionPacket() {
NBTTagCompound nbt = new NBTTagCompound();
this.writeCustomNBT(nbt);
return new S35PacketUpdateTileEntity(this.getPos(), -999, nbt);
}
@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
super.onDataPacket(net, pkt);
this.readCustomNBT(pkt.getNbtCompound());
}
@Override
public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newState) {
return oldState.getBlock() != newState.getBlock();
}
public EnumFacing getFacing() {
try {
return EnumFacing.getFront(getBlockMetadata() & 7);
} catch (Exception e) { }
return EnumFacing.UP;
}
public boolean gettingPower() {
return worldObj.isBlockPowered(getPos());
}
}

View file

@ -0,0 +1,90 @@
package thaumcraft.api.crafting;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.ThaumcraftApiHelper;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class CrucibleRecipe {
private ItemStack recipeOutput;
public Object catalyst;
public AspectList aspects;
public String research;
public int hash;
public CrucibleRecipe(String researchKey, ItemStack result, Object cat, AspectList tags) {
recipeOutput = result;
this.aspects = tags;
this.research = researchKey;
this.catalyst = cat;
if (cat instanceof String) {
this.catalyst = OreDictionary.getOres((String) cat);
}
String hc = researchKey;
hc += result.toString();
for (Aspect tag:tags.getAspects()) {
hc += tag.getTag()+tags.getAmount(tag);
}
if (cat instanceof ItemStack) {
hc += ((ItemStack)cat).toString();
} else
if (cat instanceof List && ((List<ItemStack>)catalyst).size()>0) {
for (ItemStack is :(List<ItemStack>)catalyst) {
hc += is.toString();
}
}
hash = hc.hashCode();
}
public boolean matches(AspectList itags, ItemStack cat) {
if (catalyst instanceof ItemStack && !OreDictionary.itemMatches((ItemStack) catalyst,cat,false)) {
return false;
} else
if (catalyst instanceof List && ((List<ItemStack>)catalyst).size()>0) {
if (!ThaumcraftApiHelper.containsMatch(false, new ItemStack[]{cat},
(List<ItemStack>)catalyst)) return false;
}
if (itags==null) return false;
for (Aspect tag:aspects.getAspects()) {
if (itags.getAmount(tag)<aspects.getAmount(tag)) return false;
}
return true;
}
public boolean catalystMatches(ItemStack cat) {
if (catalyst instanceof ItemStack && OreDictionary.itemMatches((ItemStack) catalyst,cat,false)) {
return true;
} else
if (catalyst instanceof List && ((List<ItemStack>)catalyst).size()>0) {
if (ThaumcraftApiHelper.containsMatch(false, new ItemStack[]{cat}, (List<ItemStack>)catalyst)) return true;
}
return false;
}
public AspectList removeMatching(AspectList itags) {
AspectList temptags = new AspectList();
temptags.aspects.putAll(itags.aspects);
for (Aspect tag:aspects.getAspects()) {
temptags.remove(tag, aspects.getAmount(tag));
}
itags = temptags;
return itags;
}
public ItemStack getRecipeOutput() {
return recipeOutput;
}
}

View file

@ -0,0 +1,28 @@
package thaumcraft.api.crafting;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
import thaumcraft.api.aspects.AspectList;
public interface IArcaneRecipe extends IRecipe
{
boolean matches(InventoryCrafting inv, World worldIn);
boolean matches(InventoryCrafting inv, World world, EntityPlayer player);
ItemStack getCraftingResult(InventoryCrafting inv);
int getRecipeSize();
ItemStack getRecipeOutput();
ItemStack[] getRemainingItems(InventoryCrafting inv);
AspectList getAspects();
AspectList getAspects(InventoryCrafting inv);
String[] getResearch();
}

View file

@ -0,0 +1,11 @@
package thaumcraft.api.crafting;
/**
*
* @author Azanor
* This needs to be implemented by any inventory that wishes to act as an arcane workbench.
*
*/
public interface IArcaneWorkbench {
}

View file

@ -0,0 +1,20 @@
package thaumcraft.api.crafting;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
/**
*
* @author Azanor
*
* Blocks that implement this interface act as infusion crafting stabilisers like candles and skulls
*
*/
public interface IInfusionStabiliser {
/**
* returns true if the block can stabilise things
*/
public boolean canStabaliseInfusion(World world, BlockPos pos);
}

View file

@ -0,0 +1,136 @@
package thaumcraft.api.crafting;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import thaumcraft.api.ThaumcraftApiHelper;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.research.ResearchHelper;
@Deprecated
public class InfusionEnchantmentRecipe
{
public AspectList aspects;
public String[] research;
public Object[] components;
public Enchantment enchantment;
public int recipeXP;
public int instability;
public InfusionEnchantmentRecipe(String research, Enchantment input, int inst, AspectList aspects2, Object[] recipe) {
this(new String[]{research},input,inst,aspects2,recipe);
}
public InfusionEnchantmentRecipe(String[] research, Enchantment input, int inst, AspectList aspects2, Object[] recipe) {
this.research = research;
this.enchantment = input;
this.aspects = aspects2;
this.components = recipe;
this.instability = inst;
this.recipeXP = Math.max(1, input.getMinEnchantability(1)/3);
}
/**
* Used to check if a recipe matches current crafting inventory
* @param player
*/
public boolean matches(ArrayList<ItemStack> input, ItemStack central, World world, EntityPlayer player) {
if (research!=null && research[0].length()>0 && !ResearchHelper.isResearchComplete(player.getName(), research)) {
return false;
}
if (!enchantment.canApply(central) || !central.getItem().isItemTool(central)) {
return false;
}
Map map1 = EnchantmentHelper.getEnchantments(central);
Iterator iterator = map1.keySet().iterator();
while (iterator.hasNext())
{
int j1 = ((Integer)iterator.next()).intValue();
Enchantment ench = Enchantment.enchantmentsBookList[j1];
if (j1 == enchantment.effectId &&
EnchantmentHelper.getEnchantmentLevel(j1, central)>=ench.getMaxLevel())
return false;
if (enchantment.effectId != ench.effectId &&
(!enchantment.canApplyTogether(ench) ||
!ench.canApplyTogether(enchantment))) {
return false;
}
}
ItemStack i2 = null;
ArrayList<ItemStack> ii = new ArrayList<ItemStack>();
for (ItemStack is:input) {
ii.add(is.copy());
}
for (Object comp:components) {
boolean b=false;
for (int a=0;a<ii.size();a++) {
i2 = ii.get(a).copy();
if (ThaumcraftApiHelper.areItemStacksEqualForCrafting(i2, comp)) {
ii.remove(a);
b=true;
break;
}
}
if (!b) return false;
}
// System.out.println(ii.size());
return ii.size()==0?true:false;
}
public Enchantment getEnchantment() {
return enchantment;
}
public AspectList getAspects() {
return aspects;
}
public String[] getResearch() {
return research;
}
public int calcInstability(ItemStack recipeInput) {
int i = 0;
Map map1 = EnchantmentHelper.getEnchantments(recipeInput);
Iterator iterator = map1.keySet().iterator();
while (iterator.hasNext())
{ int j1 = ((Integer)iterator.next()).intValue();
i += EnchantmentHelper.getEnchantmentLevel(j1, recipeInput);
}
return (i/2) + instability;
}
public int calcXP(ItemStack recipeInput) {
return recipeXP * (1+EnchantmentHelper.getEnchantmentLevel(enchantment.effectId, recipeInput));
}
public float getEssentiaMod(ItemStack recipeInput) {
float mod = EnchantmentHelper.getEnchantmentLevel(enchantment.effectId, recipeInput);
Map map1 = EnchantmentHelper.getEnchantments(recipeInput);
Iterator iterator = map1.keySet().iterator();
while (iterator.hasNext())
{
int j1 = ((Integer)iterator.next()).intValue();
if (j1 != enchantment.effectId)
mod += EnchantmentHelper.getEnchantmentLevel(j1, recipeInput) * .1f;
}
return mod;
}
}

View file

@ -0,0 +1,106 @@
package thaumcraft.api.crafting;
import java.util.ArrayList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.ThaumcraftApiHelper;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.research.ResearchHelper;
public class InfusionRecipe
{
protected AspectList aspects;
protected String[] research;
private Object[] components;
private Object recipeInput;
protected Object recipeOutput;
protected int instability;
public InfusionRecipe(String research, Object output, int inst, AspectList aspects2, Object input, Object[] recipe) {
this(new String[]{research},output,inst,aspects2,input,recipe);
}
public InfusionRecipe(String[] research, Object output, int inst, AspectList aspects2, Object input, Object[] recipe) {
this.research = research;
this.recipeOutput = output;
this.recipeInput = input;
this.aspects = aspects2;
this.components = recipe;
this.instability = inst;
}
/**
* Used to check if a recipe matches current crafting inventory
* @param player
*/
public boolean matches(ArrayList<ItemStack> input, ItemStack central, World world, EntityPlayer player) {
if (getRecipeInput()==null) return false;
if (research!=null && research[0].length()>0 && !ResearchHelper.isResearchComplete(player.getName(), research)) {
return false;
}
ItemStack i2 = central.copy();
if (getRecipeInput() instanceof ItemStack &&
((ItemStack)getRecipeInput()).getItemDamage()==OreDictionary.WILDCARD_VALUE) {
i2.setItemDamage(OreDictionary.WILDCARD_VALUE);
}
if (!ThaumcraftApiHelper.areItemStacksEqualForCrafting(i2, getRecipeInput())) return false;
ArrayList<ItemStack> ii = new ArrayList<ItemStack>();
for (ItemStack is:input) {
ii.add(is.copy());
}
for (Object comp:getComponents()) {
boolean b=false;
for (int a=0;a<ii.size();a++) {
i2 = ii.get(a).copy();
if (ThaumcraftApiHelper.areItemStacksEqualForCrafting(i2, comp)) {
ii.remove(a);
b=true;
break;
}
}
if (!b) return false;
}
return ii.size()==0?true:false;
}
public String[] getResearch() {
return research;
}
public Object getRecipeInput() {
return recipeInput;
}
public Object[] getComponents() {
return components;
}
public Object getRecipeOutput() {
return recipeOutput;
}
public AspectList getAspects() {
return aspects;
}
public Object getRecipeOutput(EntityPlayer player, ItemStack input, ArrayList<ItemStack> comps ) {
return recipeOutput;
}
public AspectList getAspects(EntityPlayer player, ItemStack input, ArrayList<ItemStack> comps) {
return aspects;
}
public int getInstability(EntityPlayer player, ItemStack input, ArrayList<ItemStack> comps) {
return instability;
}
}

View file

@ -0,0 +1,284 @@
package thaumcraft.api.crafting;
import java.util.HashMap;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.ThaumcraftApiHelper;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.research.ResearchHelper;
public class ShapedArcaneRecipe implements IArcaneRecipe
{
//Added in for future ease of change, but hard coded for now.
private static final int MAX_CRAFT_GRID_WIDTH = 3;
private static final int MAX_CRAFT_GRID_HEIGHT = 3;
public ItemStack output = null;
public Object[] input = null;
public AspectList aspects = null;
public String[] research;
public int width = 0;
public int height = 0;
private boolean mirrored = true;
public ShapedArcaneRecipe(String research, ItemStack result, AspectList aspects, Object... recipe){ this(new String[]{research}, result, aspects, recipe); }
public ShapedArcaneRecipe(String[] research, ItemStack result, AspectList aspects, Object... recipe)
{
output = result.copy();
this.research = research;
this.aspects = aspects;
String shape = "";
int idx = 0;
if (recipe[idx] instanceof Boolean)
{
mirrored = (Boolean)recipe[idx];
if (recipe[idx+1] instanceof Object[])
{
recipe = (Object[])recipe[idx+1];
}
else
{
idx = 1;
}
}
if (recipe[idx] instanceof String[])
{
String[] parts = ((String[])recipe[idx++]);
for (String s : parts)
{
width = s.length();
shape += s;
}
height = parts.length;
}
else
{
while (recipe[idx] instanceof String)
{
String s = (String)recipe[idx++];
shape += s;
width = s.length();
height++;
}
}
if (width * height != shape.length())
{
String ret = "Invalid shaped ore recipe: ";
for (Object tmp : recipe)
{
ret += tmp + ", ";
}
ret += output;
throw new RuntimeException(ret);
}
HashMap<Character, Object> itemMap = new HashMap<Character, Object>();
for (; idx < recipe.length; idx += 2)
{
Character chr = (Character)recipe[idx];
Object in = recipe[idx + 1];
if (in instanceof ItemStack)
{
itemMap.put(chr, ((ItemStack)in).copy());
}
else if (in instanceof Item)
{
itemMap.put(chr, new ItemStack((Item)in));
}
else if (in instanceof Block)
{
itemMap.put(chr, new ItemStack((Block)in, 1, OreDictionary.WILDCARD_VALUE));
}
else if (in instanceof String)
{
itemMap.put(chr, OreDictionary.getOres((String)in));
}
else
{
String ret = "Invalid shaped ore recipe: ";
for (Object tmp : recipe)
{
ret += tmp + ", ";
}
ret += output;
throw new RuntimeException(ret);
}
}
input = new Object[width * height];
int x = 0;
for (char chr : shape.toCharArray())
{
input[x++] = itemMap.get(chr);
}
}
@Override
public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); }
@Override
public int getRecipeSize(){ return input.length; }
@Override
public ItemStack getRecipeOutput(){ return output; }
@Override
public boolean matches(InventoryCrafting inv, World world)
{
return inv instanceof IArcaneWorkbench && matches(inv,world,null);
}
@Override
public boolean matches(InventoryCrafting inv, World world, EntityPlayer player)
{
if (player!=null && ( research!=null && research[0].length()>0 && !ResearchHelper.isResearchComplete(player.getName(), research))) {
return false;
}
for (int x = 0; x <= MAX_CRAFT_GRID_WIDTH - width; x++)
{
for (int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - height; ++y)
{
if (checkMatch(inv, x, y, false))
{
return true;
}
if (mirrored && checkMatch(inv, x, y, true))
{
return true;
}
}
}
return false;
}
private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror)
{
for (int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++)
{
for (int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++)
{
int subX = x - startX;
int subY = y - startY;
Object target = null;
if (subX >= 0 && subY >= 0 && subX < width && subY < height)
{
if (mirror)
{
target = input[width - subX - 1 + subY * width];
}
else
{
target = input[subX + subY * width];
}
}
ItemStack slot = inv.getStackInRowAndColumn(x, y);
if (target instanceof ItemStack)
{
if (!checkItemEquals((ItemStack)target, slot))
{
return false;
}
}
else if (target instanceof List)
{
boolean matched = false;
for (ItemStack item : (List<ItemStack>)target)
{
matched = matched || checkItemEquals(item, slot);
}
if (!matched)
{
return false;
}
}
else if (target == null && slot != null)
{
return false;
}
}
}
return true;
}
private boolean checkItemEquals(ItemStack target, ItemStack input)
{
if (input == null && target != null || input != null && target == null)
{
return false;
}
return (target.getItem() == input.getItem() &&
(!target.hasTagCompound() || ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(input,target)) &&
(target.getItemDamage() == OreDictionary.WILDCARD_VALUE|| target.getItemDamage() == input.getItemDamage()));
}
public ShapedArcaneRecipe setMirrored(boolean mirror)
{
mirrored = mirror;
return this;
}
/**
* Returns the input for this recipe, any mod accessing this value should never
* manipulate the values in this array as it will effect the recipe itself.
* @return The recipes input vales.
*/
public Object[] getInput()
{
return this.input;
}
@Override
public AspectList getAspects() {
return aspects;
}
@Override
public AspectList getAspects(InventoryCrafting inv) {
return aspects;
}
@Override
public String[] getResearch() {
return research;
}
@Override
public ItemStack[] getRemainingItems(InventoryCrafting p_179532_1_)
{
ItemStack[] aitemstack = new ItemStack[p_179532_1_.getSizeInventory()];
for (int i = 0; i < Math.min(9, aitemstack.length); ++i)
{
ItemStack itemstack = p_179532_1_.getStackInSlot(i);
aitemstack[i] = net.minecraftforge.common.ForgeHooks.getContainerItem(itemstack);
}
return aitemstack;
}
}

View file

@ -0,0 +1,182 @@
package thaumcraft.api.crafting;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import thaumcraft.api.ThaumcraftApiHelper;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.research.ResearchHelper;
public class ShapelessArcaneRecipe implements IArcaneRecipe
{
private ItemStack output = null;
private ArrayList input = new ArrayList();
public AspectList aspects = null;
public String[] research;
public ShapelessArcaneRecipe(String research, ItemStack result, AspectList aspects, Object... recipe){ this(new String[] {research}, result,aspects, recipe); }
public ShapelessArcaneRecipe(String[] research, ItemStack result, AspectList aspects, Object... recipe)
{
output = result.copy();
this.research = research;
this.aspects = aspects;
for (Object in : recipe)
{
if (in instanceof ItemStack)
{
input.add(((ItemStack)in).copy());
}
else if (in instanceof Item)
{
input.add(new ItemStack((Item)in));
}
else if (in instanceof Block)
{
input.add(new ItemStack((Block)in));
}
else if (in instanceof String)
{
input.add(OreDictionary.getOres((String)in));
}
else
{
String ret = "Invalid shapeless ore recipe: ";
for (Object tmp : recipe)
{
ret += tmp + ", ";
}
ret += output;
throw new RuntimeException(ret);
}
}
}
@Override
public int getRecipeSize(){ return input.size(); }
@Override
public ItemStack getRecipeOutput(){ return output; }
@Override
public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); }
@Override
public boolean matches(InventoryCrafting inv, World world)
{
return inv instanceof IArcaneWorkbench && matches(inv,world,null);
}
@Override
public boolean matches(InventoryCrafting var1, World world, EntityPlayer player)
{
if (player!=null && ( research != null && research[0].length()>0 && !ResearchHelper.isResearchComplete(player.getName(), research))) {
return false;
}
ArrayList required = new ArrayList(input);
for (int x = 0; x < 9; x++)
{
ItemStack slot = var1.getStackInSlot(x);
if (slot != null)
{
boolean inRecipe = false;
Iterator req = required.iterator();
while (req.hasNext())
{
boolean match = false;
Object next = req.next();
if (next instanceof ItemStack)
{
match = checkItemEquals((ItemStack)next, slot);
}
else if (next instanceof List)
{
for (ItemStack item : (List<ItemStack>)next)
{
match = match || checkItemEquals(item, slot);
}
}
if (match)
{
inRecipe = true;
required.remove(next);
break;
}
}
if (!inRecipe)
{
return false;
}
}
}
return required.isEmpty();
}
private boolean checkItemEquals(ItemStack target, ItemStack input)
{
if (input == null && target != null || input != null && target == null)
{
return false;
}
return (target.getItem() == input.getItem() &&
(!target.hasTagCompound() || ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(input,target)) &&
(target.getItemDamage() == OreDictionary.WILDCARD_VALUE|| target.getItemDamage() == input.getItemDamage()));
}
/**
* Returns the input for this recipe, any mod accessing this value should never
* manipulate the values in this array as it will effect the recipe itself.
* @return The recipes input vales.
*/
public ArrayList getInput()
{
return this.input;
}
@Override
public AspectList getAspects() {
return aspects;
}
@Override
public AspectList getAspects(InventoryCrafting inv) {
return aspects;
}
@Override
public String[] getResearch() {
return research;
}
@Override
public ItemStack[] getRemainingItems(InventoryCrafting p_179532_1_)
{
ItemStack[] aitemstack = new ItemStack[p_179532_1_.getSizeInventory()];
for (int i = 0; i < Math.min(9, aitemstack.length); ++i)
{
ItemStack itemstack = p_179532_1_.getStackInSlot(i);
aitemstack[i] = net.minecraftforge.common.ForgeHooks.getContainerItem(itemstack);
}
return aitemstack;
}
}

View file

@ -0,0 +1,32 @@
package thaumcraft.api.damagesource;
import net.minecraft.entity.Entity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSourceIndirect;
public class DamageSourceIndirectThaumcraftEntity extends EntityDamageSourceIndirect {
private boolean fireDamage;
private float hungerDamage;
private boolean isUnblockable;
public DamageSourceIndirectThaumcraftEntity(String par1Str,
Entity par2Entity, Entity par3Entity) {
super(par1Str, par2Entity, par3Entity);
}
public DamageSource setFireDamage()
{
this.fireDamage = true;
return this;
}
public DamageSource setDamageBypassesArmor()
{
this.isUnblockable = true;
this.hungerDamage = 0.0F;
return this;
}
}

View file

@ -0,0 +1,47 @@
package thaumcraft.api.damagesource;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSource;
public class DamageSourceThaumcraft extends DamageSource
{
public static DamageSource taint = new DamageSourceThaumcraft("taint").setDamageBypassesArmor().setMagicDamage();
public static DamageSource tentacle = new DamageSourceThaumcraft("tentacle");
public static DamageSource swarm = new DamageSourceThaumcraft("swarm");
public static DamageSource dissolve = new DamageSourceThaumcraft("dissolve").setDamageBypassesArmor();
protected DamageSourceThaumcraft(String par1Str) {
super(par1Str);
}
/** This kind of damage can be blocked or not. */
private boolean isUnblockable = false;
private boolean isDamageAllowedInCreativeMode = false;
private float hungerDamage = 0.3F;
/** This kind of damage is based on fire or not. */
private boolean fireDamage;
/** This kind of damage is based on a projectile or not. */
private boolean projectile;
/**
* Whether this damage source will have its damage amount scaled based on the current difficulty.
*/
private boolean difficultyScaled;
private boolean magicDamage = false;
private boolean explosion = false;
public static DamageSource causeSwarmDamage(EntityLivingBase par0EntityLiving)
{
return new EntityDamageSource("swarm", par0EntityLiving);
}
public static DamageSource causeTentacleDamage(EntityLivingBase par0EntityLiving)
{
return new EntityDamageSource("tentacle", par0EntityLiving);
}
}

View file

@ -0,0 +1,5 @@
package thaumcraft.api.entities;
public interface IEldritchMob {
}

View file

@ -0,0 +1,5 @@
package thaumcraft.api.entities;
public interface ITaintedMob {
}

View file

@ -0,0 +1,11 @@
package thaumcraft.api.golems;
/**
* Items using this interface will make golem seals visible in the world while held
*
* @author azanor
*
*/
public interface ISealDisplayer {
}

View file

@ -0,0 +1,93 @@
package thaumcraft.api.internal;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class DummyInternalMethodHandler implements IInternalMethodHandler {
@Override
public boolean isResearchComplete(String username, String researchkey) {
return false;
}
@Override
public AspectList getObjectAspects(ItemStack is) {
return null;
}
@Override
public AspectList generateTags(Item item, int meta) {
return null;
}
@Override
public boolean consumeVisFromWand(ItemStack wand, EntityPlayer player,
AspectList cost, boolean doit, boolean crafting) {
return false;
}
@Override
public boolean consumeVisFromInventory(EntityPlayer player, AspectList cost) {
return false;
}
@Override
public void addWarpToPlayer(EntityPlayer player, int amount, EnumWarpType type) {
}
@Override
public int getPlayerWarp(EntityPlayer player, EnumWarpType type) {
return 0;
}
@Override
public void markRunicDirty(Entity entity) {
}
@Override
public boolean completeResearch(EntityPlayer player, String researchkey) {
return false;
}
@Override
public boolean drainAura(World world, BlockPos pos, Aspect aspect, int amount) {
return false;
}
@Override
public void addAura(World world, BlockPos pos, Aspect aspect, int amount) {
}
@Override
public void pollute(World world, BlockPos pos, int amount, boolean showEffect) { }
@Override
public int getAura(World world, BlockPos pos, Aspect aspect) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getAuraBase(World world, BlockPos pos) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int drainAuraAvailable(World world, BlockPos pos, Aspect aspect,
int amount) {
// TODO Auto-generated method stub
return 0;
}
}

View file

@ -0,0 +1,5 @@
package thaumcraft.api.internal;
public enum EnumWarpType {
PERMANENT, NORMAL, TEMPORARY;
}

View file

@ -0,0 +1,30 @@
package thaumcraft.api.internal;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public interface IInternalMethodHandler {
public boolean isResearchComplete(String username, String researchkey);
public AspectList getObjectAspects(ItemStack is);
public AspectList generateTags(Item item, int meta);
public boolean consumeVisFromWand(ItemStack wand, EntityPlayer player, AspectList cost, boolean doit, boolean crafting);
public boolean consumeVisFromInventory(EntityPlayer player, AspectList cost);
public void addWarpToPlayer(EntityPlayer player, int amount, EnumWarpType type);
public int getPlayerWarp(EntityPlayer player, EnumWarpType type);
public void markRunicDirty(Entity entity);
public boolean completeResearch(EntityPlayer player, String researchkey);
public boolean drainAura(World world, BlockPos pos, Aspect aspect,int amount);
public int drainAuraAvailable(World world, BlockPos pos, Aspect aspect, int amount);
public void addAura(World world, BlockPos pos, Aspect aspect, int amount);
public void pollute(World world, BlockPos pos, int amount, boolean showEffect);
public int getAura(World world, BlockPos pos, Aspect aspect);
public int getAuraBase(World world, BlockPos pos);
}

View file

@ -0,0 +1,24 @@
package thaumcraft.api.internal;
import java.util.ArrayList;
import net.minecraft.item.ItemStack;
import net.minecraft.util.WeightedRandom;
public class WeightedRandomLoot extends WeightedRandom.Item {
/** The Item/Block ID to generate in the bag. */
public ItemStack item;
public WeightedRandomLoot(ItemStack stack, int weight)
{
super(weight);
this.item = stack;
}
public static ArrayList<WeightedRandomLoot> lootBagCommon = new ArrayList<WeightedRandomLoot>();
public static ArrayList<WeightedRandomLoot> lootBagUncommon = new ArrayList<WeightedRandomLoot>();
public static ArrayList<WeightedRandomLoot> lootBagRare = new ArrayList<WeightedRandomLoot>();
}

View file

@ -0,0 +1,101 @@
package thaumcraft.api.internal;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
public class WorldCoordinates implements Comparable
{
public BlockPos pos;
public int dim;
public WorldCoordinates() {}
public WorldCoordinates(BlockPos pos, int d)
{
this.pos = pos;
this.dim = d;
}
public WorldCoordinates(TileEntity tile)
{
this.pos = tile.getPos();
this.dim = tile.getWorld().provider.getDimensionId();
}
public WorldCoordinates(WorldCoordinates par1ChunkCoordinates)
{
this.pos = par1ChunkCoordinates.pos;
this.dim = par1ChunkCoordinates.dim;
}
public boolean equals(Object par1Obj)
{
if (!(par1Obj instanceof WorldCoordinates))
{
return false;
}
else
{
WorldCoordinates coordinates = (WorldCoordinates)par1Obj;
return this.pos.equals(coordinates.pos) && this.dim == coordinates.dim ;
}
}
public int hashCode()
{
return this.pos.getX() + this.pos.getY() << 8 + this.pos.getZ() << 16 + this.dim << 24;
}
/**
* Compare the coordinate with another coordinate
*/
public int compareWorldCoordinate(WorldCoordinates par1)
{
return this.dim == par1.dim ? this.pos.compareTo(par1.pos) : -1;
}
public void set(BlockPos pos, int d)
{
this.pos = pos;
this.dim = d;
}
/**
* Returns the squared distance between this coordinates and the coordinates given as argument.
*/
public double getDistanceSquared(BlockPos pos)
{
return this.pos.distanceSq(pos);
}
/**
* Return the squared distance between this coordinates and the ChunkCoordinates given as argument.
*/
public double getDistanceSquaredToWorldCoordinates(WorldCoordinates par1ChunkCoordinates)
{
return this.getDistanceSquared(par1ChunkCoordinates.pos);
}
public int compareTo(Object par1Obj)
{
return this.compareWorldCoordinate((WorldCoordinates)par1Obj);
}
public void readNBT(NBTTagCompound nbt) {
int x = nbt.getInteger("w_x");
int y = nbt.getInteger("w_y");
int z = nbt.getInteger("w_z");
this.pos = new BlockPos(x,y,z);
this.dim = nbt.getInteger("w_d");
}
public void writeNBT(NBTTagCompound nbt) {
nbt.setInteger("w_x",pos.getX());
nbt.setInteger("w_y",pos.getY());
nbt.setInteger("w_z",pos.getZ());
nbt.setInteger("w_d",dim);
}
}

View file

@ -0,0 +1,30 @@
package thaumcraft.api.items;
import java.util.ArrayList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
public interface IArchitect {
/**
* Returns a list of blocks that should be highlighted in world.
*/
public ArrayList<BlockPos> getArchitectBlocks(ItemStack stack, World world,
BlockPos pos, EnumFacing side, EntityPlayer player);
/**
* which axis should be displayed.
*/
public boolean showAxis(ItemStack stack, World world, EntityPlayer player, EnumFacing side,
EnumAxis axis);
public enum EnumAxis {
X, // east / west
Y, // up / down
Z; // north / south
}
}

View file

@ -0,0 +1,22 @@
package thaumcraft.api.items;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
/**
*
* @author Azanor
*
* Equipped or held items that extend this class will be able to perform most functions that
* goggles of revealing can apart from view nodes which is handled by IRevealer.
*
*/
public interface IGoggles {
/*
* If this method returns true things like block essentia contents will be shown.
*/
public boolean showIngamePopups(ItemStack itemstack, EntityLivingBase player);
}

View file

@ -0,0 +1,35 @@
package thaumcraft.api.items;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
/**
*
* @author Azanor
*
* Items with this interface can be recharged in wand pedestals and similar devices.
* The recharging needs to occur in handleRecharge and the passed in pos will be the
* player pos or the pos of the device doing the charging.
* The recharge pedestal will simply call handleRecharge and let the item do whatever
* it would normally to recharge.
* HandleRecharge should under normal conditions always be called every 5 ticks.
*
*/
public interface IRechargable {
/**
* @param world
* @param is
* @param pos
* @param player The passed in player can be null
* @param amount how much vis to recharge - modified by things like the node tapper research
* @return the last aspect that was recharged
*/
public Aspect handleRecharge(World world, ItemStack is, BlockPos pos, EntityPlayer player, int amount);
public AspectList getAspectsInChargable(ItemStack is);
}

View file

@ -0,0 +1,13 @@
package thaumcraft.api.items;
/**
* @author Azanor
* Items, armor and tools with this interface can receive the Repair enchantment.
* Repairs 1 point of durability every 10 seconds (2 for repair II)
*/
public interface IRepairable {
}

View file

@ -0,0 +1,17 @@
package thaumcraft.api.items;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
/**
* @author Azanor
* Items, armor and tools with this interface can receive the Repair enchantment.
* Repairs 1 point of durability every 10 seconds (2 for repair II)
*/
public interface IRepairableExtended extends IRepairable {
public boolean doRepair(ItemStack stack, EntityPlayer player, int enchantlevel);
}

View file

@ -0,0 +1,22 @@
package thaumcraft.api.items;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
/**
*
* @author Azanor
*
* Equipped or held items that extend this class will make nodes or related objects visible in world.
*
*/
public interface IRevealer {
/*
* If this method returns true the nodes will be visible.
*/
public boolean showNodes(ItemStack itemstack, EntityLivingBase player);
}

View file

@ -0,0 +1,22 @@
package thaumcraft.api.items;
import net.minecraft.item.ItemStack;
/**
*
* @author Azanor
*
* Armor or bauble slot items that implement this interface can provide runic shielding.
* Recharging, hardening, etc. is handled internally by thaumcraft.
*
*/
public interface IRunicArmor {
/**
* returns how much charge this item can provide. This is the base shielding value - any hardening is stored and calculated internally.
*/
public int getRunicCharge(ItemStack itemstack);
}

View file

@ -0,0 +1,14 @@
package thaumcraft.api.items;
/**
*
* @author Azanor
*
* Interface used to identify scribing tool items used in research table
*
*/
public interface IScribeTools {
}

View file

@ -0,0 +1,20 @@
package thaumcraft.api.items;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import thaumcraft.api.aspects.Aspect;
/**
* @author Azanor
* ItemArmor with this interface will grant a discount to the vis cost of actions the wearer performs with casting wands.
* The amount returned is the percentage by which the cost is discounted. There is a built-int max discount of 50%, but
* individual items really shouldn't have a discount more than 5%
*/
public interface IVisDiscountGear {
int getVisDiscount(ItemStack stack, EntityPlayer player, Aspect aspect);
}

View file

@ -0,0 +1,22 @@
package thaumcraft.api.items;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
/**
*
* @author Azanor
*
* Armor, held items or bauble slot items that implement this interface add warp when equipped or held.
*
*/
public interface IWarpingGear {
/**
* returns how much warp this item adds while worn or held.
*/
public int getWarp(ItemStack itemstack, EntityPlayer player);
}

View file

@ -0,0 +1,88 @@
package thaumcraft.api.items;
import java.util.List;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.aspects.IEssentiaContainerItem;
public class ItemGenericEssentiaContainer extends Item implements IEssentiaContainerItem
{
public ItemGenericEssentiaContainer(int base)
{
super();
this.base = base;
this.setMaxStackSize(64);
this.setHasSubtypes(true);
this.setMaxDamage(0);
}
int base = 1;
@SideOnly(Side.CLIENT)
@Override
public void getSubItems(Item par1, CreativeTabs par2CreativeTabs,List par3List) {
for (Aspect tag:Aspect.aspects.values()) {
ItemStack i = new ItemStack(this);
this.setAspects(i, new AspectList().add(tag, base));
par3List.add(i);
}
}
@SideOnly(Side.CLIENT)
@Override
public int getColorFromItemStack(ItemStack stack, int par2)
{
if (getAspects(stack)!=null) {
return getAspects(stack).getAspects()[0].getColor();
} else {
return 16777215;
}
}
@Override
public AspectList getAspects(ItemStack itemstack) {
if (itemstack.hasTagCompound()) {
AspectList aspects = new AspectList();
aspects.readFromNBT(itemstack.getTagCompound());
return aspects.size()>0?aspects:null;
}
return null;
}
@Override
public void setAspects(ItemStack itemstack, AspectList aspects) {
if (!itemstack.hasTagCompound())
itemstack.setTagCompound(new NBTTagCompound());
aspects.writeToNBT(itemstack.getTagCompound());
}
@Override
public boolean ignoreContainedAspects() {return false;}
@Override
public void onUpdate(ItemStack stack, World world, Entity entity, int par4, boolean par5) {
if (!world.isRemote && !stack.hasTagCompound()) {
Aspect[] displayAspects = Aspect.aspects.values().toArray(new Aspect[]{});
this.setAspects(stack, new AspectList().add(displayAspects[world.rand.nextInt(displayAspects.length)], base));
}
super.onUpdate(stack, world, entity, par4, par5);
}
@Override
public void onCreated(ItemStack stack, World world, EntityPlayer player) {
if (!world.isRemote && !stack.hasTagCompound()) {
Aspect[] displayAspects = Aspect.aspects.values().toArray(new Aspect[]{});
this.setAspects(stack, new AspectList().add(displayAspects[world.rand.nextInt(displayAspects.length)], base));
}
}
}

View file

@ -0,0 +1,21 @@
package thaumcraft.api.items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class ItemRunic extends Item implements IRunicArmor {
int charge;
public ItemRunic (int charge)
{
super();
this.charge = charge;
}
@Override
public int getRunicCharge(ItemStack itemstack) {
return charge;
}
}

View file

@ -0,0 +1,185 @@
package thaumcraft.api.items;
import net.minecraft.item.Item;
public class ItemsTC {
//raw materials
public static Item amber;
public static Item quicksilver;
/** air, fire, water, earth, order, entropy, tainted, balanced*/
public static Item shard;
/** "thaumium","void","brass"*/
public static Item ingots;
/**"iron","copper","tin","silver","lead","quicksilver","thaumium","void","brass"*/
public static Item nuggets;
/**"iron","gold","copper","tin","silver","lead","cinnabar"*/
public static Item clusters;
//resources
public static Item tallow;
public static Item fabric;
/** "brass","thaumium","void"*/
public static Item gear;
/** "brass","iron","thaumium","void"*/
public static Item plate;
public static Item voidSeed;
public static Item salisMundus;
public static Item mirroredGlass;
public static Item primalCharm;
public static Item phial;
public static Item label;
public static Item filter;
/** "clockwork","biothaumic" */
public static Item mind;
public static Item morphicResonator;
//consumables
public static Item alumentum;
public static Item brain;
/** "beef","chicken","pork","fish","rabbit","mutton"*/
public static Item chunks;
public static Item tripleMeatTreat;
public static Item bucketDeath;
public static Item bucketPure;
public static Item bottleTaint;
public static Item bathSalts;
public static Item sanitySoap;
/** "basic","focus","magnet"*/
public static Item turretPlacer;
//armor
public static Item goggles;
public static Item travellerBoots;
public static Item thaumiumHelm;
public static Item thaumiumChest;
public static Item thaumiumLegs;
public static Item thaumiumBoots;
public static Item clothChest;
public static Item clothLegs;
public static Item clothBoots;
public static Item fortressHelm;
public static Item fortressChest;
public static Item fortressLegs;
public static Item voidHelm;
public static Item voidChest;
public static Item voidLegs;
public static Item voidBoots;
public static Item voidRobeHelm;
public static Item voidRobeChest;
public static Item voidRobeLegs;
public static Item crimsonBoots;
public static Item crimsonPlateHelm;
public static Item crimsonPlateChest;
public static Item crimsonPlateLegs;
public static Item crimsonRobeHelm;
public static Item crimsonRobeChest;
public static Item crimsonRobeLegs;
public static Item crimsonPraetorHelm;
public static Item crimsonPraetorChest;
public static Item crimsonPraetorLegs;
public static Item thaumostaticHarness;
//tools
public static Item thaumometer;
public static Item thaumonomicon;
public static Item resonator;
public static Item sinisterStone;
public static Item sanityChecker;
public static Item thaumiumAxe;
public static Item thaumiumSword;
public static Item thaumiumShovel;
public static Item thaumiumPick;
public static Item thaumiumHoe;
public static Item elementalAxe;
public static Item elementalSword;
public static Item elementalShovel;
public static Item elementalPick;
public static Item elementalHoe;
public static Item voidAxe;
public static Item voidSword;
public static Item voidShovel;
public static Item voidPick;
public static Item voidHoe;
public static Item crimsonBlade;
public static Item primalCrusher;
public static Item boneBow;
public static Item primalArrows;
public static Item handMirror;
//wand
public static Item wand;
/** iron, gold, brass, thaumium_inert, thaumium_charged, void_inert, void_charged*/
public static Item wandCaps;
/** greatwood, silverwood, obsidian, blaze, ice, quartz, bone, reed,
* greatwood_staff, silverwood_staff, obsidian_staff, blaze_staff, ice_staff,
* quartz_staff, bone_staff, reed_staff, primal_staff */
public static Item wandRods;
public static Item focusEqualTrade;
public static Item focusFire;
public static Item focusFrost;
public static Item focusPech;
public static Item focusExcavation;
public static Item focusHellbat;
public static Item focusPrimal;
public static Item focusShock;
public static Item focusWarding;
public static Item focusHole;
public static Item focusShard;
public static Item focusPouch;
//baubles
/** "amulet_mundane","ring_mundane","girdle_mundane","ring_apprentice"*/
public static Item baubles;
public static Item amuletRunic;
public static Item ringRunic;
public static Item girdleRunic;
public static Item amuletVis;
public static Item girdleHover;
//misc
/** "slime","tendril"*/
public static Item tainted;
public static Item knowledgeFragment;
public static Item coin;
public static Item wispyEssence;
public static Item crystalEssence;
public static Item primordialPearl;
public static Item researchNotes;
public static Item scribingTools;
public static Item lootBag;
public static Item eldritchEye;
public static Item crimsonRites;
public static Item runedTablet;
public static Item creativePlacer;
//golems
public static Item golemBell;
public static Item golemPlacer;
/** "blank","pickup","fill","fill_advanced","empty","empty_advanced" */
public static Item seals;
}

View file

@ -0,0 +1,5 @@
@API(owner = "Thaumcraft", apiVersion = "5.0.0.4", provides = "Thaumcraft|API")
package thaumcraft.api;
import net.minecraftforge.fml.common.API;

View file

@ -0,0 +1,67 @@
package thaumcraft.api.potions;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.potion.Potion;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import thaumcraft.api.damagesource.DamageSourceThaumcraft;
import thaumcraft.api.entities.ITaintedMob;
public class PotionFluxTaint extends Potion
{
public static PotionFluxTaint instance = null; // will be instantiated at runtime
private int statusIconIndex = -1;
public PotionFluxTaint(int par1, boolean par2, int par3)
{
super(par1,new ResourceLocation("flux_taint"),par2,par3);
setIconIndex(0, 0);
}
public static void init()
{
instance.setPotionName("potion.fluxtaint");
instance.setIconIndex(3, 1);
instance.setEffectiveness(0.25D);
}
@Override
public boolean isBadEffect() {
return true;
}
@Override
@SideOnly(Side.CLIENT)
public int getStatusIconIndex() {
Minecraft.getMinecraft().renderEngine.bindTexture(rl);
return super.getStatusIconIndex();
}
static final ResourceLocation rl = new ResourceLocation("thaumcraft","textures/misc/potions.png");
@Override
public void performEffect(EntityLivingBase target, int par2) {
if (target instanceof ITaintedMob) {
target.heal(1);
} else
if (!target.isEntityUndead() && !(target instanceof EntityPlayer))
{
target.attackEntityFrom(DamageSourceThaumcraft.taint, 1);
}
else
if (!target.isEntityUndead() && (target.getMaxHealth() > 1 || (target instanceof EntityPlayer)))
{
target.attackEntityFrom(DamageSourceThaumcraft.taint, 1);
}
}
public boolean isReady(int par1, int par2)
{
int k = 40 >> par2;
return k > 0 ? par1 % k == 0 : true;
}
}

View file

@ -0,0 +1,48 @@
package thaumcraft.api.potions;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.potion.Potion;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class PotionVisExhaust extends Potion
{
public static PotionVisExhaust instance = null; // will be instantiated at runtime
private int statusIconIndex = -1;
public PotionVisExhaust(int par1, boolean par2, int par3)
{
super(par1,new ResourceLocation("vis_exhaust"),par2,par3);
setIconIndex(0, 0);
}
public static void init()
{
instance.setPotionName("potion.visexhaust");
instance.setIconIndex(5, 1);
instance.setEffectiveness(0.25D);
}
@Override
public boolean isBadEffect() {
return true;
}
@Override
@SideOnly(Side.CLIENT)
public int getStatusIconIndex() {
Minecraft.getMinecraft().renderEngine.bindTexture(rl);
return super.getStatusIconIndex();
}
static final ResourceLocation rl = new ResourceLocation("thaumcraft","textures/misc/potions.png");
@Override
public void performEffect(EntityLivingBase target, int par2) {
}
}

View file

@ -0,0 +1,23 @@
package thaumcraft.api.research;
import net.minecraft.entity.player.EntityPlayer;
public interface IScanThing {
/**
* The passed in obj can either be an Entity, a BlockPos, an Itemstack, or a null if nothing was actually clicked on.
* You could then probably use the players lookvec to do whatever you want.
* @param player
* @param obj
* @return the research key that will be unlocked if the object is scanned.
* This need not be an actual defined research item - any text string will do.
* You can then use this research key (fake or otherwise) as a parent for research or for whatever.
*/
public boolean checkThing(EntityPlayer player, Object obj);
/**
* @return the research linked to this 'thing'
*/
public String getResearchKey();
}

View file

@ -0,0 +1,117 @@
package thaumcraft.api.research;
import java.util.Collection;
import java.util.LinkedHashMap;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.logging.log4j.Level;
public class ResearchCategories {
//Research
public static LinkedHashMap <String, ResearchCategoryList> researchCategories = new LinkedHashMap <String,ResearchCategoryList>();
/**
* @param key
* @return the research item linked to this key
*/
public static ResearchCategoryList getResearchList(String key) {
return researchCategories.get(key);
}
/**
* @param key
* @return the name of the research category linked to this key.
* Must be stored as localization information in the LanguageRegistry.
*/
public static String getCategoryName(String key) {
return StatCollector.translateToLocal("tc.research_category."+key);
}
/**
* @param key the research key
* @return the ResearchItem object.
*/
public static ResearchItem getResearch(String key) {
Collection rc = researchCategories.values();
for (Object cat:rc) {
Collection rl = ((ResearchCategoryList)cat).research.values();
for (Object ri:rl) {
if ((((ResearchItem)ri).key).equals(key)) return (ResearchItem)ri;
}
}
return null;
}
/**
* This should only be done at the PostInit stage
* @param key the key used for this category
* @param researchkey the research that the player needs to have completed before this category becomes visible. Set as null to always show.
* @param icon the icon to be used for the research category tab
* @param background the resource location of the background image to use for this category
* @return the name of the research linked to this key
*/
public static void registerCategory(String key, String researchkey, ResourceLocation icon, ResourceLocation background) {
if (getResearchList(key)==null) {
ResearchCategoryList rl = new ResearchCategoryList(researchkey, icon, background);
researchCategories.put(key, rl);
}
}
/**
* This should only be done at the PostInit stage
* @param key the key used for this category
* @param researchkey the research that the player needs to have completed before this category becomes visible. Set as null to always show.
* @param icon the icon to be used for the research category tab
* @param background the resource location of the background image to use for this category
* @param background2 the resource location of the foreground image that lies between the background and icons
* @return the name of the research linked to this key
*/
public static void registerCategory(String key, String researchkey, ResourceLocation icon, ResourceLocation background, ResourceLocation background2) {
if (getResearchList(key)==null) {
ResearchCategoryList rl = new ResearchCategoryList(researchkey, icon, background, background2);
researchCategories.put(key, rl);
}
}
public static void addResearch(ResearchItem ri) {
ResearchCategoryList rl = getResearchList(ri.category);
if (rl!=null && !rl.research.containsKey(ri.key)) {
if (!ri.isVirtual()) {
for (ResearchItem rr:rl.research.values()) {
if (rr.displayColumn == ri.displayColumn && rr.displayRow == ri.displayRow) {
FMLLog.log(Level.FATAL, "[Thaumcraft] Research ["+ri.getName()+"] not added as it overlaps with existing research ["+rr.getName()+"]");
return;
}
}
}
rl.research.put(ri.key, ri);
if (ri.displayColumn < rl.minDisplayColumn)
{
rl.minDisplayColumn = ri.displayColumn;
}
if (ri.displayRow < rl.minDisplayRow)
{
rl.minDisplayRow = ri.displayRow;
}
if (ri.displayColumn > rl.maxDisplayColumn)
{
rl.maxDisplayColumn = ri.displayColumn;
}
if (ri.displayRow > rl.maxDisplayRow)
{
rl.maxDisplayRow = ri.displayRow;
}
}
}
}

View file

@ -0,0 +1,50 @@
package thaumcraft.api.research;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.util.ResourceLocation;
public class ResearchCategoryList {
/** Is the smallest column used on the GUI. */
public int minDisplayColumn;
/** Is the smallest row used on the GUI. */
public int minDisplayRow;
/** Is the biggest column used on the GUI. */
public int maxDisplayColumn;
/** Is the biggest row used on the GUI. */
public int maxDisplayRow;
/** display variables **/
public ResourceLocation icon;
public ResourceLocation background;
public ResourceLocation background2;
public String researchKey;
public ResearchCategoryList(String researchKey, ResourceLocation icon, ResourceLocation background) {
this.researchKey = researchKey;
this.icon = icon;
this.background = background;
this.background2 = null;
}
public ResearchCategoryList(String researchKey, ResourceLocation icon, ResourceLocation background, ResourceLocation background2) {
this.researchKey = researchKey;
this.icon = icon;
this.background = background;
this.background2 = background2;
}
//Research
public Map<String, ResearchItem> research = new HashMap<String,ResearchItem>();
}

View file

@ -0,0 +1,42 @@
package thaumcraft.api.research;
import net.minecraft.entity.player.EntityPlayer;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.internal.EnumWarpType;
public class ResearchHelper {
public static boolean completeResearch(EntityPlayer player, String researchkey) {
return ThaumcraftApi.internalMethods.completeResearch(player, researchkey);
}
public static boolean isResearchComplete(String username, String[] researchkeys) {
for (String key:researchkeys) if (!ResearchHelper.isResearchComplete(username, key)) return false;
return true;
}
public static boolean isResearchComplete(String username, String researchkey) {
return ThaumcraftApi.internalMethods.isResearchComplete(username, researchkey);
}
/**
* This adds warp to a player. It will automatically be synced clientside
* @param player the player using the wand
* @param amount how much warp to add. Negative amounts are only valid for temporary warp
* @param type the type of warp to be added
*/
public static void addWarpToPlayer(EntityPlayer player, int amount, EnumWarpType type) {
ThaumcraftApi.internalMethods.addWarpToPlayer(player, amount, type);
}
/**
* This retrieves how much warp the player has
* @param player the player using the wand
* @param type the type of warp to retrieve
* @return how much warp the player has
*/
public static int getPlayerWarp(EntityPlayer player, EnumWarpType type) {
return ThaumcraftApi.internalMethods.getPlayerWarp(player, type);
}
}

View file

@ -0,0 +1,303 @@
package thaumcraft.api.research;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class ResearchItem
{
/**
* A short string used as a key for this research. Must be unique
*/
public final String key;
/**
* A short string used as a reference to the research category to which this must be added.
*/
public final String category;
/**
* The aspect tags and their values required to complete this research *
*/
public final AspectList tags;
/**
* This links to any research that needs to be completed before this research can be discovered or learnt.
*/
public String[] parents = null;
/**
* Like parent above, but a line will not be displayed in the thaumonomicon linking them. Just used to prevent clutter.
*/
public String[] parentsHidden = null;
/**
* any research linked to this that will be unlocked automatically when this research is complete
*/
public String[] siblings = null;
/**
* the horizontal position of the research icon
*/
public final int displayColumn;
/**
* the vertical position of the research icon
*/
public final int displayRow;
/**
* the icon to be used for this research
*/
public final ItemStack[] icon_item;
/**
* the icon to be used for this research
*/
public final ResourceLocation[] icon_resource;
/**
* How large the research grid is. Valid values are 1 to 3.
*/
private int complexity;
/**
* Special research has a spiky border. Used for important research milestones.
*/
private boolean isSpecial;
/**
* Research that can be directly purchased with knowledge fragments
*/
private boolean isSecondary;
/**
* This indicates if the research should use a circular icon border. Usually used for "passive" research
* that doesn't have recipes and grants passive effects, or that unlock automatically.
*/
private boolean isRound;
/**
* Stub research cannot be discovered by normal means, but can be unlocked via the sibling system.
*/
private boolean isStub;
/**
* This indicated that the research is completely hidden and cannot be discovered by any
* player-controlled means. The recipes will never show up in the thaumonomicon.
* Usually used to unlock "hidden" recipes via sibling unlocking, like
* the various cap and rod combos for wands.
*/
private boolean isVirtual;
/**
* Concealed research does not display in the thaumonomicon until parent researches are discovered.
* Often times some of the parent researches is linked to scanned objects.
*/
private boolean isHidden;
/**
* These research items will automatically unlock for all players on game start
*/
private boolean isAutoUnlock;
/**
* Flip the way the connecting lines are drawn in the research browser.
*/
private boolean isFlipped;
private ResearchPage[] pages = null;
public ResearchItem(String key, String category)
{
this.key = key;
this.category = category;
this.tags = new AspectList();
this.icon_resource = null;
this.icon_item = null;
this.displayColumn = 0;
this.displayRow = 0;
this.isVirtual = true;
}
public ResearchItem(String key, String category, AspectList tags, int col, int row, int complex, Object ... icon)
{
this.key = key;
this.category = category;
this.tags = tags;
if (icon[0] instanceof ResourceLocation) {
ResourceLocation[] t = new ResourceLocation[icon.length];
System.arraycopy(icon, 0, t, 0, icon.length);
this.icon_resource = t;
} else this.icon_resource = null;
if (icon[0] instanceof ItemStack) {
ItemStack[] t = new ItemStack[icon.length];
System.arraycopy(icon, 0, t, 0, icon.length);
this.icon_item = t;
} else this.icon_item = null;
this.displayColumn = col;
this.displayRow = row;
this.complexity = complex;
if (complexity < 1) this.complexity = 1;
if (complexity > 3) this.complexity = 3;
}
public ResearchItem setSpecial()
{
this.isSpecial = true;
return this;
}
public ResearchItem setStub()
{
this.isStub = true;
return this;
}
public ResearchItem setHidden()
{
this.isHidden = true;
return this;
}
public ResearchItem setParents(String... par)
{
this.parents = par;
return this;
}
public ResearchItem setParentsHidden(String... par)
{
this.parentsHidden = par;
return this;
}
public ResearchItem setSiblings(String... sib)
{
this.siblings = sib;
return this;
}
public ResearchItem setPages(ResearchPage... par)
{
this.pages = par;
return this;
}
public ResearchPage[] getPages() {
return pages;
}
public ResearchItem registerResearchItem()
{
ResearchCategories.addResearch(this);
return this;
}
public String getName()
{
return StatCollector.translateToLocal("tc.research_name."+key);
}
public String getText()
{
return StatCollector.translateToLocal("tc.research_text."+key);
}
public boolean isSpecial()
{
return this.isSpecial;
}
public boolean isStub()
{
return this.isStub;
}
public boolean isHidden()
{
return this.isHidden;
}
public boolean isVirtual()
{
return this.isVirtual;
}
public boolean isAutoUnlock() {
return isAutoUnlock;
}
public ResearchItem setAutoUnlock()
{
this.isAutoUnlock = true;
return this;
}
public boolean isRound() {
return isRound;
}
public ResearchItem setRound() {
this.isRound = true;
return this;
}
public ResearchItem setSecondary()
{
this.isSecondary = true;
return this;
}
public boolean isSecondary() {
return isSecondary;
}
public int getComplexity() {
return complexity;
}
public ResearchItem setFlipped() {
this.isFlipped = true;
return this;
}
public boolean isFlipped() {
return this.isFlipped;
}
public ResearchItem setComplexity(int complexity) {
this.complexity = complexity;
return this;
}
public int getExperience() {
if (this.tags!=null && this.tags.visSize()>0) {
return Math.max(1, (int) Math.sqrt(this.tags.visSize()));
} else
return 0;
}
/**
* @return the aspect aspects ordinal with the highest value. Used to determine scroll color and similar things
*/
public Aspect getResearchPrimaryTag() {
Aspect aspect=null;
int highest=0;
if (tags!=null)
for (Aspect tag:tags.getAspects()) {
if (tags.getAmount(tag)>highest) {
aspect=tag;
highest=tags.getAmount(tag);
};
}
return aspect;
}
}

View file

@ -0,0 +1,183 @@
package thaumcraft.api.research;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import thaumcraft.api.aspects.AspectList;
import thaumcraft.api.crafting.CrucibleRecipe;
import thaumcraft.api.crafting.IArcaneRecipe;
import thaumcraft.api.crafting.InfusionEnchantmentRecipe;
import thaumcraft.api.crafting.InfusionRecipe;
public class ResearchPage {
public static enum PageType
{
TEXT,
IMAGE,
CRUCIBLE_CRAFTING,
ARCANE_CRAFTING,
ASPECTS,
NORMAL_CRAFTING,
INFUSION_CRAFTING,
COMPOUND_CRAFTING,
INFUSION_ENCHANTMENT,
SMELTING
}
public PageType type = PageType.TEXT;
public String text=null;
public String research=null;
public ResourceLocation image=null;
public AspectList aspects=null;
public Object recipe=null;
public Object recipeOutput=null;
/**
* @param text this can (but does not have to) be a reference to a localization variable, not the actual text.
*/
public ResearchPage(String text) {
this.type = PageType.TEXT;
this.text = text;
}
/**
* @param recipe a vanilla crafting recipe.
*/
public ResearchPage(IRecipe recipe) {
this.type = PageType.NORMAL_CRAFTING;
this.recipe = recipe;
this.recipeOutput = recipe.getRecipeOutput();
}
/**
* @param recipe a collection of vanilla crafting recipes.
*/
public ResearchPage(IRecipe[] recipe) {
this.type = PageType.NORMAL_CRAFTING;
this.recipe = recipe;
}
/**
* @param recipe a collection of arcane crafting recipes.
*/
public ResearchPage(IArcaneRecipe[] recipe) {
this.type = PageType.ARCANE_CRAFTING;
this.recipe = recipe;
}
/**
* @param recipe a collection of arcane crafting recipes.
*/
public ResearchPage(CrucibleRecipe[] recipe) {
this.type = PageType.CRUCIBLE_CRAFTING;
this.recipe = recipe;
}
/**
* @param recipe a collection of infusion crafting recipes.
*/
public ResearchPage(InfusionRecipe[] recipe) {
this.type = PageType.INFUSION_CRAFTING;
this.recipe = recipe;
}
/**
* @param recipe a compound crafting recipe.
*/
public ResearchPage(List recipe) {
this.type = PageType.COMPOUND_CRAFTING;
this.recipe = recipe;
}
/**
* @param recipe an arcane worktable crafting recipe.
*/
public ResearchPage(IArcaneRecipe recipe) {
this.type = PageType.ARCANE_CRAFTING;
this.recipe = recipe;
this.recipeOutput = recipe.getRecipeOutput();
}
/**
* @param recipe an alchemy crafting recipe.
*/
public ResearchPage(CrucibleRecipe recipe) {
this.type = PageType.CRUCIBLE_CRAFTING;
this.recipe = recipe;
this.recipeOutput = recipe.getRecipeOutput();
}
/**
* @param recipe a furnace smelting crafting recipe.
*/
public ResearchPage(ItemStack input) {
this.type = PageType.SMELTING;
this.recipe = input;
this.recipeOutput = FurnaceRecipes.instance().getSmeltingResult(input);
}
/**
* @param recipe an infusion crafting recipe.
*/
public ResearchPage(InfusionRecipe recipe) {
this.type = PageType.INFUSION_CRAFTING;
this.recipe = recipe;
if (recipe.getRecipeOutput() instanceof ItemStack) {
this.recipeOutput = (ItemStack) recipe.getRecipeOutput();
} else {
this.recipeOutput = recipe.getRecipeInput();
}
}
/**
* @param recipe an infusion crafting recipe.
*/
public ResearchPage(InfusionEnchantmentRecipe recipe) {
this.type = PageType.INFUSION_ENCHANTMENT;
this.recipe = recipe;
}
/**
* @param image
* @param caption this can (but does not have to) be a reference to a localization variable, not the actual text.
*/
public ResearchPage(ResourceLocation image, String caption) {
this.type = PageType.IMAGE;
this.image = image;
this.text = caption;
}
/**
* This function should really not be called directly - used internally
*/
public ResearchPage(AspectList as) {
this.type = PageType.ASPECTS;
this.aspects = as;
}
/**
* returns a localized text of the text field (if one exists). Returns the text field itself otherwise.
* @return
*/
public String getTranslatedText() {
String ret="";
if (text != null) {
ret = StatCollector.translateToLocal(text);
if (ret.isEmpty()) ret = text;
}
return ret;
}
/**
* This page will only be shown if this research is unlocked
*/
public ResearchPage setRequisite(String research) {
this.research = research;
return this;
}
}

View file

@ -0,0 +1,61 @@
package thaumcraft.api.research;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectHelper;
import thaumcraft.api.aspects.AspectList;
public class ScanAspect implements IScanThing {
String research;
Aspect aspect;
/**
* NOTE: You should not have to add your own entry for aspects since a trigger research is added automatically for each aspect in the format "![tagname]"
* for example: "!vitium"
*/
public ScanAspect(String research, Aspect aspect) {
this.research = research;
this.aspect = aspect;
}
@Override
public boolean checkThing(EntityPlayer player, Object obj) {
if (obj == null) return false;
AspectList al = null;
if (obj instanceof Entity && !(obj instanceof EntityItem)) {
al = AspectHelper.getEntityAspects((Entity) obj);
} else {
ItemStack is = null;
if (obj instanceof ItemStack)
is = (ItemStack) obj;
if (obj instanceof EntityItem && ((EntityItem)obj).getEntityItem()!=null)
is = ((EntityItem)obj).getEntityItem();
if (obj instanceof BlockPos) {
Block b = player.worldObj.getBlockState((BlockPos) obj).getBlock();
is = new ItemStack(b,1,b.getMetaFromState(player.worldObj.getBlockState((BlockPos) obj)));
}
if (is!=null) {
al = AspectHelper.getObjectAspects(is);
}
}
return al!=null && al.getAmount(aspect)>0;
}
@Override
public String getResearchKey() {
return research;
}
}

View file

@ -0,0 +1,30 @@
package thaumcraft.api.research;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.BlockPos;
public class ScanBlock implements IScanThing {
String research;
Block block;
public ScanBlock(String research, Block block) {
this.research = research;
this.block = block;
}
@Override
public boolean checkThing(EntityPlayer player, Object obj) {
if (obj!=null && obj instanceof BlockPos && player.worldObj.getBlockState((BlockPos) obj).getBlock()==block) {
return true;
}
return false;
}
@Override
public String getResearchKey() {
return research;
}
}

View file

@ -0,0 +1,38 @@
package thaumcraft.api.research;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
public class ScanBlockState implements IScanThing {
String research;
IBlockState blockState;
public ScanBlockState(String research, IBlockState blockState) {
this.research = research;
this.blockState = blockState;
}
public ScanBlockState(String research, IBlockState blockState, boolean item) {
this.research = research;
this.blockState = blockState;
if (item)
ScanningManager.addScannableThing(new ScanItem(research,
new ItemStack(blockState.getBlock(),1,blockState.getBlock().getMetaFromState(blockState))));
}
@Override
public boolean checkThing(EntityPlayer player, Object obj) {
if (obj!=null && obj instanceof BlockPos && player.worldObj.getBlockState((BlockPos) obj)==blockState) {
return true;
}
return false;
}
@Override
public String getResearchKey() {
return research;
}
}

View file

@ -0,0 +1,57 @@
package thaumcraft.api.research;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import thaumcraft.api.ThaumcraftApi.EntityTagsNBT;
import thaumcraft.api.ThaumcraftApiHelper;
public class ScanEntity implements IScanThing {
String research;
Class entityClass;
EntityTagsNBT[] NBTData;
/**
* false if the specific entity class should be used, or true if anything the inherits from that class is also allowed.
*/
boolean inheritedClasses=false;
public ScanEntity(String research, Class entityClass, boolean inheritedClasses) {
this.research = research;
this.entityClass = entityClass;
this.inheritedClasses = inheritedClasses;
}
public ScanEntity(String research, Class entityClass, boolean inheritedClasses, EntityTagsNBT... nbt) {
this.research = research;
this.entityClass = entityClass;
this.inheritedClasses = inheritedClasses;
this.NBTData = nbt;
}
@Override
public boolean checkThing(EntityPlayer player, Object obj) {
if (obj!=null && ((!inheritedClasses && entityClass==obj.getClass()) ||
(inheritedClasses && entityClass.isInstance(obj)))) {
if (NBTData!=null && NBTData.length>0) {
boolean b = true;
NBTTagCompound tc = new NBTTagCompound();
((Entity)obj).writeToNBT(tc);
for (EntityTagsNBT nbt:NBTData) {
if (!tc.hasKey(nbt.name) || !ThaumcraftApiHelper.getNBTDataFromId(tc, tc.getTagId(nbt.name), nbt.name).equals(nbt.value)) {
return false;
}
}
}
return true;
}
return false;
}
@Override
public String getResearchKey() {
return research;
}
}

View file

@ -0,0 +1,37 @@
package thaumcraft.api.research;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import thaumcraft.api.ThaumcraftApiHelper;
public class ScanItem implements IScanThing {
String research;
ItemStack stack;
public ScanItem(String research, ItemStack stack) {
this.research = research;
this.stack = stack;
}
@Override
public boolean checkThing(EntityPlayer player, Object obj) {
if (obj == null) return false;
ItemStack is = null;
if (obj instanceof ItemStack)
is = (ItemStack) obj;
if (obj instanceof EntityItem && ((EntityItem)obj).getEntityItem()!=null)
is = ((EntityItem)obj).getEntityItem();
return is!=null && ThaumcraftApiHelper.areItemStacksEqualForCrafting(is, stack);
}
@Override
public String getResearchKey() {
return research;
}
}

View file

@ -0,0 +1,58 @@
package thaumcraft.api.research;
import java.util.ArrayList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.StatCollector;
public class ScanningManager {
static ArrayList<IScanThing> things = new ArrayList<IScanThing>();
/**
* Add things to scan
* @example
* <i>ScanManager.addScannableThing(new ScanItem("HIPSTER",new ItemStack(Items.apple,1,OreDictionary.WILDCARD_VALUE)));</i><br>
* This will unlock the <b>HIPSTER</b> research if you scan any kind of apple.
*/
public static void addScannableThing(IScanThing obj) {
things.add(obj);
}
/**
*
* @param player
* @param object this could in theory be anything, but vanilla tc scanning tools only pass in Entity, BlockPos, Itemstack or null
*/
public static void scanTheThing(EntityPlayer player, Object object) {
boolean found = false;
for (IScanThing thing:things) {
if (thing.checkThing(player, object)) {
if (ResearchHelper.completeResearch(player, thing.getResearchKey())) {
found=true;
}
}
}
if (!found) {
player.addChatMessage(new ChatComponentText("\u00a75\u00a7o"+StatCollector.translateToLocal("tc.unknownobject")));
}
}
/**
* @param player
* @param object
* @return true if the object can be scanned for research the player has not yet discovered
*/
public static boolean isThingStillScannable(EntityPlayer player, Object object) {
for (IScanThing thing:things) {
if (thing.checkThing(player, object)) {
if (!ResearchHelper.isResearchComplete(player.getName(), thing.getResearchKey())) {
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,107 @@
package thaumcraft.api.wands;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class FocusUpgradeType {
public static FocusUpgradeType[] types = new FocusUpgradeType[20];
public short id;
public ResourceLocation icon;
public String name;
public String text;
/**
* What aspects are used to calculate the cost of this upgrade. The amounts given is ignored, just the type is used for the calculation.
*/
public AspectList aspects;
private static int lastID = 0;
public FocusUpgradeType(ResourceLocation icon, String name, String text, AspectList aspects) {
this.id = (short) lastID;
lastID++;
this.icon = icon;
this.name = name;
this.text = text;
this.aspects = aspects;
// allocate space
if (id>=types.length) {
FocusUpgradeType[] temp = new FocusUpgradeType[id+1];
System.arraycopy(types, 0, temp, 0, types.length);
types = temp;
}
types[id] = this;
}
public String getLocalizedName() {
return StatCollector.translateToLocal(name);
}
public String getLocalizedText() {
return StatCollector.translateToLocal(text);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FocusUpgradeType) {
return this.id == ((FocusUpgradeType)obj).id;
} else return false;
}
// basic upgrade types
public static FocusUpgradeType potency = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/potency.png"),
"focus.upgrade.potency.name","focus.upgrade.potency.text",
new AspectList().add(Aspect.AVERSION,1));
public static FocusUpgradeType frugal = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/frugal.png"),
"focus.upgrade.frugal.name","focus.upgrade.frugal.text",
new AspectList().add(Aspect.DESIRE,1));
public static FocusUpgradeType treasure = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/treasure.png"),
"focus.upgrade.treasure.name","focus.upgrade.treasure.text",
new AspectList().add(Aspect.DESIRE,1));
public static FocusUpgradeType enlarge = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/enlarge.png"),
"focus.upgrade.enlarge.name","focus.upgrade.enlarge.text",
new AspectList().add(Aspect.MOTION,1));
public static FocusUpgradeType alchemistsfire = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/alchemistsfire.png"),
"focus.upgrade.alchemistsfire.name","focus.upgrade.alchemistsfire.text",
new AspectList().add(Aspect.ENERGY,1).add(Aspect.WATER,1));
public static FocusUpgradeType alchemistsfrost = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/alchemistsfrost.png"),
"focus.upgrade.alchemistsfrost.name","focus.upgrade.alchemistsfrost.text",
new AspectList().add(Aspect.COLD,1).add(Aspect.TRAP,1));
public static FocusUpgradeType architect = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/architect.png"),
"focus.upgrade.architect.name","focus.upgrade.architect.text",
new AspectList().add(Aspect.CRAFT,1));
public static FocusUpgradeType extend = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/extend.png"),
"focus.upgrade.extend.name","focus.upgrade.extend.text",
new AspectList().add(Aspect.EXCHANGE,1));
public static FocusUpgradeType silktouch = new FocusUpgradeType(
new ResourceLocation("thaumcraft", "textures/foci/silktouch.png"),
"focus.upgrade.silktouch.name","focus.upgrade.silktouch.text",
new AspectList().add(Aspect.DESIRE,1));
}

View file

@ -0,0 +1,54 @@
package thaumcraft.api.wands;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public interface IWand {
public abstract int getMaxVis(ItemStack stack);
public abstract int getVis(ItemStack is, Aspect aspect);
public abstract AspectList getAllVis(ItemStack is);
public abstract AspectList getAspectsWithRoom(ItemStack wandstack);
public abstract float getConsumptionModifier(ItemStack is, EntityPlayer player, Aspect aspect, boolean crafting);
public abstract boolean consumeVis(ItemStack is, EntityPlayer player, Aspect aspect, int amount, boolean crafting);
public abstract boolean consumeAllVis(ItemStack is, EntityPlayer player, AspectList aspects, boolean doit, boolean crafting);
public abstract int addVis(ItemStack is, Aspect aspect, int amount, boolean doit);
public abstract ItemFocusBasic getFocus(ItemStack stack);
public abstract ItemStack getFocusStack(ItemStack stack);
public abstract void setFocus(ItemStack stack, ItemStack focus);
public abstract WandRod getRod(ItemStack stack);
public abstract boolean isStaff(ItemStack stack);
public abstract boolean isSceptre(ItemStack stack);
public abstract void setRod(ItemStack stack, WandRod rod);
public abstract WandCap getCap(ItemStack stack);
public abstract void setCap(ItemStack stack, WandCap cap);
public abstract int getFocusPotency(ItemStack itemstack);
public abstract int getFocusTreasure(ItemStack itemstack);
public abstract int getFocusFrugal(ItemStack itemstack);
public abstract int getFocusEnlarge(ItemStack itemstack);
public abstract int getFocusExtend(ItemStack itemstack);
}

View file

@ -0,0 +1,16 @@
package thaumcraft.api.wands;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
/**
*
* @author azanor
*
* Implemented by a class that you wish to be called whenever a wand with this rod performs its
* update tick.
*
*/
public interface IWandRodOnUpdate {
void onUpdate(ItemStack itemstack, EntityPlayer player);
}

View file

@ -0,0 +1,17 @@
package thaumcraft.api.wands;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
public interface IWandTriggerManager {
/**
* This class will be called by wands with the proper parameters. It is up to you to decide what to do with them.
*/
public boolean performTrigger(World world, ItemStack wand, EntityPlayer player,
BlockPos pos, EnumFacing side, int event);
}

View file

@ -0,0 +1,25 @@
package thaumcraft.api.wands;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
/**
*
* @author azanor
*
* Add this to a tile entity that you wish wands to interact with in some way.
*
*/
public interface IWandable {
public boolean onWandRightClick(World world, ItemStack wandstack, EntityPlayer player, BlockPos pos, EnumFacing side);
public void onUsingWandTick(ItemStack wandstack, EntityPlayer player, int count);
public void onWandStoppedUsing(ItemStack wandstack, World world, EntityPlayer player, int count);
}

View file

@ -0,0 +1,313 @@
package thaumcraft.api.wands;
import java.text.DecimalFormat;
import java.util.LinkedHashMap;
import java.util.List;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class ItemFocusBasic extends Item {
public ItemFocusBasic (String id, ResourceLocation texture, int renderColor)
{
super();
maxStackSize = 1;
canRepair=false;
this.setMaxDamage(0);
this.id = id;
this.texture = texture;
foci.put(id, this);
this.focusColor = renderColor;
}
public ItemFocusBasic (String id, int renderColor)
{
this(id,new ResourceLocation("thaumcraft","items/wand/focus"), renderColor);
}
public static LinkedHashMap<String,ItemFocusBasic> foci = new LinkedHashMap<String,ItemFocusBasic>();
/**
* Unique identifier used for this focus
*/
private String id;
public String getFocusId() {
return id;
}
/**
* Texture used to render the cap on the wand
*/
private ResourceLocation texture;
public ResourceLocation getFocusTexture() {
return texture;
}
/**
* What color the focus will be rendered ingame on the wand
*/
private int focusColor=0;
/**
* What color will the focus orb be rendered on the held wand
*/
public int getFocusColor(ItemStack focusstack) {
return this.focusColor;
}
@Override
public boolean isDamageable() {
return false;
}
public boolean canBePlacedInTurret() {
return false;
}
/**
* This is used to correct for foci that shoot projectiles effected by gravity.
* The number will be modified by range to the target
* @return a number to add to the angle the turrent aims at.
*/
public float getTurretCorrection(ItemStack focusstack) {
return 0;
}
/**
* @return the possible range of the attack - if the entity is outside this range the turret will not attempt to attack it. Values higher than 32 will have no effect
*/
public float getTurretRange(ItemStack focusstack) {
return 32;
}
@Override
public void addInformation(ItemStack stack,EntityPlayer player, List list, boolean par4) {
AspectList al = this.getVisCost(stack);
if (al!=null && al.size()>0) {
list.add(StatCollector.translateToLocal(isVisCostPerTick(stack)?"item.Focus.cost2":"item.Focus.cost1"));
for (Aspect aspect:al.getAspectsSortedByName()) {
DecimalFormat myFormatter = new DecimalFormat("#####.##");
String amount = myFormatter.format(al.getAmount(aspect));
list.add(" \u00A7"+aspect.getChatcolor()+aspect.getName()+"\u00A7r x "+ amount);
}
}
addFocusInformation(stack,player,list,par4);
}
public void addFocusInformation(ItemStack focusstack,EntityPlayer player, List list, boolean par4) {
LinkedHashMap<Short, Integer> map = new LinkedHashMap<Short, Integer>();
for (short id:this.getAppliedUpgrades(focusstack)) {
if (id>=0) {
int amt = 1;
if (map.containsKey(id)) {
amt = map.get(id) + 1;
}
map.put(id, amt);
}
}
for (Short id:map.keySet()) {
list.add(EnumChatFormatting.DARK_PURPLE +FocusUpgradeType.types[id].getLocalizedName()+
(map.get(id)>1?" "+StatCollector.translateToLocal("enchantment.level." + map.get(id)):""));
}
}
/**
* Purely for display on the focus tooltip (see addInformation method above)
*/
public boolean isVisCostPerTick(ItemStack focusstack) {
return false;
}
@Override
public EnumRarity getRarity(ItemStack focusstack)
{
return EnumRarity.RARE;
}
public enum WandFocusAnimation {
WAVE, CHARGE;
}
public WandFocusAnimation getAnimation(ItemStack focusstack) {
return WandFocusAnimation.WAVE;
}
/**
* Just insert two alphanumeric characters before this string in your focus item class
*/
public String getSortingHelper(ItemStack focusstack) {
String out=this.id;
for (short id:this.getAppliedUpgrades(focusstack)) {
out = out + id;
}
return out;
}
/**
* How much vis does this focus consume per activation.
*/
public AspectList getVisCost(ItemStack focusstack) {
return null;
}
/**
* This returns how many milliseconds must pass before the focus can be activated again.
*/
public int getActivationCooldown(ItemStack focusstack) {
return 0;
}
/**
* Used by foci like equal trade to determine their area in artchitect mode
*/
public int getMaxAreaSize(ItemStack focusstack) {
return 1;
}
/**
* What upgrades can be applied to this focus for ranks 1 to 5
*/
public FocusUpgradeType[] getPossibleUpgradesByRank(ItemStack focusstack, int rank) {
return null;
}
/**
* What upgrades does the focus currently have
*/
public short[] getAppliedUpgrades(ItemStack focusstack) {
short[] l = new short[] {-1,-1,-1,-1,-1};
NBTTagList nbttaglist = getFocusUpgradeTagList(focusstack);
if (nbttaglist == null)
{
return l;
}
else
{
for (int j = 0; j < nbttaglist.tagCount(); ++j)
{
if (j>=5) break;
l[j] = nbttaglist.getCompoundTagAt(j).getShort("id");
}
return l;
}
}
public boolean applyUpgrade(ItemStack focusstack, FocusUpgradeType type, int rank) {
short[] upgrades = getAppliedUpgrades(focusstack);
if (upgrades[rank-1]!=-1 || rank<1 || rank>5) {
return false;
}
upgrades[rank-1] = type.id;
setFocusUpgradeTagList(focusstack, upgrades);
return true;
}
/**
* Use this method to define custom logic about which upgrades can be applied. This can be used to set up upgrade "trees"
* that make certain upgrades available only when others are unlocked first, when certain research is completed, or similar logic.
*
*/
public boolean canApplyUpgrade(ItemStack focusstack, EntityPlayer player, FocusUpgradeType type, int rank) {
return true;
}
/**
* Does this focus have the passed upgrade type
*/
public boolean isUpgradedWith(ItemStack focusstack, FocusUpgradeType focusUpgradetype) {
return getUpgradeLevel(focusstack,focusUpgradetype)>0;
}
/**
* What level is the passed upgrade type on the focus. If it is not present it returns 0
*/
public int getUpgradeLevel(ItemStack focusstack, FocusUpgradeType focusUpgradetype) {
short[] list = getAppliedUpgrades(focusstack);
int level=0;
for (short id:list) {
if (id == focusUpgradetype.id)
{
level++;
}
}
return level;
}
/**
* This method will be called whenever you right click, and possibly per wand usage tick depending on isVisCostPerTick
* IMPORTANT: It should be noted that vis consumption is now handled by the wand and not the focus so do not subtract any vis here.
* @param wandstack
* @param world
* @param entity - do not assume it will always be a player since it could be used by other entities as well
* @param movingobjectposition The target
* @param useCount the amount of ticks the item has been used for
* @return did the focus actually activate. Used to determine if vis should be consumed or not.
*/
public boolean onFocusActivation(ItemStack wandstack, World world, EntityLivingBase entity, MovingObjectPosition movingobjectposition, int useCount) {
return true;
}
// public ItemStack onFocusRightClick(ItemStack wandstack, World world,EntityPlayer player, MovingObjectPosition movingobjectposition) {
// // TODO Auto-generated method stub
// return null;
// }
//
// public void onUsingFocusTick(ItemStack wandstack, EntityPlayer player,int count) {
// // TODO Auto-generated method stub
// }
//
// public void onPlayerStoppedUsingFocus(ItemStack wandstack, World world, EntityPlayer player, int count) {
// // TODO Auto-generated method stub
//
// }
public boolean onFocusBlockStartBreak(ItemStack wandstack, BlockPos pos, EntityPlayer player) {
// TODO Auto-generated method stub
return false;
}
/**
* Internal helper methods
*/
private NBTTagList getFocusUpgradeTagList(ItemStack focusstack)
{
return focusstack.getTagCompound() == null ? null : focusstack.getTagCompound().getTagList("upgrade", 10);
}
private void setFocusUpgradeTagList(ItemStack focusstack, short[] upgrades) {
if (!focusstack.hasTagCompound())
focusstack.setTagCompound(new NBTTagCompound());
NBTTagCompound nbttagcompound = focusstack.getTagCompound();
NBTTagList tlist = new NBTTagList();
nbttagcompound.setTag("upgrade", tlist);
for (short id : upgrades) {
NBTTagCompound f = new NBTTagCompound();
f.setShort("id", id);
tlist.appendTag(f);
}
}
}

View file

@ -0,0 +1,142 @@
package thaumcraft.api.wands;
import java.util.LinkedHashMap;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import thaumcraft.api.aspects.Aspect;
/**
* This class is used to keep the material information for the various caps.
* It is also used to generate the wand recipes ingame.
* @author Azanor
*
*/
public class WandCap {
private String tag;
/**
* Cost to craft this wand. Combined with the rod cost.
*/
private int craftCost;
/**
* the amount by which all aspect costs are multiplied
*/
float baseCostModifier;
/**
* how many additional vis is gained per charge 'tick' (one charge tick occurs every 5 game ticks)
* examples: brass caps have a bonus of 1 and void caps have a bonus of 3
*/
int chargeBonus;
/**
* specifies a list of primal aspects that use the special discount figure instead of the normal discount.
*/
List<Aspect> specialCostModifierAspects;
/**
* the amount by which the specified aspect costs are multiplied
*/
float specialCostModifier;
/**
* The texture that will be used for the ingame wand cap
*/
ResourceLocation texture;
/**
* the actual item that makes up this cap and will be used to generate the wand recipes
*/
ItemStack item;
public static LinkedHashMap<String,WandCap> caps = new LinkedHashMap<String,WandCap>();
public WandCap (String tag, float discount, int charge, ItemStack item, int craftCost, ResourceLocation texture) {
this.setTag(tag);
this.baseCostModifier = discount;
this.specialCostModifierAspects = null;
this.texture = texture;
this.item=item;
this.chargeBonus = charge;
this.setCraftCost(craftCost);
caps.put(tag, this);
}
public WandCap (String tag, float discount, int charge, List<Aspect> specialAspects, float discountSpecial, ItemStack item, int craftCost, ResourceLocation texture) {
this.setTag(tag);
this.baseCostModifier = discount;
this.specialCostModifierAspects = specialAspects;
this.specialCostModifier = discountSpecial;
this.texture = texture;
this.item=item;
this.chargeBonus = charge;
this.setCraftCost(craftCost);
caps.put(tag, this);
}
public float getBaseCostModifier() {
return baseCostModifier;
}
public List<Aspect> getSpecialCostModifierAspects() {
return specialCostModifierAspects;
}
public float getSpecialCostModifier() {
return specialCostModifier;
}
public int getChargeBonus() {
return chargeBonus;
}
public ResourceLocation getTexture() {
return texture;
}
public void setTexture(ResourceLocation texture) {
this.texture = texture;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public ItemStack getItem() {
return item;
}
public void setItem(ItemStack item) {
this.item = item;
}
public int getCraftCost() {
return craftCost;
}
public void setCraftCost(int craftCost) {
this.craftCost = craftCost;
}
/**
* The research a player needs to have finished to be able to craft a wand with this cap.
*/
public String getResearch() {
return "CAP_"+getTag();
}
// Some examples:
// WandCap WAND_CAP_IRON = new WandCap("iron", 1.1f, Arrays.asList(Aspect.ORDER),1, new ItemStack(ConfigItems.itemWandCap,1,0),1);
// WandCap WAND_CAP_GOLD = new WandCap("gold", 1f, new ItemStack(ConfigItems.itemWandCap,1,1),3);
}

View file

@ -0,0 +1,36 @@
package thaumcraft.api.wands;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.AspectList;
public class WandHelper {
/**
* Use to subtract vis from a wand for most operations
* @param wand the wand itemstack
* @param player the player using the wand
* @param cost the cost of the operation.
* @param doit actually subtract the vis from the wand if true - if false just simulate the result
* @param crafting is this a crafting operation or not - if
* false then things like frugal and potency will apply to the costs
* @return was the vis successfully subtracted
*/
public static boolean consumeVisFromWand(ItemStack wand, EntityPlayer player,
AspectList cost, boolean doit, boolean crafting) {
return ThaumcraftApi.internalMethods.consumeVisFromWand(wand, player, cost, doit, crafting);
}
/**
* Subtract vis from a wand the player is carrying. The costs are handled like crafting however and things like
* frugal don't effect them
* @param player the player using the wand
* @param cost the cost of the operation.
* @return was the vis successfully subtracted
*/
public static boolean consumeVisFromInventory(EntityPlayer player, AspectList cost) {
return ThaumcraftApi.internalMethods.consumeVisFromInventory(player, cost);
}
}

View file

@ -0,0 +1,155 @@
package thaumcraft.api.wands;
import java.util.LinkedHashMap;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
/**
*
* @author Azanor
*
* This class is used to keep the material information for the various rods.
* It is also used to generate the wand recipes ingame.
*
*/
public class WandRod {
private String tag;
/**
* Cost to craft this wand. Combined with the rod cost.
*/
private int craftCost;
/**
* The amount of vis that can be stored
*/
int capacity;
/**
* The texture that will be used for the ingame wand rod
*/
protected ResourceLocation texture;
/**
* the actual item that makes up this rod and will be used to generate the wand recipes
*/
ItemStack item;
/**
* A class that will be called whenever the wand onUpdate tick is run
*/
IWandRodOnUpdate onUpdate;
/**
* Is this a staff rod?
*/
private boolean isStaff=false;
/**
* Does this rod give a free level of potency?
*/
private boolean potencyBonus=false;
public static LinkedHashMap<String,WandRod> rods = new LinkedHashMap<String,WandRod>();
public static WandRod getRod(String tag) {
return rods.get(tag);
}
public WandRod (String tag, int capacity, ItemStack item, int craftCost, ResourceLocation texture) {
this.setTag(tag);
this.capacity = capacity;
this.texture = texture;
this.item=item;
this.setCraftCost(craftCost);
rods.put(tag, this);
}
public WandRod (String tag, int capacity, ItemStack item, int craftCost, IWandRodOnUpdate onUpdate, ResourceLocation texture) {
this.setTag(tag);
this.capacity = capacity;
this.texture = texture;
this.item=item;
this.setCraftCost(craftCost);
rods.put(tag, this);
this.onUpdate = onUpdate;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
public ResourceLocation getTexture() {
return texture;
}
public void setTexture(ResourceLocation texture) {
this.texture = texture;
}
public ItemStack getItem() {
return item;
}
public void setItem(ItemStack item) {
this.item = item;
}
public int getCraftCost() {
return craftCost;
}
public void setCraftCost(int craftCost) {
this.craftCost = craftCost;
}
public IWandRodOnUpdate getOnUpdate() {
return onUpdate;
}
public void setOnUpdate(IWandRodOnUpdate onUpdate) {
this.onUpdate = onUpdate;
}
/**
* The research a player needs to have finished to be able to craft a wand with this rod.
*/
public String getResearch() {
return "ROD_"+getTag();
}
public boolean isStaff() {
return isStaff;
}
public void setStaff(boolean isStaff) {
this.isStaff = isStaff;
}
public boolean hasPotencyBonus() {
return potencyBonus;
}
public void setPotencyBonus(boolean potencyBonus) {
this.potencyBonus = potencyBonus;
}
// Some examples:
// WandRod WAND_ROD_WOOD = new WandRod("wood",250,new ItemStack(Item.stick),1,new ResourceLocation("thaumcraft","items/wand/cap_iron_mat"));
// WandRod WAND_ROD_BLAZE = new WandRod("blaze",750,new ItemStack(Item.blazeRod),7,new ResourceLocation("thaumcraft","items/wand/rod_blaze_mat"),new WandRodBlazeOnUpdate());
}

View file

@ -0,0 +1,124 @@
package thaumcraft.api.wands;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
/**
* This class serves a similar function to IWandable in that it allows wands to interact
* with object in the world. In this case it is most useful for adding interaction with non-mod
* blocks where you can't control what happens in their code.
* Example where it is used is in crafting the thaumonomicon from a bookshelf and the
* crucible from a cauldron
*
* @author azanor
*
*/
public class WandTriggerRegistry {
private static HashMap<String,HashMap<IBlockState,List>> triggers = new HashMap<String,HashMap<IBlockState,List>>();
private static final String DEFAULT = "default";
/**
* Registers an action to perform when a casting wand right clicks on a specific block.
* A manager class needs to be created that implements IWandTriggerManager.
* @param manager
* @param event a logical number that you can use to differentiate different events or actions
* @param blockState
* @param meta send -1 as a wildcard value for all possible meta values
* @param modid a unique identifier. It is best to register your own triggers using your mod id to avoid conflicts with mods that register triggers for the same block
*/
public static void registerWandBlockTrigger(IWandTriggerManager manager, int event, IBlockState state, String modid) {
if (!triggers.containsKey(modid)) {
triggers.put(modid, new HashMap<IBlockState,List>());
}
HashMap<IBlockState,List> temp = triggers.get(modid);
temp.put(state,Arrays.asList(manager,event));
triggers.put(modid, temp);
}
/**
* for legacy support
*/
public static void registerWandBlockTrigger(IWandTriggerManager manager, int event, IBlockState state) {
registerWandBlockTrigger(manager, event, state, DEFAULT);
}
/**
* Checks all trigger registries if one exists for the given block and meta
* @param blockState
* @param meta
* @return
*/
public static boolean hasTrigger(IBlockState state) {
for (String modid:triggers.keySet()) {
HashMap<IBlockState,List> temp = triggers.get(modid);
if (temp.containsKey(state)) return true;
}
return false;
}
/**
* modid sensitive version
*/
public static boolean hasTrigger(IBlockState state, String modid) {
if (!triggers.containsKey(modid)) return false;
HashMap<IBlockState,List> temp = triggers.get(modid);
if (temp.containsKey(state)) return true;
return false;
}
/**
* This is called by the onItemUseFirst function in wands.
* Parameters and return value functions like you would expect for that function.
* @param world
* @param wand
* @param player
* @param x
* @param y
* @param z
* @param side
* @param blockState
* @param meta
* @return
*/
public static boolean performTrigger(World world, ItemStack wand, EntityPlayer player,
BlockPos pos, EnumFacing side, IBlockState state) {
for (String modid:triggers.keySet()) {
HashMap<IBlockState,List> temp = triggers.get(modid);
List l = temp.get(state);
if (l==null) continue;
IWandTriggerManager manager = (IWandTriggerManager) l.get(0);
int event = (Integer) l.get(1);
boolean result = manager.performTrigger(world, wand, player, pos, side, event);
if (result) return true;
}
return false;
}
/**
* modid sensitive version
*/
public static boolean performTrigger(World world, ItemStack wand, EntityPlayer player,
BlockPos pos, EnumFacing side, IBlockState state, String modid) {
if (!triggers.containsKey(modid)) return false;
HashMap<IBlockState,List> temp = triggers.get(modid);
List l = temp.get(state);
if (l==null) return false;
IWandTriggerManager manager = (IWandTriggerManager) l.get(0);
int event = (Integer) l.get(1);
return manager.performTrigger(world, wand, player, pos, side, event);
}
}

View file

@ -0,0 +1,23 @@
package biomesoplenty.common.init;
import biomesoplenty.common.integration.ThaumcraftCompat;
import biomesoplenty.core.BiomesOPlenty;
import net.minecraftforge.fml.common.Loader;
public class ModCompatibility
{
public static void postInit()
{
if (Loader.isModLoaded("Thaumcraft"))
{
try
{
ThaumcraftCompat.init();
}
catch (Exception e)
{
BiomesOPlenty.logger.error("There was an error while integrating Thaumcraft with Biomes O' Plenty", e);
}
}
}
}

View file

@ -0,0 +1,222 @@
package biomesoplenty.common.integration;
import biomesoplenty.api.block.BOPBlocks;
import biomesoplenty.api.item.BOPItems;
import biomesoplenty.common.block.BlockBOPBones;
import biomesoplenty.common.block.BlockBOPBones.BoneType;
import biomesoplenty.common.block.BlockBOPFlower;
import biomesoplenty.common.block.BlockBOPGem;
import biomesoplenty.common.block.BlockBOPGrass;
import biomesoplenty.common.block.BlockBOPGrass.BOPGrassType;
import biomesoplenty.common.block.BlockBOPLeaves;
import biomesoplenty.common.block.BlockBOPLog;
import biomesoplenty.common.block.BlockBOPMushroom;
import biomesoplenty.common.block.BlockBOPMushroom.MushroomType;
import biomesoplenty.common.block.BlockBOPPlanks;
import biomesoplenty.common.block.BlockBOPPlant;
import biomesoplenty.common.block.BlockBOPSand;
import biomesoplenty.common.block.BlockBOPSapling;
import biomesoplenty.common.block.BlockBOPSeaweed;
import biomesoplenty.common.block.BlockBOPSeaweed.SeaweedType;
import biomesoplenty.common.enums.BOPFlowers;
import biomesoplenty.common.enums.BOPGems;
import biomesoplenty.common.enums.BOPPlants;
import biomesoplenty.common.enums.BOPTrees;
import biomesoplenty.common.enums.BOPWoods;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.event.FMLInterModComms;
import thaumcraft.api.ThaumcraftApi;
import thaumcraft.api.aspects.Aspect;
import thaumcraft.api.aspects.AspectList;
public class ThaumcraftCompat
{
public static void init()
{
addThaumcraftAspects();
addThaumcraftGolemsSupport();
}
private static void addThaumcraftAspects()
{
//Thaumcraft sets most aspects automatically, just special cases are there
//Logs
addAspectsToState(BlockBOPLog.paging.getVariantState(BOPWoods.DARK), new Aspect[] { Aspect.PLANT, Aspect.DARKNESS }, new int[] { 4, 2 });
addAspectsToState(BlockBOPLog.paging.getVariantState(BOPWoods.ETHEREAL), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 4, 2 });
addAspectsToState(BlockBOPLog.paging.getVariantState(BOPWoods.HELLBARK), new Aspect[] { Aspect.PLANT, Aspect.FIRE }, new int[] { 4, 2 });
addAspectsToState(BlockBOPLog.paging.getVariantState(BOPWoods.DEAD), new Aspect[] { Aspect.PLANT, Aspect.DEATH }, new int[] { 4, 2 });
addAspectsToState(BlockBOPLog.paging.getVariantState(BOPWoods.SACRED_OAK), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 4, 2 });
//Planks
addAspectsToState(BlockBOPPlanks.paging.getVariantState(BOPWoods.SACRED_OAK), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlanks.paging.getVariantState(BOPWoods.MAGIC), new Aspect[] { Aspect.PLANT }, new int[] { 1 });
addAspectsToState(BlockBOPPlanks.paging.getVariantState(BOPWoods.DARK), new Aspect[] { Aspect.PLANT, Aspect.DARKNESS }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlanks.paging.getVariantState(BOPWoods.ETHEREAL), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 1, 1 });
addAspectsToBlock(BOPBlocks.bamboo_thatching, new Aspect[] { Aspect.WATER, Aspect.PLANT }, new int[] { 4, 4 });
addAspectsToState(BlockBOPPlanks.paging.getVariantState(BOPWoods.HELLBARK), new Aspect[] { Aspect.PLANT, Aspect.FIRE }, new int[] { 1, 1 });
//Leaves
//TODO: addAspectsToBlock(BOPCBlocks.appleLeaves, new Aspect[] { Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 1 });
//TODO: addAspectsToBlock(BOPCBlocks.persimmonLeaves, new Aspect[] { Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.DEAD), new Aspect[] { Aspect.PLANT, Aspect.DEATH }, new int[] { 1, 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.DARK), new Aspect[] { Aspect.PLANT, Aspect.DARKNESS }, new int[] { 1, 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.ETHEREAL), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 1, 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.SACRED_OAK), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 1, 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.MAGIC), new Aspect[] { Aspect.PLANT }, new int[] { 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.HELLBARK), new Aspect[] { Aspect.PLANT, Aspect.FIRE }, new int[] { 1, 1 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.FLOWERING), new Aspect[] { Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 1 });
//Saplings
//TODO: Apple addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 2, 2 });
//TODO: Persimmon addAspectsToState(BOPCBlocks.saplings, 15, new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 1, 2 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.ETHEREAL), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.LIGHT }, new int[] { 1, 1, 2 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.MAGIC), new Aspect[] { Aspect.PLANT, Aspect.PLANT }, new int[] { 1, 1 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.DARK), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.DARKNESS }, new int[] { 1, 1, 2 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.DEAD), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.DEATH }, new int[] { 1, 1, 2 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.HELLBARK), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.FIRE }, new int[] { 1, 1, 2 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.SACRED_OAK), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.LIGHT }, new int[] { 1, 1, 2 });
addAspectsToState(BlockBOPSapling.paging.getVariantState(BOPTrees.FLOWERING), new Aspect[] { Aspect.PLANT, Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 1, 2 });
//Blocks
addAspectsToBlock(BOPBlocks.mud, new Aspect[] { Aspect.WATER, Aspect.EARTH }, new int[] { 2, 5 });
addAspectsToBlock(BOPBlocks.dried_dirt, new Aspect[] { Aspect.ENTROPY, Aspect.EARTH }, new int[] { 1, 1 });
addAspectsToBlock(BOPBlocks.hard_ice, new Aspect[] { Aspect.EARTH, Aspect.COLD }, new int[] { 2, 2 });
addAspectsToState(BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BOPGrassType.ORIGIN), new Aspect[] { Aspect.EARTH, Aspect.PLANT }, new int[] { 1, 2 });
addAspectsToBlock(BOPBlocks.ash_stone, new Aspect[] { Aspect.EARTH, Aspect.FIRE }, new int[] { 1, 1 });
addAspectsToBlock(BOPBlocks.hard_sand, new Aspect[] { Aspect.EARTH, Aspect.ENTROPY }, new int[] { 1, 2 });
addAspectsToBlock(BOPBlocks.hard_dirt, new Aspect[] { Aspect.EARTH }, new int[] { 2 });
addAspectsToBlock(BOPBlocks.crystal, new Aspect[] { Aspect.DESIRE, Aspect.LIGHT, Aspect.CRYSTAL }, new int[] { 5, 5, 5 });
addAspectsToBlock(BOPBlocks.crag_rock, new Aspect[] { Aspect.EARTH }, new int[] { 2 });
addAspectsToState(BOPBlocks.sand.getDefaultState().withProperty(BlockBOPSand.VARIANT, BlockBOPSand.SandType.QUICKSAND), new Aspect[] { Aspect.EARTH, Aspect.TRAP }, new int[] { 2, 4 });
addAspectsToState(BOPBlocks.grass.getDefaultState().withProperty(BlockBOPGrass.VARIANT, BOPGrassType.SMOLDERING), new Aspect[] { Aspect.EARTH, Aspect.FIRE }, new int[] { 2, 1 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.AMETHYST), new Aspect[] { Aspect.DESIRE, Aspect.ORDER, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 3, 7, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.AMETHYST), new Aspect[] { Aspect.DESIRE, Aspect.ORDER, Aspect.CRYSTAL }, new int[] { 5, 5, 8 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.RED_BIG_FLOWER), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPLeaves.paging.getVariantState(BOPTrees.YELLOW_BIG_FLOWER), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BOPBlocks.bone_segment.getDefaultState().withProperty(BlockBOPBones.VARIANT, BoneType.SMALL), new Aspect[] { Aspect.DEATH }, new int[] { 3 });
addAspectsToState(BOPBlocks.bone_segment.getDefaultState().withProperty(BlockBOPBones.VARIANT, BoneType.MEDIUM), new Aspect[] { Aspect.DEATH }, new int[] { 5 });
addAspectsToState(BOPBlocks.bone_segment.getDefaultState().withProperty(BlockBOPBones.VARIANT, BoneType.LARGE), new Aspect[] { Aspect.DEATH }, new int[] { 7 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.POISONIVY), new Aspect[] { Aspect.PLANT }, new int[] { 2 });
//Plants
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.CATTAIL), new Aspect[] { Aspect.PLANT, Aspect.WATER }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.REED), new Aspect[] { Aspect.PLANT, Aspect.PLANT }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.CATTAIL), new Aspect[] { Aspect.PLANT, Aspect.WATER }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.SPROUT), new Aspect[] { Aspect.PLANT }, new int[] { 2 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.BUSH), new Aspect[] { Aspect.PLANT }, new int[] { 2 });
addAspectsToState(BOPBlocks.seaweed.getDefaultState().withProperty(BlockBOPSeaweed.VARIANT, SeaweedType.KELP), new Aspect[] { Aspect.PLANT, Aspect.WATER }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.ROOT), new Aspect[] { Aspect.PLANT, Aspect.EARTH }, new int[] { 1, 1 });
addAspectsToBlock(BOPBlocks.bamboo, new Aspect[] { Aspect.PLANT, Aspect.LIFE }, new int[] { 1, 1 });
addAspectsToState(BOPBlocks.mushroom.getDefaultState().withProperty(BlockBOPMushroom.VARIANT, MushroomType.TOADSTOOL), new Aspect[] { Aspect.PLANT }, new int[] { 3 });
addAspectsToState(BOPBlocks.mushroom.getDefaultState().withProperty(BlockBOPMushroom.VARIANT, MushroomType.PORTOBELLO), new Aspect[] { Aspect.PLANT }, new int[] { 3 });
addAspectsToState(BOPBlocks.mushroom.getDefaultState().withProperty(BlockBOPMushroom.VARIANT, MushroomType.BLUE_MILK_CAP), new Aspect[] { Aspect.PLANT }, new int[] { 3 });
addAspectsToState(BOPBlocks.mushroom.getDefaultState().withProperty(BlockBOPMushroom.VARIANT, MushroomType.GLOWSHROOM), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 3, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.TINYCACTUS), new Aspect[] { Aspect.PLANT, Aspect.AVERSION }, new int[] { 2, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.DESERTSPROUTS), new Aspect[] { Aspect.PLANT }, new int[] { 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.DUNEGRASS), new Aspect[] { Aspect.PLANT, Aspect.AIR }, new int[] { 1, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.THORN), new Aspect[] { Aspect.PLANT, Aspect.AVERSION }, new int[] { 2, 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.DESERTGRASS), new Aspect[] { Aspect.PLANT }, new int[] { 1 });
addAspectsToState(BlockBOPPlant.paging.getVariantState(BOPPlants.DEADGRASS), new Aspect[] { Aspect.PLANT, Aspect.DEATH }, new int[] { 1, 2 });
addAspectsToBlock(BOPBlocks.tree_moss, new Aspect[] { Aspect.PLANT }, new int[] { 2 });
addAspectsToBlock(BOPBlocks.moss, new Aspect[] { Aspect.PLANT }, new int[] { 2 });
//TODO: addAspectsToBlock(BOPBlocks.willow, new Aspect[] { Aspect.PLANT }, new int[] { 2 });
//Flowers
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.VIOLET), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.BLUE_HYDRANGEA), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.DEATHBLOOM), new Aspect[] { Aspect.PLANT, Aspect.DEATH }, new int[] { 4, 1 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.GLOWFLOWER), new Aspect[] { Aspect.PLANT, Aspect.LIGHT }, new int[] { 4, 1 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.WHITE_ANEMONE), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.SWAMPFLOWER), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.WILDFLOWER), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.ORANGE_COSMOS), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.DANDELION), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.PINK_DAFFODIL), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.BROMELIAD), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.CLOVER), new Aspect[] { Aspect.PLANT }, new int[] { 2 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.PINK_HIBISCUS), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.LILY_OF_THE_VALLEY), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.BURNING_BLOSSOM), new Aspect[] { Aspect.PLANT, Aspect.FIRE }, new int[] { 4, 2 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.LAVENDER), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.GOLDENROD), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.BLUEBELLS), new Aspect[] { Aspect.PLANT }, new int[] { 4 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.MINERS_DELIGHT), new Aspect[] { Aspect.PLANT, Aspect.EARTH }, new int[] { 4, 1 });
addAspectsToState(BlockBOPFlower.paging.getVariantState(BOPFlowers.ICY_IRIS), new Aspect[] { Aspect.PLANT, Aspect.COLD }, new int[] { 4, 2 });
//Gems
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.RUBY), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.RUBY), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.PERIDOT), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.PERIDOT), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.TOPAZ), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.TOPAZ), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.TANZANITE), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.TANZANITE), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.MALACHITE), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.MALACHITE), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.SAPPHIRE), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.SAPPHIRE), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
addAspectsToState(BOPBlocks.gem_ore.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.AMBER), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL, Aspect.EARTH }, new int[] { 3, 5, 3 });
addAspectsToState(BOPBlocks.gem_block.getDefaultState().withProperty(BlockBOPGem.VARIANT, BOPGems.AMBER), new Aspect[] { Aspect.DESIRE, Aspect.CRYSTAL }, new int[] { 5, 7 });
//Items
addAspectsToItem(BOPItems.gem, new Aspect[] { Aspect.DESIRE, Aspect.ORDER, Aspect.CRYSTAL }, new int[] { 4, 4, 4 });
addAspectsToItem(BOPItems.ash, new Aspect[] { Aspect.ENTROPY, Aspect.EXCHANGE }, new int[] { 1, 1 });
addAspectsToItem(BOPItems.crystal_shard, new Aspect[] { Aspect.CRYSTAL, Aspect.LIGHT, Aspect.DESIRE }, new int[] { 4, 2, 3 });
addAspectsToItem(BOPItems.mud_brick, new Aspect[] { Aspect.EARTH, Aspect.FIRE }, new int[] { 2, 1 });
addAspectsToItemMeta(BOPItems.dart, 0, new Aspect[] { Aspect.AVERSION }, new int[] { 1 });
addAspectsToItemMeta(BOPItems.dart, 1, new Aspect[] { Aspect.AVERSION }, new int[] { 1 });
}
//Allows Thaumcraft golems to harvest BoP crops
private static void addThaumcraftGolemsSupport()
{
addClickableCrop(BlockBOPPlant.paging.getVariantState(BOPPlants.BERRYBUSH));
FMLInterModComms.sendMessage("Thaumcraft", "harvestStandardCrop", new ItemStack(BOPBlocks.fruit_block, 1, 0));
FMLInterModComms.sendMessage("Thaumcraft", "harvestStandardCrop", new ItemStack(BOPBlocks.fruit_block, 1, 1));
}
private static void addAspectsToBlock(Block block, Aspect[] aspects, int[] amounts)
{
addAspects(new ItemStack(block), aspects, amounts);
}
private static void addAspectsToState(IBlockState state, Aspect[] aspects, int[] amounts)
{
addAspects(new ItemStack(state.getBlock(), 1, state.getBlock().getMetaFromState(state)), aspects, amounts);
}
private static void addAspectsToItem(Item item, Aspect[] aspects, int[] amounts)
{
addAspects(new ItemStack(item), aspects, amounts);
}
private static void addAspectsToItemMeta(Item items, int meta, Aspect[] aspects, int[] amounts)
{
addAspects(new ItemStack(items, 1, meta), aspects, amounts);
}
private static void addClickableCrop(IBlockState state)
{
FMLInterModComms.sendMessage("Thaumcraft", "harvestClickableCrop", new ItemStack(state.getBlock(), 1, state.getBlock().getMetaFromState(state)));
}
private static void addAspects(ItemStack stack, Aspect[] aspects, int[] amounts)
{
AspectList list = new AspectList();
for (int i = 0; i < aspects.length; i++)
list.add(aspects[i], amounts[i]);
ThaumcraftApi.registerObjectTag(stack, list);
}
}

View file

@ -18,6 +18,7 @@ import biomesoplenty.common.init.ModBiomes;
import biomesoplenty.common.init.ModBlockQueries;
import biomesoplenty.common.init.ModBlocks;
import biomesoplenty.common.init.ModChecks;
import biomesoplenty.common.init.ModCompatibility;
import biomesoplenty.common.init.ModConfiguration;
import biomesoplenty.common.init.ModCrafting;
import biomesoplenty.common.init.ModEntities;
@ -80,6 +81,7 @@ public class BiomesOPlenty
@EventHandler
public void postInit(FMLPostInitializationEvent event)
{
ModCompatibility.postInit();
ModChecks.postInit();
}