diff --git a/build.gradle b/build.gradle index 6c38ab3..d41d2d7 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ repositories { dependencies { implementation "thaumcraft:Thaumcraft:1.7.10-4.2.3.5:deobf" - implementation "dev.tilera:auracore:1.5.0:deobf" + implementation "dev.tilera:auracore:1.6.0:deobf" implementation "com.github.tox1cozZ:mixin-booter-legacy:1.1.2" } diff --git a/src/main/java/net/anvilcraft/classiccasting/CCItems.java b/src/main/java/net/anvilcraft/classiccasting/CCItems.java index 05b02a2..801642f 100644 --- a/src/main/java/net/anvilcraft/classiccasting/CCItems.java +++ b/src/main/java/net/anvilcraft/classiccasting/CCItems.java @@ -3,6 +3,7 @@ package net.anvilcraft.classiccasting; import cpw.mods.fml.common.registry.GameRegistry; import net.anvilcraft.classiccasting.items.ItemAuraCompass; import net.anvilcraft.classiccasting.items.ItemPortableHole; +import net.anvilcraft.classiccasting.items.ItemResearchNotes; import net.anvilcraft.classiccasting.items.wands.ItemHellrod; import net.anvilcraft.classiccasting.items.wands.ItemWandCastingAdept; import net.anvilcraft.classiccasting.items.wands.ItemWandCastingApprentice; @@ -29,6 +30,8 @@ public class CCItems { public static Item wandLightning; public static Item wandTrade; + public static Item researchNotes; + public static void init() { portableHole = new ItemPortableHole(); auraCompass = new ItemAuraCompass(); @@ -44,6 +47,8 @@ public class CCItems { wandLightning = new ItemWandLightning(); wandTrade = new ItemWandTrade(); + researchNotes = new ItemResearchNotes(); + GameRegistry.registerItem(portableHole, "portableHole"); GameRegistry.registerItem(auraCompass, "auraCompass"); @@ -57,5 +62,7 @@ public class CCItems { GameRegistry.registerItem(wandHellrod, "wandHellrod"); GameRegistry.registerItem(wandLightning, "wandLightning"); GameRegistry.registerItem(wandTrade, "wandTrade"); + + GameRegistry.registerItem(researchNotes, "researchNotes"); } } diff --git a/src/main/java/net/anvilcraft/classiccasting/ClassicCasting.java b/src/main/java/net/anvilcraft/classiccasting/ClassicCasting.java index 6279707..3959c2d 100644 --- a/src/main/java/net/anvilcraft/classiccasting/ClassicCasting.java +++ b/src/main/java/net/anvilcraft/classiccasting/ClassicCasting.java @@ -7,7 +7,9 @@ import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.registry.EntityRegistry; +import dev.tilera.auracore.api.research.ResearchTableExtensionRegistry; import net.anvilcraft.classiccasting.entities.EntityFrostShard; +import net.anvilcraft.classiccasting.research.ClassicResearchTableExtension; @Mod( modid = "classiccasting", @@ -49,6 +51,8 @@ public class ClassicCasting { Recipes.init(); proxy.init(); + + ResearchTableExtensionRegistry.registerResearchTableExtension(ClassicResearchTableExtension.class, true); } @Mod.EventHandler diff --git a/src/main/java/net/anvilcraft/classiccasting/items/ItemResearchNotes.java b/src/main/java/net/anvilcraft/classiccasting/items/ItemResearchNotes.java new file mode 100644 index 0000000..6e1bfc5 --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/items/ItemResearchNotes.java @@ -0,0 +1,134 @@ +package net.anvilcraft.classiccasting.items; + +import java.util.List; + +import cpw.mods.fml.common.registry.LanguageRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.anvilcraft.classiccasting.research.CCResearchManager; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.EnumRarity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IIcon; +import net.minecraft.world.World; +import thaumcraft.api.research.ResearchCategories; +import thaumcraft.api.research.ResearchItem; +import thaumcraft.common.Thaumcraft; +import thaumcraft.common.lib.network.PacketHandler; +import thaumcraft.common.lib.network.playerdata.PacketResearchComplete; +import thaumcraft.common.lib.research.ResearchManager; + +public class ItemResearchNotes extends Item { + @SideOnly(value=Side.CLIENT) + public IIcon iconNote; + @SideOnly(value=Side.CLIENT) + public IIcon iconNoteOver; + @SideOnly(value=Side.CLIENT) + public IIcon iconDiscovery; + @SideOnly(value=Side.CLIENT) + public IIcon iconDiscoveryOver; + + public ItemResearchNotes() { + super(); + this.setHasSubtypes(true); + this.setMaxDamage(0); + this.setMaxStackSize(1); + } + + @SideOnly(value=Side.CLIENT) + @Override + public void registerIcons(IIconRegister ir) { + this.iconNote = ir.registerIcon("thaumcraft:researchnotes"); + this.iconNoteOver = ir.registerIcon("thaumcraft:researchnotesoverlay"); + this.iconDiscovery = ir.registerIcon("thaumcraft:discovery"); + this.iconDiscoveryOver = ir.registerIcon("thaumcraft:discoveryoverlay"); + } + + @SideOnly(value=Side.CLIENT) + @Override + public IIcon getIcon(ItemStack stack, int par1) { + return par1 / 64 == 0 ? this.iconNote : this.iconDiscovery; + } + + @SideOnly(value=Side.CLIENT) + @Override + public IIcon getIconFromDamageForRenderPass(int par1, int renderPass) { + return renderPass == 0 ? (par1 / 64 == 0 ? this.iconNote : this.iconDiscovery) : (par1 / 64 == 0 ? this.iconNoteOver : this.iconDiscoveryOver); + } + + @Override + public ItemStack onItemRightClick(ItemStack stack, World par2World, EntityPlayer player) { + if (!par2World.isRemote && CCResearchManager.getData(stack).getTotalProgress() == 1.0f && !ResearchManager.isResearchComplete(player.getDisplayName(), CCResearchManager.getData((ItemStack)stack).key)) { + if (ResearchManager.doesPlayerHaveRequisites(player.getDisplayName(), CCResearchManager.getData((ItemStack)stack).key)) { + PacketHandler.INSTANCE.sendTo(new PacketResearchComplete(ResearchManager.getData((ItemStack)stack).key), (EntityPlayerMP)player); + Thaumcraft.proxy.getResearchManager().completeResearch(player, CCResearchManager.getData(stack).key); + String[] siblings = ResearchCategories.getResearch((String)ResearchManager.getData((ItemStack)stack).key).siblings; + if (siblings != null) { + for (String s : siblings) { + ResearchItem sibling = ResearchCategories.getResearch(s); + if (s == null) continue; + if (ResearchManager.isResearchComplete(player.getDisplayName(), sibling.key) || !ResearchManager.doesPlayerHaveRequisites(player.getDisplayName(), sibling.key)) continue; + PacketHandler.INSTANCE.sendTo(new PacketResearchComplete(sibling.key), (EntityPlayerMP)player); + Thaumcraft.proxy.getResearchManager().completeResearch(player, sibling.key); + } + } + --stack.stackSize; + par2World.playSoundAtEntity(player, "thaumcraft.learn", 0.75f, 1.0f); + } else { + player.addChatMessage(new ChatComponentText(LanguageRegistry.instance().getStringLocalization("tc.discoveryerror"))); + } + } + return stack; + } + + @Override + @SideOnly(value=Side.CLIENT) + public int getColorFromItemStack(ItemStack stack, int par2) { + int md = stack.getItemDamage(); + if (md >= 64) { + md -= 64; + } + //TODO: WTF + //return stack.getItemDamage() == 0 || par2 == 0 ? 0xFFFFFF : EnumTag.get((int)md).color; + return 0xFFFFFF; + } + + @Override + @SideOnly(value=Side.CLIENT) + public boolean requiresMultipleRenderPasses() { + return true; + } + + @Override + public boolean getShareTag() { + return true; + } + + @Override + public String getItemStackDisplayName(ItemStack itemstack) { + return itemstack.getItemDamage() < 64 ? LanguageRegistry.instance().getStringLocalization("item.researchnotes.name") : LanguageRegistry.instance().getStringLocalization("item.discovery.name"); + } + + @Override + public void addInformation(ItemStack stack, EntityPlayer par2EntityPlayer, List list, boolean par4) { + if (CCResearchManager.getData(stack).getTotalProgress() >= 0.2f) { + ResearchItem item = ResearchCategories.getResearch(ResearchManager.getData((ItemStack)stack).key); + if (item != null) + list.add(item.getName()); + } else { + list.add(LanguageRegistry.instance().getStringLocalization("tc.discoveryunknown")); + } + if (stack.getItemDamage() < 64 && CCResearchManager.getData(stack).getTotalProgress() > 0.333332f) { + list.add((int)(CCResearchManager.getData(stack).getTotalProgress() * 100.0f) + LanguageRegistry.instance().getStringLocalization("tc.discoveryprogress")); + } + } + + public EnumRarity getRarity(ItemStack itemstack) { + return itemstack.getItemDamage() < 64 ? EnumRarity.rare : EnumRarity.epic; + } +} + diff --git a/src/main/java/net/anvilcraft/classiccasting/research/CCResearchManager.java b/src/main/java/net/anvilcraft/classiccasting/research/CCResearchManager.java new file mode 100644 index 0000000..532f19c --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/research/CCResearchManager.java @@ -0,0 +1,219 @@ +package net.anvilcraft.classiccasting.research; + +import java.util.ArrayList; + +import net.anvilcraft.classiccasting.CCItems; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; +import thaumcraft.api.research.ResearchCategories; +import thaumcraft.api.research.ResearchCategoryList; +import thaumcraft.api.research.ResearchItem; +import thaumcraft.common.config.ConfigItems; +import thaumcraft.common.lib.research.ResearchManager; + +public class CCResearchManager { + + public static ItemStack createNote(ItemStack stack, String key) { + ResearchItem research = ResearchCategories.getResearch(key); + if (research == null) return null; + if (stack.stackTagCompound == null) { + stack.setTagCompound(new NBTTagCompound()); + } + if (!stack.stackTagCompound.hasKey("tcr")) { + stack.stackTagCompound.setTag("tcr", new NBTTagCompound()); + } + NBTTagCompound var3 = (NBTTagCompound) stack.stackTagCompound.getTag("tcr"); + var3.setString("project", key); + research.tags.writeToNBT(var3, "tags"); + NBTTagCompound progress = new NBTTagCompound(); + for(Aspect a : research.tags.getAspects()) { + progress.setInteger(a.getTag(), 0); + } + var3.setTag("progress", progress); + new AspectList().writeToNBT(var3, "failed"); + return stack; + } + + public static ResearchNoteData getData(ItemStack stack) { + ResearchNoteData var1 = new ResearchNoteData(); + if (stack.stackTagCompound == null) { + return var1; + } + if (!stack.stackTagCompound.hasKey("tcr")) { + return var1; + } + NBTTagCompound var3 = stack.stackTagCompound.getCompoundTag("tcr"); + if (!var3.hasKey("project") || !var3.hasKey("tags") || !var3.hasKey("progress") || !var3.hasKey("failed")) { + return var1; + } + + var1.key = var3.getString("project"); + var1.tags.readFromNBT(var3, "tags"); + NBTTagCompound progress = var3.getCompoundTag("progress"); + for(Aspect a : var1.tags.getAspects()) { + var1.progress.put(a, progress.getInteger(a.getTag())); + } + var1.failedTags.readFromNBT(var3, "failed"); + // WTF? + /* + boolean busted = false; + for (Aspect tt : var1.tags.getAspects()) { + if (tt != null) continue; + busted = true; + break; + } + if (!busted && var1.tags.length != ResearchList.getResearchTags(var1.key).length) { + busted = true; + } + if (busted) { + byte[] tt = var1.tags; + int[] tp = var1.progress; + var1.tags = ResearchList.getResearchTags(var1.key); + var1.progress = new int[ResearchList.getResearchTags(var1.key).length]; + var1.failedTags = new byte[64]; + for (int a = 0; a < var1.tags.length; ++a) { + for (int b = 0; b < tt.length; ++b) { + if (var1.tags[a] != tt[b]) continue; + var1.progress[a] = tp[b]; + } + } + }*/ + return var1; + } + + public static void updateData(ItemStack stack, ResearchNoteData data) { + + if (stack.stackTagCompound == null) { + stack.setTagCompound(new NBTTagCompound()); + } + if (!stack.stackTagCompound.hasKey("tcr")) { + stack.stackTagCompound.setTag("tcr", new NBTTagCompound()); + return; + } + NBTTagCompound var3 = (NBTTagCompound) stack.stackTagCompound.getTag("tcr"); + + var3.setString("project", data.key); + data.tags.writeToNBT(var3, "tags"); + NBTTagCompound progress = new NBTTagCompound(); + for (Aspect a : data.tags.getAspects()) { + if (data.progress.containsKey(a)) { + progress.setInteger(a.getTag(), data.progress.get(a)); + } else { + progress.setInteger(a.getTag(), 0); + } + } + var3.setTag("progress", progress); + data.failedTags.writeToNBT(var3, "failed"); + } + + public static void createResearchNoteForTable(ClassicResearchTableExtension table, String key) { + if (table.getStackInSlot(5) == null && table.getStackInSlot(6) != null && table.getStackInSlot(6).isItemEqual(new ItemStack(Items.paper))) { + table.decrStackSize(6, 1); + ResearchItem item = ResearchCategories.getResearch(key); + //int md = ResearchList.getResearchPrimaryTag(key); + int md = 0; + table.setInventorySlotContents(5, CCResearchManager.createNote(new ItemStack(CCItems.researchNotes, 1, md), key)); + table.markDirty(); + } + } + + public static String findMatchingResearch(EntityPlayer player, Aspect[] tags, short[] tagAmounts) { + int bestMatchNum = 0; + String bestMatch = null; + for (ResearchCategoryList cat : ResearchCategories.researchCategories.values()) { + for (ResearchItem research : cat.research.values()) { + if (research.isStub() || research.isLost() || ResearchManager.isResearchComplete(player.getDisplayName(), research.key) || !ResearchManager.doesPlayerHaveRequisites(player.getDisplayName(), research.key)) continue; + int match = 0; + for (int q = 0; q < 5; ++q) { + if (tags[q] == null || tagAmounts[q] <= 0 || research.tags.getAmount(tags[q]) <= 0) continue; + ++match; + } + if (match <= 0 || match <= bestMatchNum) continue; + bestMatchNum = match; + bestMatch = research.key; + } + } + return bestMatch; + } + + public static boolean progressTableResearch(World world, EntityPlayer researcher, ClassicResearchTableExtension table, ItemStack note, int baseChance, int baseLoss, Aspect[] inTags, short[] inTagAmounts) { + AspectList tags; + String key; + boolean progressed = false; + if (baseLoss <= 0) { + baseLoss = 1; + } + if (note.stackTagCompound == null && (key = CCResearchManager.findLostResearch(researcher)) != null) { + note = CCResearchManager.createNote(note, key); + } + ResearchNoteData data = CCResearchManager.getData(note); + ResearchItem research = ResearchCategories.getResearch(data.key); + if (research == null) return false; + if ((tags = research.tags.copy()) != null) { + boolean found; + for (Aspect tag : inTags) { + if (tag == null) continue; + found = false; + for (Aspect entry : tags.getAspects()) { + if (entry != tag) continue; + found = true; + break; + } + if (found || data.failedTags.getAmount(tag) >= 100) continue; + data.failedTags.add(tag, Math.round((float)(2 + world.rand.nextInt(baseLoss)) / 10.0f)); + } + for (Aspect tag : tags.getAspects()) { + found = false; + int entry; + for (entry = 0; entry < inTags.length; ++entry) { + if (inTags[entry] != tag) continue; + found = true; + break; + } + if (!found) continue; + float chance = (float)baseChance / 100.0f; + int tries = CCResearchManager.researchIterations(inTagAmounts[entry]); + if (tries == 0) { + tries = 1; + chance = (float)baseChance / 2.0f; + } + for (int a = 0; a < tries; ++a) { + if (!(world.rand.nextFloat() <= chance)) continue; + if (data.tags.getAmount(tag) <= 0 || data.progress.get(tag) >= research.tags.getAmount(tag)) break; + data.progress.put(tag, data.progress.get(tag) + 1); + chance *= 0.9f; + progressed = true; + continue; + } + } + CCResearchManager.updateData(note, data); + } else { + table.contents[5] = new ItemStack(ConfigItems.itemResource, 7 + world.rand.nextInt(3), 9); + } + return progressed; + } + + private static int researchIterations(int amount) { + return 1 + amount / 2; + } + + public static String findLostResearch(EntityPlayer player) { + String bestMatch = null; + ArrayList choices = new ArrayList(); + for(ResearchCategoryList cat : ResearchCategories.researchCategories.values()) { + for (ResearchItem research : cat.research.values()) { + if (research.isStub() || !research.isLost() || ResearchManager.isResearchComplete(player.getDisplayName(), research.key) || !ResearchManager.doesPlayerHaveRequisites(player.getDisplayName(), research.key)) continue; + choices.add(research.key); + } + } + if (choices.size() > 0) { + bestMatch = (String)choices.get(player.worldObj.rand.nextInt(choices.size())); + } + return bestMatch; + } +} diff --git a/src/main/java/net/anvilcraft/classiccasting/research/ClassicResearchTableExtension.java b/src/main/java/net/anvilcraft/classiccasting/research/ClassicResearchTableExtension.java new file mode 100644 index 0000000..a6442df --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/research/ClassicResearchTableExtension.java @@ -0,0 +1,585 @@ +package net.anvilcraft.classiccasting.research; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import dev.tilera.auracore.api.Aspects; +import dev.tilera.auracore.api.research.IResearchTable; +import dev.tilera.auracore.api.research.ResearchTableExtension; +import net.anvilcraft.classiccasting.CCItems; +import net.anvilcraft.classiccasting.items.ItemResearchNotes; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.monster.EntityBlaze; +import net.minecraft.entity.monster.EntityCreeper; +import net.minecraft.entity.monster.EntityGolem; +import net.minecraft.entity.monster.EntitySpider; +import net.minecraft.entity.passive.EntityAnimal; +import net.minecraft.entity.passive.EntitySheep; +import net.minecraft.entity.passive.EntityVillager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.potion.Potion; +import net.minecraft.util.AxisAlignedBB; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; +import thaumcraft.common.config.ConfigBlocks; +import thaumcraft.common.lib.crafting.ThaumcraftCraftingManager; + +public class ClassicResearchTableExtension extends ResearchTableExtension implements IInventory { + + public ItemStack[] contents = new ItemStack[7]; + public EntityPlayer researcher = null; + public boolean safe = true; + public int baseChance = 15; + public int baseLoss = 25; + public boolean recalc = false; + public Aspect[] tags = new Aspect[5]; + public short[] tagAmounts = new short[5]; + public float[] tagBonus = new float[5]; + private float maxTagBonus = 5.0f; + public ResearchNoteData data = null; + + public ClassicResearchTableExtension(IResearchTable researchTable) { + super(researchTable); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + nbt.setBoolean("Safe", this.safe); + NBTTagList var2 = new NBTTagList(); + for (int var3 = 0; var3 < this.contents.length; ++var3) { + if (this.contents[var3] == null) continue; + NBTTagCompound var4 = new NBTTagCompound(); + var4.setByte("Slot", (byte)var3); + this.contents[var3].writeToNBT(var4); + var2.appendTag(var4); + } + nbt.setTag("Inventory", var2); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + this.safe = nbt.getBoolean("Safe"); + NBTTagList var2 = nbt.getTagList("Inventory", 10); + this.contents = new ItemStack[this.getSizeInventory()]; + for (int var3 = 0; var3 < var2.tagCount(); ++var3) { + NBTTagCompound var4 = var2.getCompoundTagAt(var3); + int var5 = var4.getByte("Slot") & 0xFF; + if (var5 < 0 || var5 >= this.contents.length) continue; + this.contents[var5] = ItemStack.loadItemStackFromNBT((NBTTagCompound)var4); + } + } + + @Override + public void writeToPacket(NBTTagCompound nbt) { + nbt.setBoolean("safe", this.safe); + } + + @Override + public void readFromPacket(NBTTagCompound nbt) { + this.safe = nbt.getBoolean("safe"); + } + + @Override + public void onTick() { + if (this.recalc) { + this.recalculateTags(); + this.gatherResults(); + this.recalcBaseChance(); + this.recalc = false; + } + } + + @Override + public void markDirty() { + this.gatherResults(); + this.recalc = true; + } + + @Override + public boolean openGUI(EntityPlayer player) { + // TODO: Implement this + return false; + } + + @Override + public String getNBTKey() { + return "ccextension"; + } + + private void doResearch() { + short[] amounts = this.tagAmounts; + for (int a = 0; a < 5; ++a) { + int n = a; + amounts[n] = (short)(amounts[n] + Math.round(this.tagBonus[a])); + } + if (this.contents[5] == null) { + String key = CCResearchManager.findMatchingResearch(this.researcher, this.tags, amounts); + if (key != null) { + CCResearchManager.createResearchNoteForTable(this, key); + if (this.contents[5] != null) { + CCResearchManager.progressTableResearch(this.world, this.researcher, this, this.contents[5], this.baseChance, this.baseLoss, this.tags, amounts); + if (CCResearchManager.getData(this.contents[5]).getTotalProgress() == 1.0f) { + this.contents[5].setItemDamage(this.contents[5].getItemDamage() + 64); + } + } + } + } else if (this.contents[5].getItem() == CCItems.researchNotes && this.contents[5].getItemDamage() < 64) { + CCResearchManager.progressTableResearch(this.world, this.researcher, this, this.contents[5], this.baseChance, this.baseLoss, this.tags, amounts); + if (CCResearchManager.getData(this.contents[5]).getTotalProgress() == 1.0f) { + this.contents[5].setItemDamage(this.contents[5].getItemDamage() + 64); + } + } + this.researcher = null; + } + + public void startResearch() { + this.world.playSoundEffect((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, "random.click", 0.15f, 0.8f); + if (!this.world.isRemote) { + this.doResearch(); + int chance = this.baseLoss; + for (int a = 0; a < 5; ++a) { + if (this.contents[a] == null || this.world.rand.nextInt(100) >= chance) continue; + --this.contents[a].stackSize; + if (this.contents[a].stackSize != 0) continue; + this.contents[a] = null; + } + } + this.world.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); + this.markDirty(); + } + + public void toggleSafe() { + this.safe = !this.safe; + this.recalcBaseChance(); + this.world.playSoundEffect((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, "step.wood", 0.3f, 1.2f); + } + + public void gatherResults() { + this.data = null; + if (this.contents[5] != null && this.contents[5].getItem() instanceof ItemResearchNotes) { + this.data = CCResearchManager.getData(this.contents[5]); + } + } + + private void recalcBaseChance() { + /*this.baseChance = Config.resBaseSafeChance; + this.baseLoss = Config.resBaseSafeLoss; + if (!this.safe) { + this.baseChance = Config.resBaseUnsafeChance; + this.baseLoss = Config.resBaseUnsafeLoss; + }*/ + } + + private void recalculateTags() { + AspectList ot = new AspectList(); + for (int a = 0; a < 5; ++a) { + this.tags[a] = null; + this.tagAmounts[a] = 0; + this.tagBonus[a] = 0.0f; + if (this.contents[a] == null) continue; + AspectList t = ThaumcraftCraftingManager.getObjectTags(this.contents[a]); + if ((t = ThaumcraftCraftingManager.getBonusTags(this.contents[a], t)) == null || t.size() <= 0) continue; + for (Aspect tag : t.getAspects()) { + ot.merge(tag, t.getAmount(tag)); + } + } + if (ot.size() == 0) { + return; + } + ArrayList sortedTags = new ArrayList(); + block2: for (Aspect tag : ot.getAspects()) { + if (sortedTags.size() == 0) { + sortedTags.add(tag); + continue; + } + if (ot.getAmount(tag) > ot.getAmount((Aspect)((Object)sortedTags.get(0)))) { + sortedTags.add(0, tag); + continue; + } + for (int a = 1; a < sortedTags.size(); ++a) { + if (ot.getAmount(tag) <= ot.getAmount((Aspect)((Object)sortedTags.get(a)))) continue; + sortedTags.add(a, tag); + continue block2; + } + sortedTags.add(tag); + } + if (sortedTags.size() > 0) { + for (int a = 0; a < 5; ++a) { + if (sortedTags.size() > a && sortedTags.get(a) != null) { + this.tags[a] = sortedTags.get(a); + this.tagAmounts[a] = (short)ot.getAmount((Aspect)((Object)sortedTags.get(a))); + continue; + } + this.tags[a] = null; + this.tagAmounts[a] = 0; + } + } + this.recalculateBonus(); + } + + private void recalculateBonus() { + List ents; + if (!this.world.isDaytime() && this.world.getBlockLightValue(this.xCoord, this.yCoord + 1, this.zCoord) < 4 && !this.world.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord)) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.DARKNESS})); + } + if (this.world.isDaytime() && this.world.getBlockLightValue(this.xCoord, this.yCoord + 1, this.zCoord) > 11 && this.world.canBlockSeeTheSky(this.xCoord, this.yCoord + 1, this.zCoord)) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.LIGHT})); + } + if ((float)this.yCoord > (float)this.world.getActualHeight() * 0.5f) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.AIR})); + } + if ((float)this.yCoord > (float)this.world.getActualHeight() * 0.66f) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.AIR})); + } + if ((float)this.yCoord > (float)this.world.getActualHeight() * 0.75f) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.AIR})); + } + if (this.world.isRaining()) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.WEATHER})); + } + if (this.world.isThundering()) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.WEATHER, Aspect.ENERGY, Aspect.AIR})); + } + if ((ents = this.world.getEntitiesWithinAABB(EntityLivingBase.class, AxisAlignedBB.getBoundingBox((double)this.xCoord, (double)this.yCoord, (double)this.zCoord, (double)(this.xCoord + 1), (double)(this.yCoord + 1), (double)(this.zCoord + 1)).expand(15.0, 15.0, 15.0))).size() > 0) { + for (Object ent : ents) { + try { + if (((EntityLivingBase)ent).isAirBorne) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.FLIGHT})); + } + if (((EntityLivingBase)ent).getMaxHealth() - ((EntityLivingBase)ent).getHealth() > 0) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.FLESH})); + } + if (((EntityLivingBase)ent).isEntityUndead()) { + this.incrementTagBonus(0.3f, Arrays.asList(new Aspect[]{Aspect.DEATH, Aspects.EVIL})); + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.SOUL})); + } + if (((EntityLivingBase)ent).isPotionActive(Potion.poison)) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.POISON})); + } + if (((EntityLivingBase)ent).isPotionActive(Potion.regeneration)) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.HEAL})); + } + if (((EntityLivingBase)ent).isPotionActive(Potion.resistance)) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.ARMOR})); + } + if (((EntityLivingBase)ent).isPotionActive(Potion.nightVision)) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspects.VISION})); + } + if (((EntityLivingBase)ent).isPotionActive(Potion.confusion)) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspects.FLUX})); + } + if (ent instanceof EntitySpider) { + this.incrementTagBonus(0.3f, Arrays.asList(new Aspect[]{Aspects.INSECT})); + } + if (ent instanceof EntityAnimal) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.BEAST})); + } + if (ent instanceof EntitySheep) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.CLOTH})); + } + if (ent instanceof EntityPlayer) { + this.incrementTagBonus(0.4f, Arrays.asList(new Aspect[]{Aspects.CONTROL})); + } + if (ent instanceof EntityVillager) { + this.incrementTagBonus(0.3f, Arrays.asList(new Aspect[]{Aspects.CONTROL})); + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.EXCHANGE})); + } + if (ent instanceof EntityGolem) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.ARMOR, Aspect.WEAPON})); + } + if (ent instanceof EntityBlaze) { + this.incrementTagBonus(0.3f, Arrays.asList(new Aspect[]{Aspect.FIRE})); + } + if (!(ent instanceof EntityCreeper)) continue; + this.incrementTagBonus(0.3f, Arrays.asList(new Aspect[]{Aspects.DESTRUCTION, Aspects.FLUX})); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + for (int x = -10; x <= 10; ++x) { + for (int z = -10; z <= 10; ++z) { + for (int y = -10; y <= 10; ++y) { + if (y + this.yCoord <= 0 || y + this.yCoord >= this.world.getActualHeight()) continue; + Block bi = this.world.getBlock(x + this.xCoord, y + this.yCoord, z + this.zCoord); + int md = this.world.getBlockMetadata(x + this.xCoord, y + this.yCoord, z + this.zCoord); + Material bm = bi.getMaterial(); + if (bi == Blocks.jukebox) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspects.SOUND})); + continue; + } + if (bi == Blocks.beacon) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspects.CONTROL, Aspect.LIGHT})); + continue; + } + if (bi == Blocks.skull) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.MIND, Aspects.EVIL})); + continue; + } + if (bi == Blocks.anvil) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.CRAFT, Aspect.TOOL})); + continue; + } + if (bi == Blocks.diamond_block) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.CRYSTAL, Aspects.VALUABLE})); + continue; + } + if (bi == Blocks.glass_pane) { + this.incrementTagBonus(0.1f, Arrays.asList(new Aspect[]{Aspects.VISION})); + continue; + } + if (bi == Blocks.glass) { + this.incrementTagBonus(0.1f, Arrays.asList(new Aspect[]{Aspect.CRYSTAL})); + continue; + } + if (bi == Blocks.red_flower) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspects.FLOWER})); + continue; + } + if (bi == Blocks.yellow_flower) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspects.FLOWER})); + continue; + } + if (bi == Blocks.log) { + this.incrementTagBonus(0.1f, Arrays.asList(new Aspect[]{Aspect.TREE})); + continue; + } + if (bi == Blocks.crafting_table) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.CRAFT, Aspect.TOOL})); + continue; + } + if (bi == Blocks.stone_pressure_plate || bi == Blocks.wooden_pressure_plate) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.TRAP})); + continue; + } + if (bi == ConfigBlocks.blockJar && md == 1) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.MIND, Aspects.EVIL})); + continue; + } + if (bi == ConfigBlocks.blockJar) { + this.incrementTagBonus(0.33f, Arrays.asList(new Aspect[]{Aspect.TRAP})); + continue; + } + if (bi == Blocks.iron_block) { + this.incrementTagBonus(0.75f, Arrays.asList(new Aspect[]{Aspect.METAL})); + continue; + } + if (bi == Blocks.gold_block) { + this.incrementTagBonus(0.75f, Arrays.asList(new Aspect[]{Aspects.VALUABLE})); + continue; + } + if (bi == Blocks.brown_mushroom_block || bi == Blocks.red_mushroom_block || bi == Blocks.brown_mushroom || bi == Blocks.red_mushroom) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspects.FUNGUS})); + continue; + } + if (bi == Blocks.bookshelf) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.MIND})); + continue; + } + if (bi == Blocks.mob_spawner) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.BEAST, Aspect.CRAFT, Aspect.TRAP})); + continue; + } + if (bi == Blocks.chest) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.VOID})); + continue; + } + if (bi == Blocks.farmland) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.CROP})); + continue; + } + if (bi == Blocks.end_portal_frame) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.ELDRITCH})); + continue; + } + if (bi == Blocks.ender_chest) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.VOID})); + continue; + } + if (bm == Material.lava) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.FIRE, Aspects.ROCK})); + continue; + } + if (bm == Material.fire) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.FIRE})); + continue; + } + if (bi == Blocks.bedrock) { + this.incrementTagBonus(0.1f, Arrays.asList(new Aspect[]{Aspect.DARKNESS, Aspects.ROCK, Aspect.EARTH})); + continue; + } + if (bi == Blocks.deadbush) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.DEATH})); + continue; + } + if (bi == Blocks.enchanting_table) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.MAGIC})); + continue; + } + if (bm == Material.water) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.WATER})); + continue; + } + if (bi == Blocks.redstone_wire) { + this.incrementTagBonus(0.15f, Arrays.asList(new Aspect[]{Aspect.ENERGY, Aspect.MECHANISM})); + continue; + } + if (bi == Blocks.unpowered_repeater || bi == Blocks.powered_repeater) { + this.incrementTagBonus(0.25f, Arrays.asList(new Aspect[]{Aspect.ENERGY, Aspect.MECHANISM})); + continue; + } + if (bm == Material.portal) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.ELDRITCH, Aspect.VOID})); + continue; + } + if (bm == Material.cake) { + this.incrementTagBonus(0.25f, Arrays.asList(new Aspect[]{Aspect.LIFE})); + continue; + } + if (bm == Material.web) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspects.INSECT})); + continue; + } + if (bm == Material.tnt) { + this.incrementTagBonus(0.25f, Arrays.asList(new Aspect[]{Aspects.DESTRUCTION, Aspect.FIRE})); + continue; + } + if (bi == Blocks.piston) { + this.incrementTagBonus(0.3f, Arrays.asList(new Aspect[]{Aspect.MECHANISM, Aspect.MOTION})); + continue; + } + if (bi == Blocks.emerald_block) { + this.incrementTagBonus(1.0f, Arrays.asList(new Aspect[]{Aspect.MAGIC})); + continue; + } + if (bm == Material.dragonEgg) { + this.incrementTagBonus(2.0f, Arrays.asList(new Aspect[]{Aspect.ELDRITCH, Aspects.EVIL, Aspect.MAGIC})); + continue; + } + if (bm == Material.ice) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.COLD})); + continue; + } + if (bm == Material.plants) { + this.incrementTagBonus(0.2f, Arrays.asList(new Aspect[]{Aspect.PLANT})); + continue; + } + if (bm == Material.redstoneLight) { + this.incrementTagBonus(0.25f, Arrays.asList(new Aspect[]{Aspect.LIGHT})); + continue; + } + if (bi == Blocks.brewing_stand) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.MAGIC})); + continue; + } + if (bi == Blocks.cauldron) { + this.incrementTagBonus(0.5f, Arrays.asList(new Aspect[]{Aspect.WATER})); + continue; + } + if (bi != ConfigBlocks.blockMagicalLog || (md & 1) != 1) continue; + this.incrementTagBonus(0.15f, Arrays.asList(new Aspect[]{Aspects.PURE})); + } + } + } + } + + private void incrementTagBonus(float amt, List taglist) { + for (int a = 0; a < 5; ++a) { + if (this.tags[a] == null || !taglist.contains(this.tags[a]) || !(this.tagBonus[a] + amt <= this.maxTagBonus)) continue; + int n = a; + this.tagBonus[n] = this.tagBonus[n] + amt; + } + } + + @Override + public int getSizeInventory() { + return 7; + } + + @Override + public ItemStack getStackInSlot(int var1) { + return this.contents[var1]; + } + + @Override + public ItemStack decrStackSize(int var1, int var2) { + if (this.contents[var1] != null) { + if (this.contents[var1].stackSize <= var2) { + ItemStack var3 = this.contents[var1]; + this.contents[var1] = null; + this.markDirty(); + return var3; + } + ItemStack var3 = this.contents[var1].splitStack(var2); + if (this.contents[var1].stackSize == 0) { + this.contents[var1] = null; + } + this.markDirty(); + return var3; + } + return null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int var1) { + if (this.contents[var1] != null) { + ItemStack var2 = this.contents[var1]; + this.contents[var1] = null; + return var2; + } + return null; + } + + @Override + public void setInventorySlotContents(int var1, ItemStack var2) { + this.contents[var1] = var2; + if (var2 != null && var2.stackSize > this.getInventoryStackLimit()) { + var2.stackSize = this.getInventoryStackLimit(); + } + this.markDirty(); + } + + @Override + public String getInventoryName() { + return "Research Table"; + } + + @Override + public int getInventoryStackLimit() { + return 64; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) { + return this.world.getTileEntity(this.xCoord, this.yCoord, this.zCoord) != this.getResearchTable() ? false : var1.getDistanceSq((double)this.xCoord + 0.5, (double)this.yCoord + 0.5, (double)this.zCoord + 0.5) <= 64.0; + } + + @Override + public void openInventory() { + this.recalc = true; + } + + @Override + public void closeInventory() { + } + + @Override + public boolean hasCustomInventoryName() { + return false; + } + + @Override + public boolean isItemValidForSlot(int i, ItemStack itemstack) { + return true; + } + +} diff --git a/src/main/java/net/anvilcraft/classiccasting/research/ResearchNoteData.java b/src/main/java/net/anvilcraft/classiccasting/research/ResearchNoteData.java new file mode 100644 index 0000000..e5e4023 --- /dev/null +++ b/src/main/java/net/anvilcraft/classiccasting/research/ResearchNoteData.java @@ -0,0 +1,42 @@ +package net.anvilcraft.classiccasting.research; + +import java.util.HashMap; +import java.util.Map; + +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; +import thaumcraft.api.research.ResearchCategories; +import thaumcraft.api.research.ResearchItem; + +public class ResearchNoteData { + public String key; + public AspectList tags = new AspectList(); + public Map progress = new HashMap<>(); + public AspectList failedTags = new AspectList(); + + public float getTotalProgress() { + ResearchItem rr = ResearchCategories.getResearch(this.key); + if (rr == null) { + return 0.0f; + } + float totala = 0.0f; + float totalb = 0.0f; + for (Aspect a : tags.getAspects()) { + totala += (float)this.progress.get(a); + totalb += (float)rr.tags.getAmount(a); + } + return totala / totalb; + } + + public float getTagProgress(Aspect tag) { + ResearchItem rr = ResearchCategories.getResearch(this.key); + if (rr == null) { + return 0.0f; + } + for (Aspect a : tags.getAspects()) { + if (this.tags == null || tag != a) continue; + return (float)this.progress.get(a) / (float)rr.tags.getAmount(a); + } + return 0.0f; + } +}