package jp.plusplus.fbs.alchemy; import jp.plusplus.fbs.FBS; import jp.plusplus.fbs.alchemy.characteristic.*; import jp.plusplus.fbs.item.ItemCore; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.StatCollector; import net.minecraftforge.oredict.OreDictionary; import java.util.*; /** * Created by plusplus_F on 2015/09/08. * たぶん錬金術はわりと規模がでかくなると思うんで分離 */ public class AlchemyRegistry { //特性 private ArrayList> characteristics=new ArrayList>(); private HashMap, Integer> characteristicsIdMap=new HashMap, Integer>(); //素材 private HashMap> materials=new HashMap>(); private HashMap> materialNames=new HashMap>(); //鑑定 private HashMap> appraisalItems=new HashMap>(); //調合 private ArrayList recipes=new ArrayList(); private ArrayList productExpPairs=new ArrayList(); //カゴ private ArrayList basketItems=new ArrayList(); private static AlchemyRegistry instance=new AlchemyRegistry(); private static Random rand=new Random(); private AlchemyRegistry(){} public static Random getRandom(){ return instance.rand; } public static void RegisterAlchemy(){ //------------------------------------------------------------------------------------------------------- // 特性 //------------------------------------------------------------------------------------------------------- AddCharacteristic(CharacteristicSanity.Gain.class); AddCharacteristic(CharacteristicSanity.Lose.class); AddCharacteristic(CharacteristicHealth.Gain.class); AddCharacteristic(CharacteristicHealth.Lose.class); if(FBS.cooperatesSS2){ AddCharacteristic(CharacteristicWater.Gain.class); AddCharacteristic(CharacteristicWater.Lose.class); AddCharacteristic(CharacteristicStamina.Gain.class); AddCharacteristic(CharacteristicStamina.Lose.class); } AddCharacteristic(CharacteristicExp.Gain.class); AddCharacteristic(CharacteristicExp.Lose.class); AddCharacteristic(CharacteristicLook.class); AddCharacteristic(CharacteristicWeight.class); AddCharacteristic(CharacteristicQuality.class); AddCharacteristic(CharacteristicCleverness.Gain.class); AddCharacteristic(CharacteristicPoison.Gain.class); AddCharacteristic(CharacteristicPoison.Lose.class); AddCharacteristic(CharacteristicPower.Gain.class); AddCharacteristic(CharacteristicPower.Lose.class); AddCharacteristic(CharacteristicSpeed.Gain.class); AddCharacteristic(CharacteristicSpeed.Lose.class); AddCharacteristic(CharacteristicConfusion.Gain.class); AddCharacteristic(CharacteristicConfusion.Lose.class); //------------------------------------------------------------------------------------------------------- // 鑑定 //------------------------------------------------------------------------------------------------------- RegisterAppraisal(new ItemStack(Items.potionitem), new ItemStack(ItemCore.alchemyMaterial, 1, 0), 63); RegisterAppraisal(new ItemStack(Items.potionitem), new ItemStack(ItemCore.alchemyMaterial, 1, 1), 1); RegisterAppraisal(new ItemStack(Items.lava_bucket), new ItemStack(ItemCore.alchemyMaterial, 1, 2), 1); RegisterAppraisal("treeLeaves", new ItemStack(ItemCore.alchemyMaterial, 1, 3), 63); RegisterAppraisal("treeLeaves", new ItemStack(ItemCore.alchemyMaterial, 1, 6), 1); RegisterAppraisal(new ItemStack(Items.stick), new ItemStack(ItemCore.alchemyMaterial, 1, 4), 63); RegisterAppraisal(new ItemStack(Items.stick), new ItemStack(ItemCore.alchemyMaterial, 1, 7), 1); for(int i=0;i45)){ RegisterAppraisal(new ItemStack(ItemCore.mushroomUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, i), 10); } } RegisterAppraisal(new ItemStack(ItemCore.herbUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 18), 60); RegisterAppraisal(new ItemStack(ItemCore.herbUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 36), 3); RegisterAppraisal(new ItemStack(ItemCore.herbUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 37), 3); RegisterAppraisal(new ItemStack(ItemCore.mushroomUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 25), 50); RegisterAppraisal(new ItemStack(ItemCore.mushroomUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 42), 3); RegisterAppraisal(new ItemStack(ItemCore.mushroomUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 43), 3); RegisterAppraisal(new ItemStack(ItemCore.mushroomUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 44), 3); RegisterAppraisal(new ItemStack(ItemCore.mushroomUnknown), new ItemStack(ItemCore.alchemyMaterial, 1, 45), 3); for(int i=0;i chara){ instance.characteristics.add(chara); instance.characteristicsIdMap.put(chara, instance.characteristics.size()-1); } /** * 特性からIdを得る * @param chara * @return */ public static int GetCharacteristicId(Class chara){ if(!instance.characteristicsIdMap.containsKey(chara)){ AddCharacteristic(chara); } return instance.characteristicsIdMap.get(chara); } /** * Idから特性を得る * @param id * @return */ public static Class GetCharacteristicFromId(int id){ if(id<0 || id>=instance.characteristics.size()) return null; return instance.characteristics.get(id); } /** * 特性のリストをnbtに書き込む * @param nbt * @param list */ public static void WriteCharacteristicToNBT(NBTTagCompound nbt, ArrayList list){ NBTTagList tags=new NBTTagList(); for(CharacteristicBase cb : list){ NBTTagCompound tag=new NBTTagCompound(); tag.setInteger("id", cb.getId()); cb.writeToNBT(tag); tags.appendTag(tag); } nbt.setTag("characteristics", tags); nbt.setBoolean("appraisal", true); } /** * nbtから特性リストを得る * @param nbt * @return */ public static ArrayList ReadCharacteristicFromNBT(NBTTagCompound nbt){ ArrayList ret=new ArrayList(); if(nbt!=null && nbt.hasKey("characteristics")){ NBTTagList tags=(NBTTagList)nbt.getTag("characteristics"); for(int i=0;i cbs=AlchemyRegistry.ReadCharacteristicFromNBT(itemStack.getTagCompound()); for(CharacteristicBase cb : cbs){ list.add(cb.getNameColor()+"-"+cb.getLocalizedName()+":"+cb.getLocalizedEffectValue()); } } } //-------------------------------------------------------------------------------------- // 素材 //-------------------------------------------------------------------------------------- /** * 素材としてアイテムスタックを登録する * @param name * @param itemStack */ public static void RegisterMaterial(String name, ItemStack itemStack){ if(!instance.materials.containsKey(name)){ ArrayList list=new ArrayList(); instance.materials.put(name, list); } instance.materials.get(name).add(itemStack); RegisterMaterialName(itemStack, name); } /** * アイテムスタックがその素材として使えるかを返す * @param name * @param itemStack * @return */ public static boolean IsMatching(String name, ItemStack itemStack){ if(!instance.materials.containsKey(name)) return false; ArrayList list=instance.materials.get(name); for(ItemStack item : list){ if(item.isItemEqual(itemStack)){ return true; } } return false; } private static Map.Entry> cachedMaterial; /** * アイテムスタックの持つ素材名を得る * @param itemStack * @return */ public static ArrayList GetMaterialNames(ItemStack itemStack){ if(cachedMaterial!=null && cachedMaterial.getKey().isItemEqual(itemStack)){ return cachedMaterial.getValue(); } for(Map.Entry> e : instance.materialNames.entrySet()){ if(e.getKey().isItemEqual(itemStack)){ cachedMaterial=e; return e.getValue(); } } return null; } private static void RegisterMaterialName(ItemStack itemStack, String name){ ArrayList list=GetMaterialNames(itemStack); if(list!=null){ //素材名リストがある場合直接追加 list.add(name); } else{ //素材名リストがない場合リスト作ってマップに追加 list=new ArrayList(); list.add(name); instance.materialNames.put(itemStack, list); } } /** * listに素材名一覧を追加する * @param itemStack * @param list * @param flag */ public static void AddMaterialInfo(ItemStack itemStack, List list, boolean flag){ list.add(StatCollector.translateToLocal("alchemy.fbs.material")); ArrayList names= AlchemyRegistry.GetMaterialNames(itemStack); if(names!=null && !names.isEmpty()){ for(String str : names){ list.add("-"+str); } } } //-------------------------------------------------------------------------------------- // 鑑定 //-------------------------------------------------------------------------------------- /** * 鑑定アイテムを登録する * @param input * @param output 鑑定品(ItemはIAlchemyMaterialを継承しておくこと) * @param weight 出現重み */ public static void RegisterAppraisal(ItemStack input, ItemStack output, int weight){ AppraisalItemStack ais=new AppraisalItemStack(input); ArrayList list=GetAppraisals(ais); list.add(new WeightedItemStack(weight, output)); } /** * 鑑定アイテムを登録する(鉱石辞書編) * @param input * @param output 鑑定品(ItemはIAlchemyMaterialを継承しておくこと) * @param weight 出現重み */ public static void RegisterAppraisal(String input, ItemStack output, int weight){ AppraisalItemStack ais=new AppraisalItemStack(input); ArrayList list=GetAppraisals(ais); list.add(new WeightedItemStack(weight, output)); } private static ArrayList GetAppraisals(AppraisalItemStack ais){ ArrayList list; for(AppraisalItemStack aiss : instance.appraisalItems.keySet()){ if(aiss.equals(ais)){ return instance.appraisalItems.get(aiss); } } list=new ArrayList(); instance.appraisalItems.put(ais, list); return list; } public static ArrayList GetAppraisalList(ItemStack input){ for(AppraisalItemStack aiss : instance.appraisalItems.keySet()){ if(aiss.isItemEqual(input)) return instance.appraisalItems.get(aiss); } return null; } public static ArrayList GetAlllAppraisal(){ ArrayList ret=new ArrayList(); for(Map.Entry> e : instance.appraisalItems.entrySet()){ for(WeightedItemStack wis : e.getValue()){ ret.add(new ItemPair(e.getKey().getItemStack(), wis.getItemStack())); } } return ret; } /** * そのアイテムが鑑定できるか判定する * @param input * @return */ public static boolean CanAppraisal(ItemStack input){ NBTTagCompound nbt=input.getTagCompound(); if(nbt!=null && nbt.getBoolean("appraisal")) return false; return GetAppraisalList(input)!=null; } /** * 鑑定したアイテムを得る。この時ランダムで特性が付与される。 * @param input * @return 鑑定できないアイテムであればnull */ public static ItemStack GetRandomAppraisal(ItemStack input){ ArrayList list=GetAppraisalList(input); if(list.isEmpty()) return null; int ws=0; for(WeightedItemStack wis : list){ ws+=wis.getWeight(); } int r=instance.rand.nextInt(ws); ws=0; for(int i=0;i cList=((IAlchemyMaterial)ret.getItem()).addCharacteristics(ret, instance.rand); if(cList!=null && !cList.isEmpty()){ ret.setTagCompound(new NBTTagCompound()); WriteCharacteristicToNBT(ret.getTagCompound(), cList); // FBS.logger.info("written"); } //FBS.logger.info(cList.toString()); return ret; } ws+=wis.getWeight(); } return null; } //-------------------------------------------------------------------------------------- // 調合 //-------------------------------------------------------------------------------------- private static Recipe cachedRecipe; public static void RegisterRecipe(ItemStack key, ItemStack output, int lv, float prob, double exp, String ... materials){ instance.recipes.add(new Recipe(lv, prob, key, output, materials)); RegisterProductExpPair(output, exp); } public static Recipe GetRecipe(ItemStack key){ if(cachedRecipe!=null && cachedRecipe.isKey(key)) return cachedRecipe; for(Recipe r : instance.recipes){ if(r.isKey(key)){ cachedRecipe=r; return cachedRecipe; } } return null; } /** * レシピと投入済み素材リストから、inputが未投入の素材か判定する * @param key * @param input * @param inputMaterials * @return */ public static boolean IsMaterial(ItemStack key, ItemStack input, ArrayList inputMaterials){ //レシピを得る Recipe r=GetRecipe(key); return IsMaterial(r, input, inputMaterials); } public static boolean IsMaterial(Recipe recipe, ItemStack input, ArrayList inputMaterials){ if(recipe==null) return false; //matから未投入素材リストを得る LinkedList mats=recipe.getMaterialList(); LinkedList tmp=new LinkedList(inputMaterials); for(int i=0;i inputMaterials){ return IsSatisfied(GetRecipe(key), inputMaterials); } public static boolean IsSatisfied(Recipe recipe, ArrayList inputMaterials){ if(recipe==null) return false; //matから未投入素材リストを得る LinkedList mats=recipe.getMaterialList(); //投入素材数が違うのに条件を満たしているはずがないだろ! if(inputMaterials.size()!=mats.size()){ return false; } //投入素材リストを走査し、必要素材リストの中身を抜いていく LinkedList tmp=new LinkedList(inputMaterials); for(int i=0;i inputMaterials){ Recipe r=GetRecipe(key); ItemStack ret=r.getProduct(); IAlchemyProduct prod=((IAlchemyProduct) ret.getItem()); ArrayList characteristics;//完成品の持つ特性 //------------------------初期特性------------------------------ characteristics=prod.getDefaultCharacteristics(ret, instance.rand); //-----------------------引継ぎ特性----------------------------- LinkedList inherits=new LinkedList(); for(ItemStack mat : inputMaterials){ ArrayList aList=ReadCharacteristicFromNBT(mat.getTagCompound()); for(CharacteristicBase cb : aList){ if(prod.canInherit(ret, cb)) inherits.add(cb); } } //-----------------------引継ぎ判定----------------------------- int max=prod.getMaxInheritAmount(ret); for(int i=0;i inputMaterials){ ItemStack ret=recipe.getProduct().copy(); IAlchemyProduct prod=((IAlchemyProduct) ret.getItem()); ArrayList characteristics;//完成品の持つ特性 //------------------------初期特性------------------------------ characteristics=prod.getDefaultCharacteristics(ret, instance.rand); //-----------------------引継ぎ特性----------------------------- LinkedList inherits=new LinkedList(); for(ItemStack mat : inputMaterials){ ArrayList aList=ReadCharacteristicFromNBT(mat.getTagCompound()); for(CharacteristicBase cb : aList){ if(prod.canInherit(ret, cb)) inherits.add(cb); } } //-----------------------引継ぎ判定----------------------------- int max=prod.getMaxInheritAmount(ret); for(int i=0;i GetRecieps(){ return instance.recipes; } private static ProductExpPair cachedPEP; public static void RegisterProductExpPair(ItemStack p, double e){ instance.productExpPairs.add(new ProductExpPair(p, e)); } public static double GetProductExp(ItemStack p){ if(cachedPEP!=null && cachedPEP.isItemEqual(p)){ return cachedPEP.getExp(); } for(ProductExpPair pep : instance.productExpPairs){ if(pep.isItemEqual(p)){ cachedPEP=pep; return pep.getExp(); } } return 0; } private static ItemStack cachedBasketItem; public static void RegisterBasketItem(ItemStack itemStack){ instance.basketItems.add(itemStack); } public static boolean isBasketItem(ItemStack itemStack){ if(cachedBasketItem!=null && cachedBasketItem.isItemEqual(itemStack)) return true; for(ItemStack is : instance.basketItems){ if(is.isItemEqual(itemStack)){ cachedBasketItem=is; return true; } } return false; } //------------------------------------------------------------------------------------- public static class AppraisalItemStack{ private boolean isOre; private int oreId; private ItemStack itemStack; public AppraisalItemStack(ItemStack item){ isOre=false; itemStack=item; } public AppraisalItemStack(String oreId){ isOre=true; this.oreId= OreDictionary.getOreID(oreId); } public boolean isItemEqual(ItemStack m){ if (isOre){ int[] ids=OreDictionary.getOreIDs(m); for(int i : ids){ if(i==oreId) return true; } return false; } else{ return itemStack.isItemEqual(m); } } public ItemStack getItemStack(){ if(itemStack==null && isOre){ itemStack=OreDictionary.getOres(OreDictionary.getOreName(oreId)).get(0).copy(); } return itemStack; } @Override public boolean equals(Object obj){ if(obj instanceof AppraisalItemStack){ AppraisalItemStack ais=(AppraisalItemStack)obj; if(isOre!=ais.isOre) return false; return isOre?oreId==ais.oreId:itemStack.isItemEqual(ais.itemStack); } return false; } } public static class WeightedItemStack{ private int weight; private ItemStack itemStack; public WeightedItemStack(int w, ItemStack stack){ weight=w; itemStack=stack; } public int getWeight(){ return weight; } public ItemStack getItemStack(){ return itemStack; } } public static class Recipe{ protected int level; protected float prob; protected ItemStack key; protected ItemStack output; protected String[] materials; public Recipe(int level, float prob, ItemStack key, ItemStack output, String ... materials){ this.level=level; this.prob=prob; this.key=key; this.output=output; this.materials=materials; } public ItemStack getKey(){ return key; } public boolean isKey(ItemStack itemStack){ return key.isItemEqual(itemStack); } public ItemStack getProduct(){ return output; } public int getLevel(){ return level; } public float getProb(){ return prob; } public LinkedList getMaterialList(){ LinkedList list=new LinkedList(); for(String n : materials) list.add(n); return list; } } public static class ProductExpPair{ public ItemStack product; public double exp; public ProductExpPair(ItemStack p, double e){ product=p; exp=e; } public boolean isItemEqual(ItemStack item){ return product.isItemEqual(item); } public double getExp(){ return exp; } } public static class ItemPair{ private ItemStack item1; private ItemStack item2; public ItemPair(ItemStack i1, ItemStack i2){ item1=i1; item2=i2; } public ItemStack getItem1(){ return item1; } public ItemStack getItem2(){ return item2; } } }