diff --git a/CoFH_at.cfg b/CoFH_at.cfg new file mode 100644 index 0000000..19fe7ac --- /dev/null +++ b/CoFH_at.cfg @@ -0,0 +1,51 @@ +# NetherOres +public net.minecraft.entity.monster.EntityPigZombie func_70835_c(Lnet/minecraft/entity/Entity;)V # becomeAngryAt +public net.minecraft.entity.monster.EntitySilverfish field_70843_d # allySummonCooldown +public-f net.minecraft.init.Blocks field_150449_bY # oreNetherQuartz + +# MineFactory Reloaded +protected net.minecraft.util.WeightedRandomFishable * # need it all +public net.minecraft.entity.EntityList field_75624_e # classToIDMapping +public net.minecraft.entity.EntityList field_75622_f # stringToIDMapping +public net.minecraft.entity.monster.EntitySlime func_70799_a(I)V # setSlimeSize +public net.minecraft.entity.monster.EntityZombie func_82228_a(I)V # startConversion +public net.minecraft.entity.EntityLivingBase field_70718_bc # recentlyHit +public-f net.minecraft.init.Blocks field_150432_aD # ice +public-f net.minecraft.init.Blocks field_150410_aZ # glass_pane +public-f net.minecraft.init.Items field_151117_aB # milkBucket +protected net.minecraft.block.Block field_149770_b # unlocalizedName +public net.minecraft.server.management.PlayerManager func_72690_a(IIZ)Lnet/minecraft/server/management/PlayerManager$PlayerInstance; # getOrCreateChunkWatcher +public net.minecraft.server.management.PlayerManager$PlayerInstance +public net.minecraft.server.management.PlayerManager$PlayerInstance field_73263_b # playersWatchingChunk +public net.minecraft.entity.EntityLiving field_70728_aV # experienceValue +public net.minecraft.entity.EntityLiving field_82174_bp # equipmentDropChances + +# Thermal Expansion +public net.minecraft.entity.Entity field_83001_bt # invulnerable +public net.minecraft.entity.Entity field_70178_ae # isImmuneToFire +public net.minecraft.entity.player.EntityPlayer field_71074_e # itemInUse +public net.minecraft.server.management.ItemInWorldManager field_73094_o #durabilityRemainingOnBlock + +# PC Core +public net.minecraft.client.gui.GuiScreen field_146289_q # fontRenderer +public net.minecraft.client.gui.inventory.GuiContainer field_147003_i # guiLeft +public net.minecraft.client.gui.inventory.GuiContainer field_147009_r # guiTop +public net.minecraft.world.WorldServer field_73068_P # allPlayersSleeping + +# CoFH Core +protected net.minecraft.inventory.Container * # senseless to have private stuff here +protected net.minecraft.client.gui.inventory.GuiContainer * # senseless to have private stuff here +protected net.minecraft.client.gui.FontRenderer func_78280_d(Ljava/lang/String;I)Ljava/lang/String; # wrapFormattedStringToWidth +protected net.minecraft.client.gui.FontRenderer func_78255_a(Ljava/lang/String;Z)V # renderStringAtPos +public net.minecraft.entity.projectile.EntityFishHook * # (nearly) literally everything is private +protected net.minecraft.entity.player.EntityPlayer field_71072_f # itemInUseCount +public net.minecraft.item.ItemPickaxe field_150915_c # blocksEffectiveAgainst +public net.minecraft.item.ItemSpade field_150916_c # blocksEffectiveAgainst +public net.minecraft.item.ItemAxe field_150917_c # blocksEffectiveAgainst +public net.minecraft.util.RegistrySimple field_82596_a # registryObjects +public-f net.minecraft.util.RegistryNamespaced field_148759_a # underlyingIntegerMap +public net.minecraft.world.World field_72998_d # collidingBoundingBoxes + +# WorldProxy +public-f net.minecraft.world.World *()V # Doesn't matter what it is, we need it public +public-f net.minecraft.world.WorldServer *()V # Doesn't matter what it is, we need it public diff --git a/libs/CoFHCore-[1.7.10]3.0.0B9-40.jar b/libs/CoFHCore-[1.7.10]3.0.0B9-40.jar deleted file mode 100644 index 34fa3e5..0000000 Binary files a/libs/CoFHCore-[1.7.10]3.0.0B9-40.jar and /dev/null differ diff --git a/libs/CoFHCore-[1.7.10]3.0.0B9-89-dev.jar b/libs/CoFHCore-[1.7.10]3.0.0B9-89-dev.jar new file mode 100644 index 0000000..9b5ea27 Binary files /dev/null and b/libs/CoFHCore-[1.7.10]3.0.0B9-89-dev.jar differ diff --git a/libs/CoFHLib-[1.7.10]1.0.0B8-34.jar b/libs/CoFHLib-[1.7.10]1.0.0B8-34.jar deleted file mode 100644 index 7e8e347..0000000 Binary files a/libs/CoFHLib-[1.7.10]1.0.0B8-34.jar and /dev/null differ diff --git a/libs/CoFHLib-[1.7.10]1.0.0B9-60-dev.jar b/libs/CoFHLib-[1.7.10]1.0.0B9-60-dev.jar new file mode 100644 index 0000000..167891d Binary files /dev/null and b/libs/CoFHLib-[1.7.10]1.0.0B9-60-dev.jar differ diff --git a/libs/CodeChickenCore-1.7.10-1.0.4.29-dev (2).jar b/libs/CodeChickenCore-1.7.10-1.0.4.29-dev (2).jar new file mode 100644 index 0000000..40a38e3 Binary files /dev/null and b/libs/CodeChickenCore-1.7.10-1.0.4.29-dev (2).jar differ diff --git a/libs/CodeChickenLib-1.7.10-1.1.1.110-dev.jar b/libs/CodeChickenLib-1.7.10-1.1.1.110-dev.jar new file mode 100644 index 0000000..f7a9ecc Binary files /dev/null and b/libs/CodeChickenLib-1.7.10-1.1.1.110-dev.jar differ diff --git a/libs/Enchiridion-1.7.X-1.2b-dev.jar b/libs/Enchiridion-1.7.X-1.2b-dev.jar new file mode 100644 index 0000000..3e334ed Binary files /dev/null and b/libs/Enchiridion-1.7.X-1.2b-dev.jar differ diff --git a/libs/EnderIO-1.7.10-2.2.6.322-api.jar b/libs/EnderIO-1.7.10-2.2.6.322-api.jar new file mode 100644 index 0000000..aa92111 Binary files /dev/null and b/libs/EnderIO-1.7.10-2.2.6.322-api.jar differ diff --git a/libs/ForgeMultipart-1.7.10-1.1.1.320-src.jar b/libs/ForgeMultipart-1.7.10-1.1.1.320-src.jar new file mode 100644 index 0000000..a86c229 Binary files /dev/null and b/libs/ForgeMultipart-1.7.10-1.1.1.320-src.jar differ diff --git a/libs/MekanismAll-1.7.10-7.1.2.homebaked-dev.jar b/libs/MekanismAll-1.7.10-7.1.2.homebaked-dev.jar.d similarity index 100% rename from libs/MekanismAll-1.7.10-7.1.2.homebaked-dev.jar rename to libs/MekanismAll-1.7.10-7.1.2.homebaked-dev.jar.d diff --git a/libs/NotEnoughItems-1.7.10-1.0.4.83-dev.jar b/libs/NotEnoughItems-1.7.10-1.0.4.83-dev.jar new file mode 100644 index 0000000..da520d5 Binary files /dev/null and b/libs/NotEnoughItems-1.7.10-1.0.4.83-dev.jar differ diff --git a/libs/Thaumcraft-deobf-1.7.10-4.2.3.0.jar b/libs/Thaumcraft-deobf-1.7.10-4.2.3.0.jar deleted file mode 100644 index 1bdded9..0000000 Binary files a/libs/Thaumcraft-deobf-1.7.10-4.2.3.0.jar and /dev/null differ diff --git a/libs/ThermalExpansion-[1.7.10]4.0.0B5-dev-13.jar b/libs/ThermalExpansion-[1.7.10]4.0.0B8-23-dev.jar similarity index 85% rename from libs/ThermalExpansion-[1.7.10]4.0.0B5-dev-13.jar rename to libs/ThermalExpansion-[1.7.10]4.0.0B8-23-dev.jar index 9430f84..f530266 100644 Binary files a/libs/ThermalExpansion-[1.7.10]4.0.0B5-dev-13.jar and b/libs/ThermalExpansion-[1.7.10]4.0.0B8-23-dev.jar differ diff --git a/libs/ThermalFoundation-[1.7.10]1.0.0B3-dev-8 (1).jar b/libs/ThermalFoundation-[1.7.10]1.0.0RC1-20-dev.jar similarity index 90% rename from libs/ThermalFoundation-[1.7.10]1.0.0B3-dev-8 (1).jar rename to libs/ThermalFoundation-[1.7.10]1.0.0RC1-20-dev.jar index 3e8fa02..5e3d604 100644 Binary files a/libs/ThermalFoundation-[1.7.10]1.0.0B3-dev-8 (1).jar and b/libs/ThermalFoundation-[1.7.10]1.0.0RC1-20-dev.jar differ diff --git a/src/api/java/chylex/hee/api/AbstractAPI.java b/src/api/java/chylex/hee/api/AbstractAPI.java deleted file mode 100644 index 7a22e9e..0000000 --- a/src/api/java/chylex/hee/api/AbstractAPI.java +++ /dev/null @@ -1,11 +0,0 @@ -package chylex.hee.api; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.LoaderState; - -public class AbstractAPI{ - protected AbstractAPI(){} - - protected final void validate(){ - if (!Loader.instance().isInState(LoaderState.POSTINITIALIZATION))throw new IllegalStateException("Do not use HEE API outside post initialization!"); - } -} diff --git a/src/api/java/chylex/hee/api/DecompositionAPI.java b/src/api/java/chylex/hee/api/DecompositionAPI.java deleted file mode 100644 index a63dad2..0000000 --- a/src/api/java/chylex/hee/api/DecompositionAPI.java +++ /dev/null @@ -1,37 +0,0 @@ -package chylex.hee.api; -import net.minecraft.item.Item; -import chylex.hee.mechanics.misc.StardustDecomposition; - -/** - * API for Stardust and Decomposition Table (uncrafting). - */ -public final class DecompositionAPI extends AbstractAPI{ - DecompositionAPI(){} - - /** - * Blacklists an item and all of its damage values in the Decomposition Table. - * @param item Item to be banned. To ban a block, use {@link net.minecraft.item.Item#getItemFromBlock(net.minecraft.block.Block) getItemFromBlock(Block)} to convert it. - */ - public static void blacklistItem(Item item){ - blacklistItem(item,-1); - } - - /** - * Blacklists an item and selected damage values of it in the Decomposition Table. - * @param item Item to be banned. To ban a block, use {@link net.minecraft.item.Item#getItemFromBlock(net.minecraft.block.Block) getItemFromBlock(Block)} to convert it. - * @param blacklistedDamageValues Array of damage values to blacklist. - */ - public static void blacklistItem(Item item, int...blacklistedDamageValues){ - short[] damages = new short[blacklistedDamageValues.length]; - for(int a = 0; a < blacklistedDamageValues.length; a++)damages[a] = (short)blacklistedDamageValues[a]; - StardustDecomposition.addToBlacklist(item,damages); - } - - /** - * Blacklists items by parsing a string, which follows the same syntax rules as decompositionBlackList in configuration - {@code http://hardcore-ender-expansion.wikia.com/wiki/Configuration}. - * @param data String to parse. - */ - public static void blacklistItemFromString(String data){ - StardustDecomposition.addFromString(data); - } -} diff --git a/src/api/java/chylex/hee/api/EssenceAPI.java b/src/api/java/chylex/hee/api/EssenceAPI.java deleted file mode 100644 index a137a9f..0000000 --- a/src/api/java/chylex/hee/api/EssenceAPI.java +++ /dev/null @@ -1,44 +0,0 @@ -package chylex.hee.api; -import net.minecraft.item.ItemStack; -import chylex.hee.item.ItemList; -import chylex.hee.mechanics.essence.EssenceType; -import chylex.hee.mechanics.essence.handler.DragonEssenceHandler; -import chylex.hee.mechanics.essence.handler.dragon.AltarItemRecipe; - -/** - * API for Essences and Essence Altars. - */ -public final class EssenceAPI extends AbstractAPI{ - EssenceAPI(){} - - /** - * Adds an item exchange recipe to the Dragon Essence Altar. - * @param source ItemStack that will trigger the exchange. The stacks are compared using {@link ItemStack#isItemEqual(ItemStack) isItemEqual(ItemStack)}, if a different comparison method is needed, extend {@link chylex.hee.mechanics.essence.handler.dragon.AltarItemRecipe AltarItemRecipe}, override {@link chylex.hee.mechanics.essence.handler.dragon.AltarItemRecipe#isApplicable(ItemStack) isApplicable(ItemStack)} and register using {@link #addDragonItemRecipe(AltarItemRecipe)}. - * @param result Final ItemStack that is created after the exchange. - * @param cost Amount of Dragon Essence used, the final number may be lower if sockets are used. - */ - public void addDragonItemRecipe(ItemStack source, ItemStack result, int cost){ - validate(); - DragonEssenceHandler.recipes.add(new AltarItemRecipe(source,result,cost)); - } - - /** - * Adds an item exchange recipe to the Dragon Essence Altar. - * @param recipe Custom instance of AltarItemRecipe to use. - */ - public void addDragonItemRecipe(AltarItemRecipe recipe){ - validate(); - DragonEssenceHandler.recipes.add(recipe); - } - - /** - * Creates an ItemStack consisting of one essence of provided type. - * @param essenceType Type of essence. - * @return New ItemStack, or null if provided invalid value. - */ - public ItemStack createEssenceItemStack(EssenceType essenceType){ - validate(); - if (essenceType == null || essenceType == EssenceType.INVALID)return null; - return new ItemStack(ItemList.essence,1,essenceType.getItemDamage()); - } -} diff --git a/src/api/java/chylex/hee/api/HeeAPI.java b/src/api/java/chylex/hee/api/HeeAPI.java deleted file mode 100644 index 8834bd3..0000000 --- a/src/api/java/chylex/hee/api/HeeAPI.java +++ /dev/null @@ -1,42 +0,0 @@ -package chylex.hee.api; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.LoaderState; - -/** - * Main API class that contains and provides specific API instances. - */ -public final class HeeAPI{ - private static final EssenceAPI essenceAPI = new EssenceAPI(); - private static final WorldAPI worldAPI = new WorldAPI(); - private static final DecompositionAPI decompositionAPI = new DecompositionAPI(); - - /** - * @return API instance for Essences and Essence Altars. - */ - public static EssenceAPI essence(){ - validate(); - return essenceAPI; - } - - /** - * @return API instance for loot and new biomes in the End. - */ - public static WorldAPI world(){ - validate(); - return worldAPI; - } - - /** - * @return API instance for Stardust and Decomposition Table. - */ - public static DecompositionAPI decomposition(){ - validate(); - return decompositionAPI; - } - - private static void validate(){ - if (!Loader.instance().isInState(LoaderState.POSTINITIALIZATION))throw new IllegalStateException("Do not use HEE API outside post initialization!"); - } - - private HeeAPI(){} -} diff --git a/src/api/java/chylex/hee/api/WorldAPI.java b/src/api/java/chylex/hee/api/WorldAPI.java deleted file mode 100644 index 645ab2f..0000000 --- a/src/api/java/chylex/hee/api/WorldAPI.java +++ /dev/null @@ -1,104 +0,0 @@ -package chylex.hee.api; -import net.minecraft.entity.EntityLiving; -import chylex.hee.api.wrappers.LootList; -import chylex.hee.world.structure.island.biome.IslandBiomeBase; -import chylex.hee.world.structure.island.biome.IslandBiomeBurningMountains; -import chylex.hee.world.structure.island.biome.IslandBiomeEnchantedIsland; -import chylex.hee.world.structure.island.biome.IslandBiomeInfestedForest; -import chylex.hee.world.structure.island.biome.feature.forest.StructureSilverfishDungeon; -import chylex.hee.world.structure.tower.ComponentTower; -import chylex.hee.world.util.SpawnEntry; - -/** - * API for manipulating with new biomes and loot. - */ -public final class WorldAPI extends AbstractAPI{ - WorldAPI(){} - - /** - * Adds a mob spawning entry to specified biome. List of existing entries is in javadoc of each {@link Biome}. - * @param biome Biome to add the entry to. - * @param mobClass Class of the mob to spawn. - * @param maxAmount Maximum amount of mobs of this type that can exist on the island at one point in time. - * @param weight Weight of the spawn entry. - */ - public static void addMobToBiome(Biome biome, Class mobClass, int maxAmount, int weight){ - SpawnEntry entry = new SpawnEntry(mobClass,maxAmount,weight); - - switch(biome){ - case InfestedForestDeep: IslandBiomeBase.infestedForest.getSpawnEntries(IslandBiomeInfestedForest.DEEP).add(entry); break; - case InfestedForestRavaged: IslandBiomeBase.infestedForest.getSpawnEntries(IslandBiomeInfestedForest.RAVAGED).add(entry); break; - case InfestedForestRuins: IslandBiomeBase.infestedForest.getSpawnEntries(IslandBiomeInfestedForest.RUINS).add(entry); break; - case BurningMountainsScorching: IslandBiomeBase.burningMountains.getSpawnEntries(IslandBiomeBurningMountains.SCORCHING).add(entry); break; - case BurningMountainsMine: IslandBiomeBase.burningMountains.getSpawnEntries(IslandBiomeBurningMountains.MINE).add(entry); break; - case EnchantedIslandHomeland: IslandBiomeBase.enchantedIsland.getSpawnEntries(IslandBiomeEnchantedIsland.HOMELAND).add(entry); break; - default: - } - } - - /** - * Returns manipulatable loot list. Always cache the returned object if you plan on using it multiple times! - * @param loot Type of loot to use. - * @return Instance of {@link chylex.hee.api.wrappers.LootList LootList}, or null if {@code loot} parameter is null. - */ - public LootList getLootList(LootType loot){ - switch(loot){ - case DungeonTowerRegular: return new LootList(ComponentTower.lootTower); - case DungeonTowerFuel: return new LootList(ComponentTower.lootFuel); - case SilverfishDungeon: return new LootList(StructureSilverfishDungeon.lootDungeon); - default: return null; - } - } - - /** - * List of biomes that generate in the End. - */ - public static enum Biome{ - /** - * {@code Mob type, max amount, weight}
- * {@code EntitySilverfish, 35, 35}
- * {@code EntityMobInfestedBat, 8, 10}
- */ - InfestedForestDeep, - - InfestedForestRavaged, - - InfestedForestRuins, - - /** - * {@code Mob type, max amount, weight}
- * {@code EntityMobFireGolem, 14, 10}
- * {@code EntityMobScorchingLens, 10, 6}
- */ - BurningMountainsScorching, - - BurningMountainsMine, - - /** - * {@code Mob type, max amount, weight}
- * {@code EntityMobEnderGuardian, 9, 30}
- * {@code EntityMobBabyEnderman, 16, 20}
- */ - EnchantedIslandHomeland - } - - /** - * List of structures which generate loot inside them. - */ - public static enum LootType{ - /** - * Loot spawned inside chests, dispensers and similar containers in Dungeon Tower. - */ - DungeonTowerRegular, - - /** - * Loot spawned inside fuel slot of furnaces in Dungeon Tower. - */ - DungeonTowerFuel, - - /** - * Loot spawned inside Silverfish Dungeon chest. - */ - SilverfishDungeon - } -} diff --git a/src/api/java/chylex/hee/api/interfaces/IAcceptFieryEssence.java b/src/api/java/chylex/hee/api/interfaces/IAcceptFieryEssence.java deleted file mode 100644 index eaff2af..0000000 --- a/src/api/java/chylex/hee/api/interfaces/IAcceptFieryEssence.java +++ /dev/null @@ -1,18 +0,0 @@ -package chylex.hee.api.interfaces; - -/** - * Use this interface for any tile entities that should use Fiery Essence for a speed boost (or some other effect). - */ -public interface IAcceptFieryEssence{ - /** - * Returns how many times the Altar can boost the acceptor. Higher levels of essence should have higher boost. - * @param essenceLevel current level of essence - * @return amount of boosts available - */ - int getBoostAmount(int essenceLevel); - - /** - * Performs a single boost. This method is called multiple times, based on number returned by {@link #getBoostAmount(int)}. - */ - void boost(); -} diff --git a/src/api/java/chylex/hee/api/interfaces/IIgnoreEnderGoo.java b/src/api/java/chylex/hee/api/interfaces/IIgnoreEnderGoo.java deleted file mode 100644 index f2caac2..0000000 --- a/src/api/java/chylex/hee/api/interfaces/IIgnoreEnderGoo.java +++ /dev/null @@ -1,6 +0,0 @@ -package chylex.hee.api.interfaces; - -/** - * Ender Goo will not give bad effects to entities that implement this interface. - */ -public interface IIgnoreEnderGoo{} diff --git a/src/api/java/chylex/hee/api/wrappers/LootList.java b/src/api/java/chylex/hee/api/wrappers/LootList.java deleted file mode 100644 index 03ea2b7..0000000 --- a/src/api/java/chylex/hee/api/wrappers/LootList.java +++ /dev/null @@ -1,49 +0,0 @@ -package chylex.hee.api.wrappers; -import java.util.Iterator; -import net.minecraft.item.Item; -import chylex.hee.world.loot.IItemPostProcessor; -import chylex.hee.world.loot.LootItemStack; -import chylex.hee.world.loot.WeightedLootList; - -/** - * A wrapper class for simplified access to weighted loot list. - */ -public class LootList{ - private final WeightedLootList wrappedCollection; - - public LootList(WeightedLootList loot){ - this.wrappedCollection = loot; - } - - /** - * Adds new loot to the list. - * @param lootItemStack Instance of {@link chylex.hee.world.loot.LootItemStack LootItemStack} that holds basic generation properties. - */ - public void addLoot(LootItemStack lootItemStack){ - wrappedCollection.add(lootItemStack); - } - - /** - * Adds a post processor to the list, using anonymous class is suggested. - * @param postProcessor Handler that will modify item right before it's placed into the container. - */ - public void addPostProcessor(IItemPostProcessor postProcessor){ - wrappedCollection.addItemPostProcessor(postProcessor); - } - - /** - * Deletes a specific item from the list. Iteration is performed, and first instance of {@link chylex.hee.world.loot.LootItemStack LootItemStack} with specified item is removed. - * @param item Item to remove. - * @return True if any item was removed. - */ - public boolean removeItem(Item item){ - for(Iterator iter = wrappedCollection.iterator(); iter.hasNext();){ - if (iter.next().getItem() == item){ - iter.remove(); - return true; - } - } - - return false; - } -} diff --git a/src/api/java/thaumcraft/api/BlockCoordinates.java b/src/api/java/thaumcraft/api/BlockCoordinates.java new file mode 100644 index 0000000..27a28f8 --- /dev/null +++ b/src/api/java/thaumcraft/api/BlockCoordinates.java @@ -0,0 +1,108 @@ +package thaumcraft.api; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; + +public class BlockCoordinates implements Comparable +{ + public int x; + + /** the y coordinate */ + public int y; + + /** the z coordinate */ + public int z; + + public BlockCoordinates() {} + + public BlockCoordinates(int par1, int par2, int par3) + { + this.x = par1; + this.y = par2; + this.z = par3; + } + + public BlockCoordinates(TileEntity tile) + { + this.x = tile.xCoord; + this.y = tile.yCoord; + this.z = tile.zCoord; + } + + public BlockCoordinates(BlockCoordinates par1ChunkCoordinates) + { + this.x = par1ChunkCoordinates.x; + this.y = par1ChunkCoordinates.y; + this.z = par1ChunkCoordinates.z; + } + + public boolean equals(Object par1Obj) + { + if (!(par1Obj instanceof BlockCoordinates)) + { + return false; + } + else + { + BlockCoordinates coordinates = (BlockCoordinates)par1Obj; + return this.x == coordinates.x && this.y == coordinates.y && this.z == coordinates.z ; + } + } + + public int hashCode() + { + return this.x + this.y << 8 + this.z << 16; + } + + /** + * Compare the coordinate with another coordinate + */ + public int compareWorldCoordinate(BlockCoordinates par1) + { + return this.y == par1.y ? (this.z == par1.z ? this.x - par1.x : this.z - par1.z) : this.y - par1.y; + } + + public void set(int par1, int par2, int par3, int d) + { + this.x = par1; + this.y = par2; + this.z = par3; + } + + /** + * Returns the squared distance between this coordinates and the coordinates given as argument. + */ + public float getDistanceSquared(int par1, int par2, int par3) + { + float f = (float)(this.x - par1); + float f1 = (float)(this.y - par2); + float f2 = (float)(this.z - par3); + return f * f + f1 * f1 + f2 * f2; + } + + /** + * Return the squared distance between this coordinates and the ChunkCoordinates given as argument. + */ + public float getDistanceSquaredToWorldCoordinates(BlockCoordinates par1ChunkCoordinates) + { + return this.getDistanceSquared(par1ChunkCoordinates.x, par1ChunkCoordinates.y, par1ChunkCoordinates.z); + } + + public int compareTo(Object par1Obj) + { + return this.compareWorldCoordinate((BlockCoordinates)par1Obj); + } + + public void readNBT(NBTTagCompound nbt) { + this.x = nbt.getInteger("b_x"); + this.y = nbt.getInteger("b_y"); + this.z = nbt.getInteger("b_z"); + } + + public void writeNBT(NBTTagCompound nbt) { + nbt.setInteger("b_x",x); + nbt.setInteger("b_y",y); + nbt.setInteger("b_z",z); + } + +} diff --git a/src/api/java/thaumcraft/api/IArchitect.java b/src/api/java/thaumcraft/api/IArchitect.java new file mode 100644 index 0000000..c733af5 --- /dev/null +++ b/src/api/java/thaumcraft/api/IArchitect.java @@ -0,0 +1,27 @@ +package thaumcraft.api; + +import java.util.ArrayList; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public interface IArchitect { + + /** + * Returns a list of blocks that should be highlighted in world. + */ + public ArrayList getArchitectBlocks(ItemStack stack, World world, + int x, int y, int z, int side, EntityPlayer player); + + /** + * which axis should be displayed. + */ + public boolean showAxis(ItemStack stack, World world, EntityPlayer player, int side, EnumAxis axis); + + public enum EnumAxis { + X, // east / west + Y, // up / down + Z; // north / south + } +} diff --git a/src/api/java/thaumcraft/api/IGoggles.java b/src/api/java/thaumcraft/api/IGoggles.java new file mode 100644 index 0000000..2f53d81 --- /dev/null +++ b/src/api/java/thaumcraft/api/IGoggles.java @@ -0,0 +1,22 @@ +package thaumcraft.api; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; + +/** + * + * @author Azanor + * + * Equipped head slot 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); + +} diff --git a/src/api/java/thaumcraft/api/IRepairable.java b/src/api/java/thaumcraft/api/IRepairable.java new file mode 100644 index 0000000..48c6dff --- /dev/null +++ b/src/api/java/thaumcraft/api/IRepairable.java @@ -0,0 +1,13 @@ +package thaumcraft.api; + + + +/** + * @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 { + + +} diff --git a/src/api/java/thaumcraft/api/IRepairableExtended.java b/src/api/java/thaumcraft/api/IRepairableExtended.java new file mode 100644 index 0000000..3382712 --- /dev/null +++ b/src/api/java/thaumcraft/api/IRepairableExtended.java @@ -0,0 +1,17 @@ +package thaumcraft.api; + +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); + +} diff --git a/src/api/java/thaumcraft/api/IRunicArmor.java b/src/api/java/thaumcraft/api/IRunicArmor.java new file mode 100644 index 0000000..5dd3110 --- /dev/null +++ b/src/api/java/thaumcraft/api/IRunicArmor.java @@ -0,0 +1,22 @@ +package thaumcraft.api; + +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); + + +} diff --git a/src/api/java/thaumcraft/api/IScribeTools.java b/src/api/java/thaumcraft/api/IScribeTools.java new file mode 100644 index 0000000..8800fa5 --- /dev/null +++ b/src/api/java/thaumcraft/api/IScribeTools.java @@ -0,0 +1,14 @@ +package thaumcraft.api; + + +/** + * + * @author Azanor + * + * Interface used to identify scribing tool items used in research table + * + */ + +public interface IScribeTools { + +} diff --git a/src/api/java/thaumcraft/api/IVisDiscountGear.java b/src/api/java/thaumcraft/api/IVisDiscountGear.java new file mode 100644 index 0000000..3793ea3 --- /dev/null +++ b/src/api/java/thaumcraft/api/IVisDiscountGear.java @@ -0,0 +1,20 @@ +package thaumcraft.api; + +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); + +} diff --git a/src/api/java/thaumcraft/api/IWarpingGear.java b/src/api/java/thaumcraft/api/IWarpingGear.java new file mode 100644 index 0000000..e7415ab --- /dev/null +++ b/src/api/java/thaumcraft/api/IWarpingGear.java @@ -0,0 +1,22 @@ +package thaumcraft.api; + +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); + + +} diff --git a/src/api/java/thaumcraft/api/ItemApi.java b/src/api/java/thaumcraft/api/ItemApi.java new file mode 100644 index 0000000..25dda28 --- /dev/null +++ b/src/api/java/thaumcraft/api/ItemApi.java @@ -0,0 +1,70 @@ +package thaumcraft.api; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import cpw.mods.fml.common.FMLLog; + +/** + * @author Azanor + * + * This is used to gain access to the items in my mod. + * I only give some examples and it will probably still + * require a bit of work for you to get hold of everything you need. + * + */ +public class ItemApi { + + public static ItemStack getItem(String itemString, int meta) { + ItemStack item = null; + + try { + String itemClass = "thaumcraft.common.config.ConfigItems"; + Object obj = Class.forName(itemClass).getField(itemString).get(null); + if (obj instanceof Item) { + item = new ItemStack((Item) obj,1,meta); + } else if (obj instanceof ItemStack) { + item = (ItemStack) obj; + } + } catch (Exception ex) { + FMLLog.warning("[Thaumcraft] Could not retrieve item identified by: " + itemString); + } + + return item; + } + + public static ItemStack getBlock(String itemString, int meta) { + ItemStack item = null; + + try { + String itemClass = "thaumcraft.common.config.ConfigBlocks"; + Object obj = Class.forName(itemClass).getField(itemString).get(null); + if (obj instanceof Block) { + item = new ItemStack((Block) obj,1,meta); + } else if (obj instanceof ItemStack) { + item = (ItemStack) obj; + } + } catch (Exception ex) { + FMLLog.warning("[Thaumcraft] Could not retrieve block identified by: " + itemString); + } + + return item; + } + + /** + * + * Some examples + * + * Casting Wands: + * itemWandCasting + * + * Resources: + * itemEssence, itemWispEssence, itemResource, itemShard, itemNugget, + * itemNuggetChicken, itemNuggetBeef, itemNuggetPork, itemTripleMeatTreat + * + * Research: + * itemResearchNotes, itemInkwell, itemThaumonomicon + * + */ + +} diff --git a/src/api/java/thaumcraft/api/ItemRunic.java b/src/api/java/thaumcraft/api/ItemRunic.java new file mode 100644 index 0000000..80251f5 --- /dev/null +++ b/src/api/java/thaumcraft/api/ItemRunic.java @@ -0,0 +1,21 @@ +package thaumcraft.api; + +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; + } + +} diff --git a/src/api/java/thaumcraft/api/ThaumcraftApi.java b/src/api/java/thaumcraft/api/ThaumcraftApi.java new file mode 100644 index 0000000..fbf7880 --- /dev/null +++ b/src/api/java/thaumcraft/api/ThaumcraftApi.java @@ -0,0 +1,588 @@ +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.block.Block; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.Item.ToolMaterial; +import net.minecraft.item.ItemArmor.ArmorMaterial; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.EnumHelper; +import net.minecraftforge.oredict.OreDictionary; +import thaumcraft.api.aspects.Aspect; +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.IScanEventHandler; +import thaumcraft.api.research.ResearchCategories; +import thaumcraft.api.research.ResearchCategoryList; +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 { + + //Materials + public static ToolMaterial toolMatThaumium = EnumHelper.addToolMaterial("THAUMIUM", 3, 400, 7F, 2, 22); + public static ToolMaterial toolMatVoid = EnumHelper.addToolMaterial("VOID", 4, 150, 8F, 3, 10); + public static ToolMaterial toolMatElemental = EnumHelper.addToolMaterial("THAUMIUM_ELEMENTAL", 3, 1500, 10F, 3, 18); + public static ArmorMaterial armorMatThaumium = EnumHelper.addArmorMaterial("THAUMIUM", 25, new int[] { 2, 6, 5, 2 }, 25); + public static ArmorMaterial armorMatSpecial = EnumHelper.addArmorMaterial("SPECIAL", 25, new int[] { 1, 3, 2, 1 }, 25); + public static ArmorMaterial armorMatThaumiumFortress = EnumHelper.addArmorMaterial("FORTRESS", 40, new int[] { 3, 7, 6, 3 }, 25); + public static ArmorMaterial armorMatVoid = EnumHelper.addArmorMaterial("VOID", 10, new int[] { 3, 7, 6, 3 }, 10); + public static ArmorMaterial armorMatVoidFortress = EnumHelper.addArmorMaterial("VOIDFORTRESS", 18, new int[] { 4, 8, 7, 4 }, 10); + + //Enchantment references + public static int enchantFrugal; + public static int enchantPotency; + public static int enchantWandFortune; + public static int enchantHaste; + public static int enchantRepair; + + //Miscellaneous + /** + * Portable Hole Block-id Blacklist. + * Simply add the block-id's of blocks you don't want the portable hole to go through. + */ + public static ArrayList portableHoleBlackList = new ArrayList(); + + //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 scanEventhandlers = new ArrayList(); + public static ArrayList scanEntities = new ArrayList(); + 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; + } + + /** + * not really working atm, so ignore it for now + * @param scanEventHandler + */ + public static void registerScanEventhandler(IScanEventHandler scanEventHandler) { + scanEventhandlers.add(scanEventHandler); + } + + /** + * 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.
For example the normal and wither skeleton: + *
ThaumcraftApi.registerEntityTag("Skeleton", (new AspectList()).add(Aspect.DEATH, 5)); + *
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 smeltingBonus = new HashMap(); + + /** + * 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) { + String od = OreDictionary.getOreName( OreDictionary.getOreID(in)); + out = smeltingBonus.get(od); + } + 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); + 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); + 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 + * @param recipe An array of items required to craft this. Input itemstacks are NBT sensitive. + * Infusion crafting components are automatically "fuzzy" and the oredict will be checked for possible matches. + * + */ + public static InfusionRecipe addInfusionCraftingRecipe(String research, Object result, int instability, AspectList aspects, ItemStack input,ItemStack[] 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. + * Infusion crafting components are automatically "fuzzy" and the oredict will be checked for possible matches. + * + */ + public static InfusionEnchantmentRecipe addInfusionEnchantmentRecipe(String research, Enchantment enchantment, int instability, AspectList aspects, ItemStack[] 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 keyCache = new HashMap(); + + 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 (ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), (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 objectTags = new ConcurrentHashMap(); + public static ConcurrentHashMap groupedObjectTags = new ConcurrentHashMap(); + + /** + * 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:

+ * ThaumcraftApi.registerObjectTag(new ItemStack(Blocks.cobblestone), (new AspectList()).add(Aspect.ENTROPY, 1).add(Aspect.EARTH, 1)); + * @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:

+ * ThaumcraftApi.registerObjectTag(new ItemStack(Blocks.cobblestone), new int[]{0,1}, (new AspectList()).add(Aspect.ENTROPY, 1).add(Aspect.EARTH, 1)); + * @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(); + ArrayList 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:

+ * ThaumcraftApi.registerComplexObjectTag(new ItemStack(Blocks.cobblestone), (new AspectList()).add(Aspect.MECHANISM, 2).add(Aspect.MOTION, 4)); + * 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 = ThaumcraftApiHelper.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 = ThaumcraftApiHelper.getObjectAspects(item); + for(Aspect tag:aspects.getAspects()) { + tmp.merge(tag, tmp.getAmount(tag)); + } + registerObjectTag(item,tmp); + } + } + + //WARP /////////////////////////////////////////////////////////////////////////////////////// + private static HashMap warpMap = new HashMap(); + + /** + * 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; + } + } + } + } + + //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"); + */ +} diff --git a/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java b/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java new file mode 100644 index 0000000..77d5588 --- /dev/null +++ b/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java @@ -0,0 +1,467 @@ +package thaumcraft.api; + +import java.util.HashMap; +import java.util.Iterator; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +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.common.util.ForgeDirection; +import net.minecraftforge.oredict.OreDictionary; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; +import thaumcraft.api.aspects.IEssentiaTransport; + +public class ThaumcraftApiHelper { + + 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 allAspects= new HashMap(); + private static HashMap allCompoundAspects= new HashMap(); + + 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); + } + + + /** + * Use to subtract vis from a wand for most operations + * Wands store vis differently so "real" vis costs need to be multiplied by 100 before calling this method + * @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 for use by a crafting mechanic. Costs are calculated slightly + * differently and things like the frugal enchant is ignored + * Must NOT be multiplied by 100 - send the actual vis cost + * @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 + * @return was the vis successfully subtracted + */ + public static boolean consumeVisFromWandCrafting(ItemStack wand, EntityPlayer player, + AspectList cost, boolean doit) { + return ThaumcraftApi.internalMethods.consumeVisFromWandCrafting(wand, player, cost, doit); + } + + /** + * Subtract vis from a wand the player is carrying. Works like consumeVisFromWand in that actual vis + * costs should be multiplied by 100. 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); + } + + + /** + * This adds permanents or temporary 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 temporary add temporary warp instead of permanent + */ + public static void addWarpToPlayer(EntityPlayer player, int amount, boolean temporary) { + ThaumcraftApi.internalMethods.addWarpToPlayer(player, amount, temporary); + } + + /** + * This "sticky" warp to a player. Sticky warp is permanent warp that can be removed. + * It will automatically be synced clientside + * @param player the player using the wand + * @param amount how much warp to add. Can have negative amounts. + */ + public static void addStickyWarpToPlayer(EntityPlayer player, int amount) { + ThaumcraftApi.internalMethods.addStickyWarpToPlayer(player, 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); + Block block = world.getBlock(l, i1, j1); + int k1 = world.getBlockMetadata(l, i1, j1); + + MovingObjectPosition movingobjectposition2 = null; + 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; + } + + boolean flag5 = false; + byte b0; + + if (d3 < d4 && d3 < d5) + { + if (i > l) + { + b0 = 4; + } + else + { + b0 = 5; + } + + v1.xCoord = d0; + v1.yCoord += d7 * d3; + v1.zCoord += d8 * d3; + } + else if (d4 < d5) + { + if (j > i1) + { + b0 = 0; + } + else + { + b0 = 1; + } + + v1.xCoord += d6 * d4; + v1.yCoord = d1; + v1.zCoord += d8 * d4; + } + else + { + if (k > j1) + { + b0 = 2; + } + else + { + b0 = 3; + } + + v1.xCoord += d6 * d5; + v1.yCoord += d7 * d5; + v1.zCoord = d2; + } + + Vec3 vec32 = Vec3.createVectorHelper(v1.xCoord, v1.yCoord, v1.zCoord); + l = (int)(vec32.xCoord = (double)MathHelper.floor_double(v1.xCoord)); + + if (b0 == 5) + { + --l; + ++vec32.xCoord; + } + + i1 = (int)(vec32.yCoord = (double)MathHelper.floor_double(v1.yCoord)); + + if (b0 == 1) + { + --i1; + ++vec32.yCoord; + } + + j1 = (int)(vec32.zCoord = (double)MathHelper.floor_double(v1.zCoord)); + + if (b0 == 3) + { + --j1; + ++vec32.zCoord; + } + + Block block1 = world.getBlock(l, i1, j1); + int l1 = world.getBlockMetadata(l, i1, j1); + + if (!bool2 || block1.getCollisionBoundingBoxFromPool(world, l, i1, j1) != null) + { + if (block1.canCollideCheck(l1, bool1)) + { + MovingObjectPosition movingobjectposition1 = block1.collisionRayTrace(world, l, i1, j1, v1, v2); + + if (movingobjectposition1 != null) + { + return movingobjectposition1; + } + } + else + { + movingobjectposition2 = new MovingObjectPosition(l, i1, j1, b0, v1, false); + } + } + } + + return bool3 ? movingobjectposition2 : null; + } + else + { + return null; + } + } + else + { + return null; + } + } +} diff --git a/src/api/java/thaumcraft/api/TileThaumcraft.java b/src/api/java/thaumcraft/api/TileThaumcraft.java new file mode 100644 index 0000000..56ccae8 --- /dev/null +++ b/src/api/java/thaumcraft/api/TileThaumcraft.java @@ -0,0 +1,63 @@ +package thaumcraft.api; + +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; + +/** + * + * @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 nbttagcompound) + { + super.readFromNBT(nbttagcompound); + readCustomNBT(nbttagcompound); + } + + public void readCustomNBT(NBTTagCompound nbttagcompound) + { + //TODO + } + + @Override + public void writeToNBT(NBTTagCompound nbttagcompound) + { + super.writeToNBT(nbttagcompound); + writeCustomNBT(nbttagcompound); + } + + public void writeCustomNBT(NBTTagCompound nbttagcompound) + { + //TODO + } + + //Client Packet stuff + @Override + public Packet getDescriptionPacket() { + NBTTagCompound nbttagcompound = new NBTTagCompound(); + this.writeCustomNBT(nbttagcompound); + return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, -999, nbttagcompound); + } + + @Override + public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { + super.onDataPacket(net, pkt); + this.readCustomNBT(pkt.func_148857_g()); + } + + + + +} diff --git a/src/api/java/thaumcraft/api/WorldCoordinates.java b/src/api/java/thaumcraft/api/WorldCoordinates.java new file mode 100644 index 0000000..6c620af --- /dev/null +++ b/src/api/java/thaumcraft/api/WorldCoordinates.java @@ -0,0 +1,117 @@ +package thaumcraft.api; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; + +public class WorldCoordinates implements Comparable +{ + public int x; + + /** the y coordinate */ + public int y; + + /** the z coordinate */ + public int z; + + public int dim; + + public WorldCoordinates() {} + + public WorldCoordinates(int par1, int par2, int par3, int d) + { + this.x = par1; + this.y = par2; + this.z = par3; + this.dim = d; + } + + public WorldCoordinates(TileEntity tile) + { + this.x = tile.xCoord; + this.y = tile.yCoord; + this.z = tile.zCoord; + this.dim = tile.getWorldObj().provider.dimensionId; + } + + public WorldCoordinates(WorldCoordinates par1ChunkCoordinates) + { + this.x = par1ChunkCoordinates.x; + this.y = par1ChunkCoordinates.y; + this.z = par1ChunkCoordinates.z; + this.dim = par1ChunkCoordinates.dim; + } + + public boolean equals(Object par1Obj) + { + if (!(par1Obj instanceof WorldCoordinates)) + { + return false; + } + else + { + WorldCoordinates coordinates = (WorldCoordinates)par1Obj; + return this.x == coordinates.x && this.y == coordinates.y && this.z == coordinates.z && this.dim == coordinates.dim ; + } + } + + public int hashCode() + { + return this.x + this.y << 8 + this.z << 16 + this.dim << 24; + } + + /** + * Compare the coordinate with another coordinate + */ + public int compareWorldCoordinate(WorldCoordinates par1) + { + return this.dim == par1.dim ? ( + this.y == par1.y ? (this.z == par1.z ? this.x - par1.x : this.z - par1.z) : this.y - par1.y) : -1; + } + + public void set(int par1, int par2, int par3, int d) + { + this.x = par1; + this.y = par2; + this.z = par3; + this.dim = d; + } + + /** + * Returns the squared distance between this coordinates and the coordinates given as argument. + */ + public float getDistanceSquared(int par1, int par2, int par3) + { + float f = (float)(this.x - par1); + float f1 = (float)(this.y - par2); + float f2 = (float)(this.z - par3); + return f * f + f1 * f1 + f2 * f2; + } + + /** + * Return the squared distance between this coordinates and the ChunkCoordinates given as argument. + */ + public float getDistanceSquaredToWorldCoordinates(WorldCoordinates par1ChunkCoordinates) + { + return this.getDistanceSquared(par1ChunkCoordinates.x, par1ChunkCoordinates.y, par1ChunkCoordinates.z); + } + + public int compareTo(Object par1Obj) + { + return this.compareWorldCoordinate((WorldCoordinates)par1Obj); + } + + public void readNBT(NBTTagCompound nbt) { + this.x = nbt.getInteger("w_x"); + this.y = nbt.getInteger("w_y"); + this.z = nbt.getInteger("w_z"); + this.dim = nbt.getInteger("w_d"); + } + + public void writeNBT(NBTTagCompound nbt) { + nbt.setInteger("w_x",x); + nbt.setInteger("w_y",y); + nbt.setInteger("w_z",z); + nbt.setInteger("w_d",dim); + } + +} diff --git a/src/api/java/thaumcraft/api/aspects/Aspect.java b/src/api/java/thaumcraft/api/aspects/Aspect.java new file mode 100644 index 0000000..0ea13f5 --- /dev/null +++ b/src/api/java/thaumcraft/api/aspects/Aspect.java @@ -0,0 +1,201 @@ +package thaumcraft.api.aspects; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import org.apache.commons.lang3.text.WordUtils; + +public class Aspect { + + String tag; + Aspect[] components; + int color; + private String chatcolor; + ResourceLocation image; + int blend; + + /** + * 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); + } + + /** + * 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 getPrimalAspects() { + ArrayList primals = new ArrayList(); + Collection pa = aspects.values(); + for (Aspect aspect:pa) { + if (aspect.isPrimal()) primals.add(aspect); + } + return primals; + } + + public static ArrayList getCompoundAspects() { + ArrayList compounds = new ArrayList(); + Collection 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 aspects = new LinkedHashMap(); + + //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 + 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 WEATHER = new Aspect("tempestas",0xFFFFFF, new Aspect[] {AIR, WATER}); + 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, ORDER}); + public static final Aspect LIFE = new Aspect("victus",0xde0005, new Aspect[] {WATER, EARTH}); + public static final Aspect POISON = new Aspect("venenum",0x89f000, 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 ?? = new Aspect("??",0xcdccf4, new Aspect[] {AIR, EARTH}); +// 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 METAL = new Aspect("metallum",0xb5b5cd, new Aspect[] {EARTH, CRYSTAL}); + public static final Aspect DEATH = new Aspect("mortuus",0x887788, new Aspect[] {LIFE, ENTROPY}); + public static final Aspect FLIGHT = new Aspect("volatus",0xe7e7d7, new Aspect[] {AIR, MOTION}); + public static final Aspect DARKNESS = new Aspect("tenebrae",0x222222, new Aspect[] {VOID, LIGHT}); + public static final Aspect SOUL = new Aspect("spiritus",0xebebfb, new Aspect[] {LIFE, DEATH}); + public static final Aspect HEAL = new Aspect("sano",0xff2f34, new Aspect[] {LIFE, ORDER}); + public static final Aspect TRAVEL = new Aspect("iter",0xe0585b, new Aspect[] {MOTION, EARTH}); + public static final Aspect ELDRITCH = new Aspect("alienis",0x805080, new Aspect[] {VOID, DARKNESS}); + public static final Aspect MAGIC = new Aspect("praecantatio",0x9700c0, new Aspect[] {VOID, ENERGY}); + public static final Aspect AURA = new Aspect("auram",0xffc0ff, new Aspect[] {MAGIC, AIR}); + public static final Aspect TAINT = new Aspect("vitium",0x800080, new Aspect[] {MAGIC, ENTROPY}); + public static final Aspect SLIME = new Aspect("limus",0x01f800, new Aspect[] {LIFE, WATER}); + public static final Aspect PLANT = new Aspect("herba",0x01ac00, new Aspect[] {LIFE, EARTH}); + public static final Aspect TREE = new Aspect("arbor",0x876531, new Aspect[] {AIR, PLANT}); + public static final Aspect BEAST = new Aspect("bestia",0x9f6409, new Aspect[] {MOTION, LIFE}); + public static final Aspect FLESH = new Aspect("corpus",0xee478d, new Aspect[] {DEATH, BEAST}); + public static final Aspect UNDEAD = new Aspect("exanimis",0x3a4000, new Aspect[] {MOTION, 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 MAN = new Aspect("humanus",0xffd7c0, new Aspect[] {BEAST, MIND}); + public static final Aspect CROP = new Aspect("messis",0xe1b371, new Aspect[] {PLANT, MAN}); + public static final Aspect MINE = new Aspect("perfodio",0xdcd2d8, new Aspect[] {MAN, EARTH}); + public static final Aspect TOOL = new Aspect("instrumentum",0x4040ee, new Aspect[] {MAN, ORDER}); + public static final Aspect HARVEST = new Aspect("meto",0xeead82, new Aspect[] {CROP, TOOL}); + public static final Aspect WEAPON = new Aspect("telum",0xc05050, new Aspect[] {TOOL, FIRE}); + public static final Aspect ARMOR = new Aspect("tutamen",0x00c0c0, new Aspect[] {TOOL, EARTH}); + public static final Aspect HUNGER = new Aspect("fames",0x9a0305, new Aspect[] {LIFE, VOID}); + public static final Aspect GREED = new Aspect("lucrum",0xe6be44, new Aspect[] {MAN, HUNGER}); + public static final Aspect CRAFT = new Aspect("fabrico",0x809d80, new Aspect[] {MAN, TOOL}); + public static final Aspect CLOTH = new Aspect("pannus",0xeaeac2, new Aspect[] {TOOL, BEAST}); + 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}); + + +} diff --git a/src/api/java/thaumcraft/api/aspects/AspectList.java b/src/api/java/thaumcraft/api/aspects/AspectList.java new file mode 100644 index 0000000..b578141 --- /dev/null +++ b/src/api/java/thaumcraft/api/aspects/AspectList.java @@ -0,0 +1,292 @@ +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; +import thaumcraft.api.ThaumcraftApiHelper; + +public class AspectList implements Serializable { + + public LinkedHashMap aspects = new LinkedHashMap();//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 = ThaumcraftApiHelper.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 + */ + public Aspect[] getPrimalAspects() { + AspectList t = new AspectList(); + for (Aspect as:aspects.keySet()) { + if (as.isPrimal()) { + t.add(as,1); + } + } + Aspect[] q = new Aspect[1]; + return t.aspects.keySet().toArray(q); + } + + /** + * @return an array of all the aspects in this collection sorted by name + */ + public Aspect[] getAspectsSorted() { + try { + Aspect[] out = aspects.keySet().toArray(new Aspect[]{}); + boolean change=false; + do { + change=false; + for(int a=0;a0) { + 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[] getAspectsSortedAmount() { + try { + Aspect[] out = aspects.keySet().toArray(new Aspect[1]); + boolean change=false; + do { + change=false; + for(int a=0;a0 && 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 (amount0?aspects:null; + } + return null; + } + + @Override + public void setAspects(ItemStack itemstack, AspectList aspects) { + if (!itemstack.hasTagCompound()) itemstack.setTagCompound(new NBTTagCompound()); + aspects.writeToNBT(itemstack.getTagCompound()); + } +*/ \ No newline at end of file diff --git a/src/api/java/thaumcraft/api/aspects/IEssentiaTransport.java b/src/api/java/thaumcraft/api/aspects/IEssentiaTransport.java new file mode 100644 index 0000000..fecbc16 --- /dev/null +++ b/src/api/java/thaumcraft/api/aspects/IEssentiaTransport.java @@ -0,0 +1,100 @@ +package thaumcraft.api.aspects; + +import net.minecraftforge.common.util.ForgeDirection; + + +/** + * @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(ForgeDirection face); + + /** + * Is this side used to input essentia? + * @param face + * @return + */ + boolean canInputFrom(ForgeDirection face); + + /** + * Is this side used to output essentia? + * @param face + * @return + */ + boolean canOutputTo(ForgeDirection 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(ForgeDirection 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(ForgeDirection face); + + /** + * remove the specified amount of essentia from this transport tile + * @return how much was actually taken + */ + public int takeEssentia(Aspect aspect, int amount, ForgeDirection face); + + /** + * add the specified amount of essentia to this transport tile + * @return how much was actually added + */ + public int addEssentia(Aspect aspect, int amount, ForgeDirection face); + + /** + * What type of essentia this contains + * @param face + * @return + */ + public Aspect getEssentiaType(ForgeDirection face); + + /** + * How much essentia this block contains + * @param face + * @return + */ + public int getEssentiaAmount(ForgeDirection face); + + + + /** + * Essentia will not be drawn from this container unless the suction exceeds this amount. + * @return the amount + */ + public int getMinimumSuction(); + + /** + * Return true if you want the conduit to extend a little further into the block. + * Used by jars and alembics that have smaller than normal hitboxes + * @return + */ + boolean renderExtendedTube(); + + + +} + diff --git a/src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java b/src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java new file mode 100644 index 0000000..595b6e5 --- /dev/null +++ b/src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java @@ -0,0 +1,91 @@ +package thaumcraft.api.crafting; + +import java.util.ArrayList; + +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 key; + + public int hash; + + public CrucibleRecipe(String researchKey, ItemStack result, Object cat, AspectList tags) { + recipeOutput = result; + this.aspects = tags; + this.key = researchKey; + this.catalyst = cat; + if (cat instanceof String) { + this.catalyst = OreDictionary.getOres((String) cat); + } + String hc = researchKey + 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 ArrayList && ((ArrayList)catalyst).size()>0) { + for (ItemStack is :(ArrayList)catalyst) { + hc += is.toString(); + } + } + + hash = hc.hashCode(); + } + + + + public boolean matches(AspectList itags, ItemStack cat) { + if (catalyst instanceof ItemStack && + !ThaumcraftApiHelper.itemMatches((ItemStack) catalyst,cat,false)) { + return false; + } else + if (catalyst instanceof ArrayList && ((ArrayList)catalyst).size()>0) { + ItemStack[] ores = ((ArrayList)catalyst).toArray(new ItemStack[]{}); + if (!ThaumcraftApiHelper.containsMatch(false, new ItemStack[]{cat},ores)) return false; + } + if (itags==null) return false; + for (Aspect tag:aspects.getAspects()) { + if (itags.getAmount(tag))catalyst).size()>0) { + ItemStack[] ores = ((ArrayList)catalyst).toArray(new ItemStack[]{}); + if (ThaumcraftApiHelper.containsMatch(false, new ItemStack[]{cat},ores)) 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; + } + + +} diff --git a/src/api/java/thaumcraft/api/crafting/IArcaneRecipe.java b/src/api/java/thaumcraft/api/crafting/IArcaneRecipe.java new file mode 100644 index 0000000..bb5036d --- /dev/null +++ b/src/api/java/thaumcraft/api/crafting/IArcaneRecipe.java @@ -0,0 +1,35 @@ +package thaumcraft.api.crafting; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import thaumcraft.api.aspects.AspectList; + +public interface IArcaneRecipe +{ + + + /** + * Used to check if a recipe matches current crafting inventory + * @param player + */ + boolean matches(IInventory var1, World world, EntityPlayer player); + + /** + * Returns an Item that is the result of this recipe + */ + ItemStack getCraftingResult(IInventory var1); + + /** + * Returns the size of the recipe area + */ + int getRecipeSize(); + + ItemStack getRecipeOutput(); + AspectList getAspects(); + AspectList getAspects(IInventory var1); + String getResearch(); + + +} diff --git a/src/api/java/thaumcraft/api/crafting/IInfusionStabiliser.java b/src/api/java/thaumcraft/api/crafting/IInfusionStabiliser.java new file mode 100644 index 0000000..d137ff2 --- /dev/null +++ b/src/api/java/thaumcraft/api/crafting/IInfusionStabiliser.java @@ -0,0 +1,19 @@ +package thaumcraft.api.crafting; + +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, int x, int y, int z); + +} diff --git a/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java b/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java new file mode 100644 index 0000000..773da34 --- /dev/null +++ b/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java @@ -0,0 +1,154 @@ +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 net.minecraftforge.oredict.OreDictionary; +import thaumcraft.api.ThaumcraftApiHelper; +import thaumcraft.api.aspects.AspectList; + +public class InfusionEnchantmentRecipe +{ + + public AspectList aspects; + public String research; + public ItemStack[] components; + public Enchantment enchantment; + public int recipeXP; + public int instability; + + public InfusionEnchantmentRecipe(String research, Enchantment input, int inst, + AspectList aspects2, ItemStack[] 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 input, ItemStack central, World world, EntityPlayer player) { + if (research.length()>0 && !ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), 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.enchantmentsList[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 ii = new ArrayList(); + for (ItemStack is:input) { + ii.add(is.copy()); + } + + for (ItemStack comp:components) { + boolean b=false; + for (int a=0;a input, ItemStack central, World world, EntityPlayer player) { + if (getRecipeInput()==null) return false; + + if (research.length()>0 && !ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), research)) { + return false; + } + + ItemStack i2 = central.copy(); + if (getRecipeInput().getItemDamage()==OreDictionary.WILDCARD_VALUE) { + i2.setItemDamage(OreDictionary.WILDCARD_VALUE); + } + + if (!areItemStacksEqual(i2, getRecipeInput(), true)) return false; + + ArrayList ii = new ArrayList(); + for (ItemStack is:input) { + ii.add(is.copy()); + } + + for (ItemStack comp:getComponents()) { + boolean b=false; + for (int a=0;a itemMap = new HashMap(); + + 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(IInventory var1){ return output.copy(); } + + @Override + public int getRecipeSize(){ return input.length; } + + @Override + public ItemStack getRecipeOutput(){ return output; } + + @Override + public boolean matches(IInventory inv, World world, EntityPlayer player) + { + if (research.length()>0 && !ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), 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(IInventory 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 = ThaumcraftApiHelper.getStackInRowAndColumn(inv, x, y); + + if (target instanceof ItemStack) + { + if (!checkItemEquals((ItemStack)target, slot)) + { + return false; + } + } + else if (target instanceof ArrayList) + { + boolean matched = false; + + for (ItemStack item : (ArrayList)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(IInventory inv) { + return aspects; + } + + @Override + public String getResearch() { + return research; + } +} diff --git a/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java b/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java new file mode 100644 index 0000000..3b1eaeb --- /dev/null +++ b/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java @@ -0,0 +1,161 @@ +package thaumcraft.api.crafting; + +import java.util.ArrayList; +import java.util.Iterator; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +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; + +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, Block result, AspectList aspects, Object... recipe){ this(research,new ItemStack(result),aspects, recipe); } + public ShapelessArcaneRecipe(String research, Item result, AspectList aspects, Object... recipe){ this(research,new ItemStack(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(IInventory var1){ return output.copy(); } + + @Override + public boolean matches(IInventory var1, World world, EntityPlayer player) + { + if (research.length()>0 && !ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), 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 ArrayList) + { + for (ItemStack item : (ArrayList)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(IInventory inv) { + return aspects; + } + + @Override + public String getResearch() { + return research; + } +} diff --git a/src/api/java/thaumcraft/api/damagesource/DamageSourceIndirectThaumcraftEntity.java b/src/api/java/thaumcraft/api/damagesource/DamageSourceIndirectThaumcraftEntity.java new file mode 100644 index 0000000..1562d05 --- /dev/null +++ b/src/api/java/thaumcraft/api/damagesource/DamageSourceIndirectThaumcraftEntity.java @@ -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; + } +} diff --git a/src/api/java/thaumcraft/api/damagesource/DamageSourceThaumcraft.java b/src/api/java/thaumcraft/api/damagesource/DamageSourceThaumcraft.java new file mode 100644 index 0000000..bb55672 --- /dev/null +++ b/src/api/java/thaumcraft/api/damagesource/DamageSourceThaumcraft.java @@ -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); + } + +} diff --git a/src/api/java/thaumcraft/api/entities/IEldritchMob.java b/src/api/java/thaumcraft/api/entities/IEldritchMob.java new file mode 100644 index 0000000..79fc75b --- /dev/null +++ b/src/api/java/thaumcraft/api/entities/IEldritchMob.java @@ -0,0 +1,5 @@ +package thaumcraft.api.entities; + +public interface IEldritchMob { + +} diff --git a/src/api/java/thaumcraft/api/entities/ITaintedMob.java b/src/api/java/thaumcraft/api/entities/ITaintedMob.java new file mode 100644 index 0000000..83fb1fc --- /dev/null +++ b/src/api/java/thaumcraft/api/entities/ITaintedMob.java @@ -0,0 +1,5 @@ +package thaumcraft.api.entities; + +public interface ITaintedMob { + +} diff --git a/src/api/java/thaumcraft/api/internal/DummyInternalMethodHandler.java b/src/api/java/thaumcraft/api/internal/DummyInternalMethodHandler.java new file mode 100644 index 0000000..9af8c30 --- /dev/null +++ b/src/api/java/thaumcraft/api/internal/DummyInternalMethodHandler.java @@ -0,0 +1,78 @@ +package thaumcraft.api.internal; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; + +public class DummyInternalMethodHandler implements IInternalMethodHandler { + + @Override + public void generateVisEffect(int dim, int x, int y, int z, int x2, int y2, int z2, int color) { + + } + + @Override + public boolean isResearchComplete(String username, String researchkey) { + return false; + } + + @Override + public boolean hasDiscoveredAspect(String username, Aspect aspect) { + return false; + } + + @Override + public AspectList getDiscoveredAspects(String username) { + return null; + } + + @Override + public ItemStack getStackInRowAndColumn(Object instance, int row, int column) { + return null; + } + + @Override + public AspectList getObjectAspects(ItemStack is) { + return null; + } + + @Override + public AspectList getBonusObjectTags(ItemStack is, AspectList ot) { + 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 consumeVisFromWandCrafting(ItemStack wand, + EntityPlayer player, AspectList cost, boolean doit) { + return false; + } + + @Override + public boolean consumeVisFromInventory(EntityPlayer player, AspectList cost) { + return false; + } + + @Override + public void addWarpToPlayer(EntityPlayer player, int amount, boolean temporary) { + } + + @Override + public void addStickyWarpToPlayer(EntityPlayer player, int amount) { + } + + + +} diff --git a/src/api/java/thaumcraft/api/internal/IInternalMethodHandler.java b/src/api/java/thaumcraft/api/internal/IInternalMethodHandler.java new file mode 100644 index 0000000..73fce66 --- /dev/null +++ b/src/api/java/thaumcraft/api/internal/IInternalMethodHandler.java @@ -0,0 +1,25 @@ +package thaumcraft.api.internal; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; + +public interface IInternalMethodHandler { + + public void generateVisEffect(int dim, int x, int y, int z, int x2, int y2, int z2, int color); + public boolean isResearchComplete(String username, String researchkey); + public ItemStack getStackInRowAndColumn(Object instance, int row, int column); + public AspectList getObjectAspects(ItemStack is); + public AspectList getBonusObjectTags(ItemStack is,AspectList ot); + public AspectList generateTags(Item item, int meta); + public boolean consumeVisFromWand(ItemStack wand, EntityPlayer player, AspectList cost, boolean doit, boolean crafting); + public boolean consumeVisFromWandCrafting(ItemStack wand,EntityPlayer player, AspectList cost, boolean doit); + public boolean consumeVisFromInventory(EntityPlayer player, AspectList cost); + public void addWarpToPlayer(EntityPlayer player, int amount,boolean temporary); + public void addStickyWarpToPlayer(EntityPlayer player, int amount); + public boolean hasDiscoveredAspect(String username, Aspect aspect); + public AspectList getDiscoveredAspects(String username); + +} diff --git a/src/api/java/thaumcraft/api/internal/WeightedRandomLoot.java b/src/api/java/thaumcraft/api/internal/WeightedRandomLoot.java new file mode 100644 index 0000000..4ac6ee7 --- /dev/null +++ b/src/api/java/thaumcraft/api/internal/WeightedRandomLoot.java @@ -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 lootBagCommon = new ArrayList(); + public static ArrayList lootBagUncommon = new ArrayList(); + public static ArrayList lootBagRare = new ArrayList(); + +} diff --git a/src/api/java/thaumcraft/api/nodes/INode.java b/src/api/java/thaumcraft/api/nodes/INode.java new file mode 100644 index 0000000..8c71414 --- /dev/null +++ b/src/api/java/thaumcraft/api/nodes/INode.java @@ -0,0 +1,53 @@ +package thaumcraft.api.nodes; + +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; +import thaumcraft.api.aspects.IAspectContainer; + +public interface INode extends IAspectContainer { + + /** + * Unique identifier to distinguish nodes. Normal node id's are based on world id and coordinates + * @return + */ + public String getId(); + + public AspectList getAspectsBase(); + + /** + * Return the type of node + * @return + */ + public NodeType getNodeType(); + + /** + * Set the type of node + * @return + */ + public void setNodeType(NodeType nodeType); + + /** + * Return the node modifier + * @return + */ + public void setNodeModifier(NodeModifier nodeModifier); + + /** + * Set the node modifier + * @return + */ + public NodeModifier getNodeModifier(); + + /** + * Return the maximum capacity of each aspect the node can hold + * @return + */ + public int getNodeVisBase(Aspect aspect); + + /** + * Set the maximum capacity of each aspect the node can hold + * @return + */ + public void setNodeVisBase(Aspect aspect, short nodeVisBase); + +} diff --git a/src/api/java/thaumcraft/api/nodes/IRevealer.java b/src/api/java/thaumcraft/api/nodes/IRevealer.java new file mode 100644 index 0000000..14a19b5 --- /dev/null +++ b/src/api/java/thaumcraft/api/nodes/IRevealer.java @@ -0,0 +1,22 @@ +package thaumcraft.api.nodes; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; + +/** + * + * @author Azanor + * + * Equipped head slot items that extend this class will make nodes visible in world. + * + */ + +public interface IRevealer { + + /* + * If this method returns true the nodes will be visible. + */ + public boolean showNodes(ItemStack itemstack, EntityLivingBase player); + + +} diff --git a/src/api/java/thaumcraft/api/nodes/NodeModifier.java b/src/api/java/thaumcraft/api/nodes/NodeModifier.java new file mode 100644 index 0000000..885b867 --- /dev/null +++ b/src/api/java/thaumcraft/api/nodes/NodeModifier.java @@ -0,0 +1,6 @@ +package thaumcraft.api.nodes; + +public enum NodeModifier +{ + BRIGHT, PALE, FADING +} \ No newline at end of file diff --git a/src/api/java/thaumcraft/api/nodes/NodeType.java b/src/api/java/thaumcraft/api/nodes/NodeType.java new file mode 100644 index 0000000..355324b --- /dev/null +++ b/src/api/java/thaumcraft/api/nodes/NodeType.java @@ -0,0 +1,6 @@ +package thaumcraft.api.nodes; + +public enum NodeType +{ + NORMAL, UNSTABLE, DARK, TAINTED, HUNGRY, PURE +} \ No newline at end of file diff --git a/src/api/java/thaumcraft/api/package-info.java b/src/api/java/thaumcraft/api/package-info.java new file mode 100644 index 0000000..cceaf89 --- /dev/null +++ b/src/api/java/thaumcraft/api/package-info.java @@ -0,0 +1,4 @@ +@API(owner = "Thaumcraft", apiVersion = "4.2.2.0", provides = "Thaumcraft|API") +package thaumcraft.api; + +import cpw.mods.fml.common.API; diff --git a/src/api/java/thaumcraft/api/potions/PotionFluxTaint.java b/src/api/java/thaumcraft/api/potions/PotionFluxTaint.java new file mode 100644 index 0000000..b950de0 --- /dev/null +++ b/src/api/java/thaumcraft/api/potions/PotionFluxTaint.java @@ -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 thaumcraft.api.damagesource.DamageSourceThaumcraft; +import thaumcraft.api.entities.ITaintedMob; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +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,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; + } + +} diff --git a/src/api/java/thaumcraft/api/potions/PotionVisExhaust.java b/src/api/java/thaumcraft/api/potions/PotionVisExhaust.java new file mode 100644 index 0000000..cd7fc18 --- /dev/null +++ b/src/api/java/thaumcraft/api/potions/PotionVisExhaust.java @@ -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 cpw.mods.fml.relauncher.Side; +import cpw.mods.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,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) { + + } + + +} diff --git a/src/api/java/thaumcraft/api/research/IScanEventHandler.java b/src/api/java/thaumcraft/api/research/IScanEventHandler.java new file mode 100644 index 0000000..d0efac5 --- /dev/null +++ b/src/api/java/thaumcraft/api/research/IScanEventHandler.java @@ -0,0 +1,9 @@ +package thaumcraft.api.research; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public interface IScanEventHandler { + ScanResult scanPhenomena(ItemStack stack, World world, EntityPlayer player); +} diff --git a/src/api/java/thaumcraft/api/research/ResearchCategories.java b/src/api/java/thaumcraft/api/research/ResearchCategories.java new file mode 100644 index 0000000..82309b3 --- /dev/null +++ b/src/api/java/thaumcraft/api/research/ResearchCategories.java @@ -0,0 +1,101 @@ +package thaumcraft.api.research; + +import java.util.Collection; +import java.util.LinkedHashMap; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import org.apache.logging.log4j.Level; + +import cpw.mods.fml.common.FMLLog; + +public class ResearchCategories { + + //Research + public static LinkedHashMap researchCategories = new LinkedHashMap (); + + /** + * @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 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, ResourceLocation icon, ResourceLocation background) { + if (getResearchList(key)==null) { + ResearchCategoryList rl = new ResearchCategoryList(icon, background); + 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; + } + } + } +} diff --git a/src/api/java/thaumcraft/api/research/ResearchCategoryList.java b/src/api/java/thaumcraft/api/research/ResearchCategoryList.java new file mode 100644 index 0000000..7eed010 --- /dev/null +++ b/src/api/java/thaumcraft/api/research/ResearchCategoryList.java @@ -0,0 +1,37 @@ +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 ResearchCategoryList(ResourceLocation icon, ResourceLocation background) { + this.icon = icon; + this.background = background; + } + + //Research + public Map research = new HashMap(); + + + + +} diff --git a/src/api/java/thaumcraft/api/research/ResearchItem.java b/src/api/java/thaumcraft/api/research/ResearchItem.java new file mode 100644 index 0000000..1d5fd8b --- /dev/null +++ b/src/api/java/thaumcraft/api/research/ResearchItem.java @@ -0,0 +1,369 @@ +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 RP in normal research difficulty. + */ + 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. + */ + private boolean isConcealed; + + /** + * Hidden research can only be discovered via scanning or knowledge fragments + */ + private boolean isHidden; + + /** + * This is the same as isHidden, except it cannot be discovered with knowledge fragments, only scanning. + */ + private boolean isLost; + + /** + * These research items will automatically unlock for all players on game start + */ + private boolean isAutoUnlock; + + /** + * Scanning these items will have a chance of revealing hidden knowledge in the thaumonomicon + */ + private ItemStack[] itemTriggers; + + /** + * Scanning these entities will have a chance of revealing hidden knowledge in the thaumonomicon + */ + private String[] entityTriggers; + + /** + * Scanning things with these aspects will have a chance of revealing hidden knowledge in the thaumonomicon + */ + private Aspect[] aspectTriggers; + + 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.setVirtual(); + + } + + public ResearchItem(String key, String category, AspectList tags, int col, int row, int complex, ResourceLocation icon) + { + this.key = key; + this.category = category; + this.tags = tags; + this.icon_resource = icon; + 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(String key, String category, AspectList tags, int col, int row, int complex, ItemStack icon) + { + this.key = key; + this.category = category; + this.tags = tags; + this.icon_item = icon; + this.icon_resource = 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 setLost() + { + this.isLost = true; + return this; + } + + public ResearchItem setConcealed() + { + this.isConcealed = true; + return this; + } + + public ResearchItem setHidden() + { + this.isHidden = true; + return this; + } + + public ResearchItem setVirtual() + { + this.isVirtual = 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 setItemTriggers(ItemStack... par) + { + this.itemTriggers = par; + return this; + } + + public ResearchItem setEntityTriggers(String... par) + { + this.entityTriggers = par; + return this; + } + + public ResearchItem setAspectTriggers(Aspect... par) + { + this.aspectTriggers = par; + return this; + } + + public ItemStack[] getItemTriggers() { + return itemTriggers; + } + + public String[] getEntityTriggers() { + return entityTriggers; + } + + public Aspect[] getAspectTriggers() { + return aspectTriggers; + } + + 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 isLost() + { + return this.isLost; + } + + public boolean isConcealed() + { + return this.isConcealed; + } + + 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 boolean isSecondary() { + return isSecondary; + } + + public ResearchItem setSecondary() { + this.isSecondary = true; + return this; + } + + public int getComplexity() { + return complexity; + } + + public ResearchItem setComplexity(int complexity) { + this.complexity = complexity; + return this; + } + + /** + * @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; + } + +} diff --git a/src/api/java/thaumcraft/api/research/ResearchPage.java b/src/api/java/thaumcraft/api/research/ResearchPage.java new file mode 100644 index 0000000..fdada84 --- /dev/null +++ b/src/api/java/thaumcraft/api/research/ResearchPage.java @@ -0,0 +1,193 @@ +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, + TEXT_CONCEALED, + 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 ItemStack 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 research this page will only be displayed if the player has discovered this research + * @param text this can (but does not have to) be a reference to a localization variable, not the actual text. + */ + public ResearchPage(String research, String text) { + this.type = PageType.TEXT_CONCEALED; + this.research = research; + 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.smelting().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; +// if (recipe.recipeOutput instanceof ItemStack) { +// this.recipeOutput = (ItemStack) recipe.recipeOutput; +// } else { +// this.recipeOutput = recipe.recipeInput; +// } + } + + /** + * @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; + } + + +} diff --git a/src/api/java/thaumcraft/api/research/ScanResult.java b/src/api/java/thaumcraft/api/research/ScanResult.java new file mode 100644 index 0000000..e1498f3 --- /dev/null +++ b/src/api/java/thaumcraft/api/research/ScanResult.java @@ -0,0 +1,39 @@ +package thaumcraft.api.research; + +import net.minecraft.entity.Entity; + +public class ScanResult { + public byte type = 0; //1=blocks,2=entities,3=phenomena + public int id; + public int meta; + public Entity entity; + public String phenomena; + + public ScanResult(byte type, int blockId, int blockMeta, Entity entity, + String phenomena) { + super(); + this.type = type; + this.id = blockId; + this.meta = blockMeta; + this.entity = entity; + this.phenomena = phenomena; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ScanResult) { + ScanResult sr = (ScanResult) obj; + if (type != sr.type) + return false; + if (type == 1 + && (id != sr.id || meta != sr.meta)) + return false; + if (type == 2 && entity.getEntityId() != sr.entity.getEntityId()) + return false; + if (type == 3 && !phenomena.equals(sr.phenomena)) + return false; + } + return true; + } + +} diff --git a/src/api/java/thaumcraft/api/visnet/TileVisNode.java b/src/api/java/thaumcraft/api/visnet/TileVisNode.java new file mode 100644 index 0000000..204879e --- /dev/null +++ b/src/api/java/thaumcraft/api/visnet/TileVisNode.java @@ -0,0 +1,188 @@ +package thaumcraft.api.visnet; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; + +import thaumcraft.api.TileThaumcraft; +import thaumcraft.api.WorldCoordinates; +import thaumcraft.api.aspects.Aspect; + +/** + * @author Azanor + * + * The tile entity used by nodes in the vis energy network. A node is either a source (like an aura node), + * a transport relay or vis receiver (like the infernal furnace). + * + */ +public abstract class TileVisNode extends TileThaumcraft { + + WeakReference parent = null; + ArrayList> children = new ArrayList>(); + + /** + * @return the WorldCoordinates location of where this node is located + */ + public WorldCoordinates getLocation() { + return new WorldCoordinates(this); + } + + /** + * @return the number of blocks away this node will check for parent nodes to connect to. + */ + public abstract int getRange(); + + /** + * @return true if this is the source or root node of the vis network. + */ + public abstract boolean isSource(); + + /** + * This method should never be called directly. Use VisNetHandler.drainVis() instead + * @param aspect what aspect to drain + * @param vis how much to drain + * @return how much was actually drained + */ + public int consumeVis(Aspect aspect, int vis) { + if (VisNetHandler.isNodeValid(getParent())) { + int out = getParent().get().consumeVis(aspect, vis); + if (out>0) { + triggerConsumeEffect(aspect); + } + return out; + } + return 0; + } + + public void removeThisNode() { + for (WeakReference n:getChildren()) { + if (n!=null && n.get()!=null) { + n.get().removeThisNode(); + } + } + + children = new ArrayList>(); + if (VisNetHandler.isNodeValid(this.getParent())) { + this.getParent().get().nodeRefresh=true; + } + this.setParent(null); + this.parentChanged(); + + if (this.isSource()) { + HashMap> sourcelist = VisNetHandler.sources.get(worldObj.provider.dimensionId); + if (sourcelist==null) { + sourcelist = new HashMap>(); + } + sourcelist.remove(getLocation()); + VisNetHandler.sources.put( worldObj.provider.dimensionId, sourcelist ); + } + + worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); + } + + + + @Override + public void invalidate() { + removeThisNode(); + super.invalidate(); + } + + public void triggerConsumeEffect(Aspect aspect) { } + + /** + * @return + */ + public WeakReference getParent() { + return parent; + } + + /** + * @return + */ + public WeakReference getRootSource() { + return VisNetHandler.isNodeValid(getParent()) ? + getParent().get().getRootSource() : this.isSource() ? + new WeakReference(this) : null; + } + + /** + * @param parent + */ + public void setParent(WeakReference parent) { + this.parent = parent; + } + + /** + * @return + */ + public ArrayList> getChildren() { + return children; + } + + @Override + public boolean canUpdate() { + return true; + } + + protected int nodeCounter = 0; + private boolean nodeRegged = false; + public boolean nodeRefresh = false; + + @Override + public void updateEntity() { + + if (!worldObj.isRemote && ((nodeCounter++) % 40==0 || nodeRefresh)) { + //check for changes + if (!nodeRefresh && children.size()>0) { + for (WeakReference n:children) { + if (n==null || n.get()==null || !VisNetHandler.canNodeBeSeen(this, n.get())) { + nodeRefresh=true; + break; + } + } + } + + //refresh linked nodes + if (nodeRefresh) { + for (WeakReference n:children) { + if (n.get()!=null) { + n.get().nodeRefresh=true; + } + } + children.clear(); + parent=null; + } + + //redo stuff + if (isSource() && !nodeRegged) { + VisNetHandler.addSource(getWorldObj(), this); + nodeRegged = true; + } else + if (!isSource() && !VisNetHandler.isNodeValid(getParent())) { + setParent(VisNetHandler.addNode(getWorldObj(), this)); + nodeRefresh=true; + } + + if (nodeRefresh) { + worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); + parentChanged(); + } + nodeRefresh=false; + } + + } + + public void parentChanged() { } + + /** + * @return the type of shard this is attuned to: + * none -1, air 0, fire 1, water 2, earth 3, order 4, entropy 5 + * Should return -1 for most implementations + */ + public byte getAttunement() { + return -1; + } + + +} diff --git a/src/api/java/thaumcraft/api/visnet/VisNetHandler.java b/src/api/java/thaumcraft/api/visnet/VisNetHandler.java new file mode 100644 index 0000000..7013d1c --- /dev/null +++ b/src/api/java/thaumcraft/api/visnet/VisNetHandler.java @@ -0,0 +1,275 @@ +package thaumcraft.api.visnet; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; + +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.MovingObjectPosition.MovingObjectType; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import thaumcraft.api.ThaumcraftApi; +import thaumcraft.api.ThaumcraftApiHelper; +import thaumcraft.api.WorldCoordinates; +import thaumcraft.api.aspects.Aspect; + +public class VisNetHandler { + + // NODE DRAINING + /** + * This method drains vis from a relay or source near the passed in + * location. The amount received can be less than the amount requested so + * take that into account. + * + * @param world + * @param x the x position of the draining block or entity + * @param y the y position of the draining block or entity + * @param z the z position of the draining block or entity + * @param aspect what aspect to drain + * @param amount how much to drain + * @return how much was actually drained + */ + public static int drainVis(World world, int x, int y, int z, Aspect aspect, int amount) { + + int drainedAmount = 0; + + WorldCoordinates drainer = new WorldCoordinates(x, y, z, + world.provider.dimensionId); + if (!nearbyNodes.containsKey(drainer)) { + calculateNearbyNodes(world, x, y, z); + } + + ArrayList> nodes = nearbyNodes.get(drainer); + if (nodes!=null && nodes.size()>0) + for (WeakReference noderef : nodes) { + + TileVisNode node = noderef.get(); + + if (node == null) continue; + + int a = node.consumeVis(aspect, amount); + drainedAmount += a; + amount -= a; + if (a>0) { + int color = Aspect.getPrimalAspects().indexOf(aspect); + generateVisEffect(world.provider.dimensionId, x, y, z, node.xCoord, node.yCoord, node.zCoord, color); + } + if (amount <= 0) { + break; + } + } + + return drainedAmount; + } + + public static void generateVisEffect(int dim, int x, int y, int z, int x2, int y2, int z2, int color) { + ThaumcraftApi.internalMethods.generateVisEffect(dim, x, y, z, x2, y2, z2, color); + } + + public static HashMap>> sources = new HashMap>>(); + + public static void addSource(World world, TileVisNode vs) { + HashMap> sourcelist = sources + .get(world.provider.dimensionId); + if (sourcelist == null) { + sourcelist = new HashMap>(); + } + sourcelist.put(vs.getLocation(), new WeakReference(vs)); + sources.put(world.provider.dimensionId, sourcelist); + nearbyNodes.clear(); + } + + public static boolean isNodeValid(WeakReference node) { + if (node == null || node.get() == null || node.get().isInvalid()) + return false; + return true; + } + + public static WeakReference addNode(World world, TileVisNode vn) { + WeakReference ref = new WeakReference(vn); + + HashMap> sourcelist = sources + .get(world.provider.dimensionId); + if (sourcelist == null) { + sourcelist = new HashMap>(); + return null; + } + + ArrayList nearby = new ArrayList(); + + for (WeakReference root : sourcelist.values()) { + if (!isNodeValid(root)) + continue; + + TileVisNode source = root.get(); + + float r = inRange(world, vn.getLocation(), source.getLocation(), + vn.getRange()); + if (r > 0) { + nearby.add(new Object[] { source, r - vn.getRange() * 2 }); + } + + nearby = findClosestNodes(vn, source, nearby); + cache.clear(); + } + + float dist = Float.MAX_VALUE; + TileVisNode closest = null; + if (nearby.size() > 0) { + for (Object[] o : nearby) { + if ((Float) o[1] < dist && + (vn.getAttunement() == -1 || ((TileVisNode) o[0]).getAttunement() == -1 || + vn.getAttunement() == ((TileVisNode) o[0]).getAttunement())//) { + && canNodeBeSeen(vn,(TileVisNode)o[0])) { + dist = (Float) o[1]; + closest = (TileVisNode) o[0]; + } + } + } + if (closest != null) { + closest.getChildren().add(ref); + nearbyNodes.clear(); + return new WeakReference(closest); + } + + return null; + } + + static ArrayList cache = new ArrayList(); + public static ArrayList findClosestNodes(TileVisNode target, + TileVisNode parent, ArrayList in) { + + if (cache.size() > 512 || cache.contains(new WorldCoordinates(parent))) return in; + cache.add(new WorldCoordinates(parent)); + + for (WeakReference childWR : parent.getChildren()) { + TileVisNode child = childWR.get(); + + if (child != null && !child.equals(target) && !child.equals(parent)) { + float r2 = inRange(child.getWorldObj(), child.getLocation(), + target.getLocation(), target.getRange()); + if (r2 > 0) { + in.add(new Object[] { child, r2 }); + } + + in = findClosestNodes(target, child, in); + } + } + return in; + } + + private static float inRange(World world, WorldCoordinates cc1, + WorldCoordinates cc2, int range) { + float distance = cc1.getDistanceSquaredToWorldCoordinates(cc2); + return distance > range * range ? -1 : distance; + } + + private static HashMap>> nearbyNodes = new HashMap>>(); + + private static void calculateNearbyNodes(World world, int x, int y, int z) { + + HashMap> sourcelist = sources + .get(world.provider.dimensionId); + if (sourcelist == null) { + sourcelist = new HashMap>(); + return; + } + + ArrayList> cn = new ArrayList>(); + WorldCoordinates drainer = new WorldCoordinates(x, y, z, + world.provider.dimensionId); + + ArrayList nearby = new ArrayList(); + + for (WeakReference root : sourcelist.values()) { + + if (!isNodeValid(root)) + continue; + + TileVisNode source = root.get(); + + TileVisNode closest = null; + float range = Float.MAX_VALUE; + + float r = inRange(world, drainer, source.getLocation(), + source.getRange()); + if (r > 0) { + range = r; + closest = source; + } + + ArrayList> children = new ArrayList>(); + children = getAllChildren(source,children); + + for (WeakReference child : children) { + TileVisNode n = child.get(); + if (n != null && !n.equals(root)) { + + float r2 = inRange(n.getWorldObj(), n.getLocation(), + drainer, n.getRange()); + if (r2 > 0 && r2 < range) { + range = r2; + closest = n; + } + } + } + + if (closest != null) { + + cn.add(new WeakReference(closest)); + } + } + + nearbyNodes.put(drainer, cn); + } + + private static ArrayList> getAllChildren(TileVisNode source, ArrayList> list) { + for (WeakReference child : source.getChildren()) { + TileVisNode n = child.get(); + if (n != null) { + list.add(child); + list = getAllChildren(n,list); + } + } + return list; + } + + public static boolean canNodeBeSeen(TileVisNode source,TileVisNode target) + { + MovingObjectPosition mop = ThaumcraftApiHelper.rayTraceIgnoringSource(source.getWorldObj(), + Vec3.createVectorHelper(source.xCoord+.5, source.yCoord+.5,source.zCoord+.5), + Vec3.createVectorHelper(target.xCoord+.5, target.yCoord+.5,target.zCoord+.5), + false, true, false); + return mop == null || (mop.typeOfHit==MovingObjectType.BLOCK && + mop.blockX==target.xCoord && mop.blockY==target.yCoord && mop.blockZ==target.zCoord); + } + + // public static HashMap> + // noderef = new HashMap>(); + // + // public static TileVisNode getClosestNodeWithinRadius(World world, int x, + // int y, int z, int radius) { + // TileVisNode out = null; + // WorldCoordinates wc = null; + // float cd = Float.MAX_VALUE; + // for (int sx = x - radius; sx <= x + radius; sx++) { + // for (int sy = y - radius; sy <= y + radius; sy++) { + // for (int sz = z - radius; sz <= z + radius; sz++) { + // wc = new WorldCoordinates(sx,sy,sz,world.provider.dimensionId); + // if (noderef.containsKey(wc)) { + // float d = wc.getDistanceSquared(x, y, z); + // if (d=types.length) { + FocusUpgradeType[] temp = new FocusUpgradeType[id+1]; + System.arraycopy(types, 0, temp, 0, id); + 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( 0, + new ResourceLocation("thaumcraft", "textures/foci/potency.png"), + "focus.upgrade.potency.name","focus.upgrade.potency.text", + new AspectList().add(Aspect.WEAPON,1)); + + public static FocusUpgradeType frugal = new FocusUpgradeType( 1, + new ResourceLocation("thaumcraft", "textures/foci/frugal.png"), + "focus.upgrade.frugal.name","focus.upgrade.frugal.text", + new AspectList().add(Aspect.HUNGER,1)); + + public static FocusUpgradeType treasure = new FocusUpgradeType( 2, + new ResourceLocation("thaumcraft", "textures/foci/treasure.png"), + "focus.upgrade.treasure.name","focus.upgrade.treasure.text", + new AspectList().add(Aspect.GREED,1)); + + public static FocusUpgradeType enlarge = new FocusUpgradeType( 3, + new ResourceLocation("thaumcraft", "textures/foci/enlarge.png"), + "focus.upgrade.enlarge.name","focus.upgrade.enlarge.text", + new AspectList().add(Aspect.TRAVEL,1)); + + public static FocusUpgradeType alchemistsfire = new FocusUpgradeType( 4, + new ResourceLocation("thaumcraft", "textures/foci/alchemistsfire.png"), + "focus.upgrade.alchemistsfire.name","focus.upgrade.alchemistsfire.text", + new AspectList().add(Aspect.ENERGY,1).add(Aspect.SLIME,1)); + + public static FocusUpgradeType alchemistsfrost = new FocusUpgradeType( 5, + 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( 6, + 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( 7, + 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( 8, + new ResourceLocation("thaumcraft", "textures/foci/silktouch.png"), + "focus.upgrade.silktouch.name","focus.upgrade.silktouch.text", + new AspectList().add(Aspect.GREED,1)); + + +} diff --git a/src/api/java/thaumcraft/api/wands/IWandRodOnUpdate.java b/src/api/java/thaumcraft/api/wands/IWandRodOnUpdate.java new file mode 100644 index 0000000..4ef8c84 --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/IWandRodOnUpdate.java @@ -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); +} diff --git a/src/api/java/thaumcraft/api/wands/IWandTriggerManager.java b/src/api/java/thaumcraft/api/wands/IWandTriggerManager.java new file mode 100644 index 0000000..7c299de --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/IWandTriggerManager.java @@ -0,0 +1,15 @@ +package thaumcraft.api.wands; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +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, + int x, int y, int z, int side, int event); + +} diff --git a/src/api/java/thaumcraft/api/wands/IWandable.java b/src/api/java/thaumcraft/api/wands/IWandable.java new file mode 100644 index 0000000..aeb9bac --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/IWandable.java @@ -0,0 +1,25 @@ +package thaumcraft.api.wands; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +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 int onWandRightClick(World world, ItemStack wandstack, EntityPlayer player, int x, int y, int z, int side, int md); + + public ItemStack onWandRightClick(World world, ItemStack wandstack, EntityPlayer player); + + public void onUsingWandTick(ItemStack wandstack, EntityPlayer player, int count); + + public void onWandStoppedUsing(ItemStack wandstack, World world, EntityPlayer player, int count); + +} diff --git a/src/api/java/thaumcraft/api/wands/ItemFocusBasic.java b/src/api/java/thaumcraft/api/wands/ItemFocusBasic.java new file mode 100644 index 0000000..18fc189 --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/ItemFocusBasic.java @@ -0,0 +1,270 @@ +package thaumcraft.api.wands; + +import java.text.DecimalFormat; +import java.util.LinkedHashMap; +import java.util.List; + +import net.minecraft.entity.Entity; +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.EnumChatFormatting; +import net.minecraft.util.IIcon; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public abstract class ItemFocusBasic extends Item { + + public ItemFocusBasic () + { + super(); + maxStackSize = 1; + canRepair=false; + this.setMaxDamage(0); + } + + public IIcon icon; + + @SideOnly(Side.CLIENT) + @Override + public IIcon getIconFromDamage(int par1) { + return icon; + } + + @Override + public boolean isDamageable() { + return false; + } + + @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.getAspectsSorted()) { + DecimalFormat myFormatter = new DecimalFormat("#####.##"); + String amount = myFormatter.format(al.getAmount(aspect)/100f); + 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 map = new LinkedHashMap(); + 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; + } + + /** + * What color will the focus orb be rendered on the held wand + */ + public abstract int getFocusColor(ItemStack focusstack); + + + /** + * Does the focus have ornamentation like the focus of the nine hells. Ornamentation is a standard icon rendered in a cross around the focus + */ + public IIcon getOrnament(ItemStack focusstack) { + // TODO Auto-generated method stub + return null; + } + + /** + * An icon to be rendered inside the focus itself + */ + public IIcon getFocusDepthLayerIcon(ItemStack focusstack) { + // TODO Auto-generated method stub + return null; + } + + 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=""; + for (short id:this.getAppliedUpgrades(focusstack)) { + out = out + id; + } + return out; + } + + + /** + * How much vis does this focus consume per activation. + */ + public abstract AspectList getVisCost(ItemStack focusstack); + + /** + * 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 abstract FocusUpgradeType[] getPossibleUpgradesByRank(ItemStack focusstack, int rank); + + /** + * 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; + } + + 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, int x, int y,int z, EntityPlayer player) { + // TODO Auto-generated method stub + return false; + } + + /** + * Internal helper methods + */ + private NBTTagList getFocusUpgradeTagList(ItemStack focusstack) + { + return focusstack.stackTagCompound == null ? null : focusstack.stackTagCompound.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); + } + } + + @Override + public void onUpdate(ItemStack stack, World world, Entity entity, int p_77663_4_, boolean p_77663_5_) { + if (stack.stackTagCompound !=null && stack.stackTagCompound.hasKey("ench")) { + stack.stackTagCompound.removeTag("ench"); + } + super.onUpdate(stack, world, entity, p_77663_4_, p_77663_5_); + } + + + +} diff --git a/src/api/java/thaumcraft/api/wands/StaffRod.java b/src/api/java/thaumcraft/api/wands/StaffRod.java new file mode 100644 index 0000000..e7ae90f --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/StaffRod.java @@ -0,0 +1,48 @@ +package thaumcraft.api.wands; + +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 StaffRod extends WandRod { + + boolean runes=false; + + public StaffRod(String tag, int capacity, ItemStack item, int craftCost) { + super(tag+"_staff", capacity, item, craftCost); + this.texture = new ResourceLocation("thaumcraft","textures/models/wand_rod_"+tag+".png"); + } + + public StaffRod(String tag, int capacity, ItemStack item, int craftCost, + IWandRodOnUpdate onUpdate, ResourceLocation texture) { + super(tag+"_staff", capacity, item, craftCost, onUpdate, texture); + } + + public StaffRod(String tag, int capacity, ItemStack item, int craftCost, + IWandRodOnUpdate onUpdate) { + super(tag+"_staff", capacity, item, craftCost, onUpdate); + this.texture = new ResourceLocation("thaumcraft","textures/models/wand_rod_"+tag+".png"); + } + + public StaffRod(String tag, int capacity, ItemStack item, int craftCost, + ResourceLocation texture) { + super(tag+"_staff", capacity, item, craftCost, texture); + } + + public boolean hasRunes() { + return runes; + } + + public void setRunes(boolean hasRunes) { + this.runes = hasRunes; + } + + +} diff --git a/src/api/java/thaumcraft/api/wands/WandCap.java b/src/api/java/thaumcraft/api/wands/WandCap.java new file mode 100644 index 0000000..17b4581 --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/WandCap.java @@ -0,0 +1,129 @@ +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; + + /** + * specifies a list of primal aspects that use the special discount figure instead of the normal discount. + */ + List 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 caps = new LinkedHashMap(); + + public WandCap (String tag, float discount, ItemStack item, int craftCost) { + this.setTag(tag); + this.baseCostModifier = discount; + this.specialCostModifierAspects = null; + texture = new ResourceLocation("thaumcraft","textures/models/wand_cap_"+getTag()+".png"); + this.item=item; + this.setCraftCost(craftCost); + caps.put(tag, this); + } + + public WandCap (String tag, float discount, List specialAspects, float discountSpecial, ItemStack item, int craftCost) { + this.setTag(tag); + this.baseCostModifier = discount; + this.specialCostModifierAspects = specialAspects; + this.specialCostModifier = discountSpecial; + texture = new ResourceLocation("thaumcraft","textures/models/wand_cap_"+getTag()+".png"); + this.item=item; + this.setCraftCost(craftCost); + caps.put(tag, this); + } + + public float getBaseCostModifier() { + return baseCostModifier; + } + + public List getSpecialCostModifierAspects() { + return specialCostModifierAspects; + } + + public float getSpecialCostModifier() { + return specialCostModifier; + } + + 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); + +} diff --git a/src/api/java/thaumcraft/api/wands/WandRod.java b/src/api/java/thaumcraft/api/wands/WandRod.java new file mode 100644 index 0000000..85954e4 --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/WandRod.java @@ -0,0 +1,158 @@ +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 - this number is actually multiplied + * by 100 for use by the wands internals + */ + 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; + + /** + * Does the rod glow in the dark? + */ + boolean glow; + + public static LinkedHashMap rods = new LinkedHashMap(); + + 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 WandRod (String tag, int capacity, ItemStack item, int craftCost) { + this.setTag(tag); + this.capacity = capacity; + this.texture = new ResourceLocation("thaumcraft","textures/models/wand_rod_"+getTag()+".png"); + this.item=item; + this.setCraftCost(craftCost); + rods.put(tag, this); + } + + public WandRod (String tag, int capacity, ItemStack item, int craftCost, IWandRodOnUpdate onUpdate) { + this.setTag(tag); + this.capacity = capacity; + this.texture = new ResourceLocation("thaumcraft","textures/models/wand_rod_"+getTag()+".png"); + 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; + } + + public boolean isGlowing() { + return glow; + } + + public void setGlowing(boolean hasGlow) { + this.glow = hasGlow; + } + + /** + * The research a player needs to have finished to be able to craft a wand with this rod. + */ + public String getResearch() { + return "ROD_"+getTag(); + } + + // Some examples: + // WandRod WAND_ROD_WOOD = new WandRod("wood",25,new ItemStack(Item.stick),1); + // WandRod WAND_ROD_BLAZE = new WandRod("blaze",100,new ItemStack(Item.blazeRod),7,new WandRodBlazeOnUpdate()); +} diff --git a/src/api/java/thaumcraft/api/wands/WandTriggerRegistry.java b/src/api/java/thaumcraft/api/wands/WandTriggerRegistry.java new file mode 100644 index 0000000..7224e12 --- /dev/null +++ b/src/api/java/thaumcraft/api/wands/WandTriggerRegistry.java @@ -0,0 +1,126 @@ +package thaumcraft.api.wands; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +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> triggers = new HashMap>(); + 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 block + * @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, Block block, int meta, String modid) { + if (!triggers.containsKey(modid)) { + triggers.put(modid, new HashMap()); + } + HashMap temp = triggers.get(modid); + temp.put(Arrays.asList(block,meta),Arrays.asList(manager,event)); + triggers.put(modid, temp); + } + + /** + * for legacy support + */ + public static void registerWandBlockTrigger(IWandTriggerManager manager, int event, Block block, int meta) { + registerWandBlockTrigger(manager, event, block, meta, DEFAULT); + } + + /** + * Checks all trigger registries if one exists for the given block and meta + * @param block + * @param meta + * @return + */ + public static boolean hasTrigger(Block block, int meta) { + for (String modid:triggers.keySet()) { + HashMap temp = triggers.get(modid); + if (temp.containsKey(Arrays.asList(block,meta)) || + temp.containsKey(Arrays.asList(block,-1))) return true; + } + return false; + } + + /** + * modid sensitive version + */ + public static boolean hasTrigger(Block block, int meta, String modid) { + if (!triggers.containsKey(modid)) return false; + HashMap temp = triggers.get(modid); + if (temp.containsKey(Arrays.asList(block,meta)) || + temp.containsKey(Arrays.asList(block,-1))) 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 block + * @param meta + * @return + */ + public static boolean performTrigger(World world, ItemStack wand, EntityPlayer player, + int x, int y, int z, int side, Block block, int meta) { + + for (String modid:triggers.keySet()) { + HashMap temp = triggers.get(modid); + List l = temp.get(Arrays.asList(block,meta)); + if (l==null) l = temp.get(Arrays.asList(block,-1)); + if (l==null) continue; + + IWandTriggerManager manager = (IWandTriggerManager) l.get(0); + int event = (Integer) l.get(1); + boolean result = manager.performTrigger(world, wand, player, x, y, z, side, event); + if (result) return true; + } + return false; + } + + /** + * modid sensitive version + */ + public static boolean performTrigger(World world, ItemStack wand, EntityPlayer player, + int x, int y, int z, int side, Block block, int meta, String modid) { + if (!triggers.containsKey(modid)) return false; + HashMap temp = triggers.get(modid); + List l = temp.get(Arrays.asList(block,meta)); + if (l==null) l = temp.get(Arrays.asList(block,-1)); + if (l==null) return false; + + IWandTriggerManager manager = (IWandTriggerManager) l.get(0); + int event = (Integer) l.get(1); + return manager.performTrigger(world, wand, player, x, y, z, side, event); + } + +} diff --git a/src/main/java/modtweaker/ModTweaker.java b/src/main/java/modtweaker/ModTweaker.java index 1c7043a..f8250b0 100644 --- a/src/main/java/modtweaker/ModTweaker.java +++ b/src/main/java/modtweaker/ModTweaker.java @@ -1,5 +1,7 @@ package modtweaker; +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader; + import minetweaker.MineTweakerAPI; import minetweaker.api.player.IPlayer; import minetweaker.api.server.ICommandFunction; @@ -9,7 +11,6 @@ import modtweaker.mods.exnihilo.ExNihilo; import modtweaker.mods.extendedworkbench.ExtendedWorkbench; import modtweaker.mods.factorization.Factorization; import modtweaker.mods.fsp.Steamcraft; -import modtweaker.mods.hee.HardcoreEnderExpansion; import modtweaker.mods.mariculture.Mariculture; import modtweaker.mods.mekanism.Mekanism; import modtweaker.mods.mekanism.gas.GasLogger; @@ -22,6 +23,7 @@ import modtweaker.mods.thaumcraft.Thaumcraft; import modtweaker.mods.thaumcraft.research.ResearchLogger; import modtweaker.mods.thermalexpansion.ThermalExpansion; import modtweaker.util.TweakerPlugin; +import net.minecraft.util.RegistryNamespaced; import net.minecraftforge.common.MinecraftForge; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod; @@ -39,7 +41,7 @@ public class ModTweaker { TweakerPlugin.register("exnihilo", ExNihilo.class); TweakerPlugin.register("extendedWorkbench", ExtendedWorkbench.class); TweakerPlugin.register("factorization", Factorization.class); - TweakerPlugin.register("HardcoreEnderExpansion", HardcoreEnderExpansion.class); +// TweakerPlugin.register("HardcoreEnderExpansion", HardcoreEnderExpansion.class); TweakerPlugin.register("Mariculture", Mariculture.class); TweakerPlugin.register("Mekanism", Mekanism.class); TweakerPlugin.register("Metallurgy", Metallurgy.class); diff --git a/src/main/java/modtweaker/mods/mekanism/handlers/Sawmill.java b/src/main/java/modtweaker/mods/mekanism/handlers/Sawmill.java index a60dfb2..399443f 100644 --- a/src/main/java/modtweaker/mods/mekanism/handlers/Sawmill.java +++ b/src/main/java/modtweaker/mods/mekanism/handlers/Sawmill.java @@ -11,6 +11,7 @@ import minetweaker.MineTweakerAPI; import minetweaker.api.item.IItemStack; import modtweaker.mods.mekanism.util.AddMekanismRecipe; import modtweaker.util.BaseMapRemoval; +import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenClass; @@ -22,6 +23,7 @@ public class Sawmill { public static void addRecipe(IItemStack input, IItemStack output1, @Optional IItemStack output2, @Optional double chance) { ChanceOutput chanceOutput = new ChanceOutput(toStack(output1), toStack(output2), chance); MineTweakerAPI.apply(new AddMekanismRecipe("PRECISION_SAWMILL", Recipe.PRECISION_SAWMILL.get(), toStack(input), chanceOutput)); + Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode(); } @ZenMethod diff --git a/src/main/resources/CoFH_at.cfg b/src/main/resources/CoFH_at.cfg new file mode 100644 index 0000000..19fe7ac --- /dev/null +++ b/src/main/resources/CoFH_at.cfg @@ -0,0 +1,51 @@ +# NetherOres +public net.minecraft.entity.monster.EntityPigZombie func_70835_c(Lnet/minecraft/entity/Entity;)V # becomeAngryAt +public net.minecraft.entity.monster.EntitySilverfish field_70843_d # allySummonCooldown +public-f net.minecraft.init.Blocks field_150449_bY # oreNetherQuartz + +# MineFactory Reloaded +protected net.minecraft.util.WeightedRandomFishable * # need it all +public net.minecraft.entity.EntityList field_75624_e # classToIDMapping +public net.minecraft.entity.EntityList field_75622_f # stringToIDMapping +public net.minecraft.entity.monster.EntitySlime func_70799_a(I)V # setSlimeSize +public net.minecraft.entity.monster.EntityZombie func_82228_a(I)V # startConversion +public net.minecraft.entity.EntityLivingBase field_70718_bc # recentlyHit +public-f net.minecraft.init.Blocks field_150432_aD # ice +public-f net.minecraft.init.Blocks field_150410_aZ # glass_pane +public-f net.minecraft.init.Items field_151117_aB # milkBucket +protected net.minecraft.block.Block field_149770_b # unlocalizedName +public net.minecraft.server.management.PlayerManager func_72690_a(IIZ)Lnet/minecraft/server/management/PlayerManager$PlayerInstance; # getOrCreateChunkWatcher +public net.minecraft.server.management.PlayerManager$PlayerInstance +public net.minecraft.server.management.PlayerManager$PlayerInstance field_73263_b # playersWatchingChunk +public net.minecraft.entity.EntityLiving field_70728_aV # experienceValue +public net.minecraft.entity.EntityLiving field_82174_bp # equipmentDropChances + +# Thermal Expansion +public net.minecraft.entity.Entity field_83001_bt # invulnerable +public net.minecraft.entity.Entity field_70178_ae # isImmuneToFire +public net.minecraft.entity.player.EntityPlayer field_71074_e # itemInUse +public net.minecraft.server.management.ItemInWorldManager field_73094_o #durabilityRemainingOnBlock + +# PC Core +public net.minecraft.client.gui.GuiScreen field_146289_q # fontRenderer +public net.minecraft.client.gui.inventory.GuiContainer field_147003_i # guiLeft +public net.minecraft.client.gui.inventory.GuiContainer field_147009_r # guiTop +public net.minecraft.world.WorldServer field_73068_P # allPlayersSleeping + +# CoFH Core +protected net.minecraft.inventory.Container * # senseless to have private stuff here +protected net.minecraft.client.gui.inventory.GuiContainer * # senseless to have private stuff here +protected net.minecraft.client.gui.FontRenderer func_78280_d(Ljava/lang/String;I)Ljava/lang/String; # wrapFormattedStringToWidth +protected net.minecraft.client.gui.FontRenderer func_78255_a(Ljava/lang/String;Z)V # renderStringAtPos +public net.minecraft.entity.projectile.EntityFishHook * # (nearly) literally everything is private +protected net.minecraft.entity.player.EntityPlayer field_71072_f # itemInUseCount +public net.minecraft.item.ItemPickaxe field_150915_c # blocksEffectiveAgainst +public net.minecraft.item.ItemSpade field_150916_c # blocksEffectiveAgainst +public net.minecraft.item.ItemAxe field_150917_c # blocksEffectiveAgainst +public net.minecraft.util.RegistrySimple field_82596_a # registryObjects +public-f net.minecraft.util.RegistryNamespaced field_148759_a # underlyingIntegerMap +public net.minecraft.world.World field_72998_d # collidingBoundingBoxes + +# WorldProxy +public-f net.minecraft.world.World *()V # Doesn't matter what it is, we need it public +public-f net.minecraft.world.WorldServer *()V # Doesn't matter what it is, we need it public diff --git a/src/main/resources/TConstruct_at.cfg b/src/main/resources/TConstruct_at.cfg new file mode 100644 index 0000000..467fa4b --- /dev/null +++ b/src/main/resources/TConstruct_at.cfg @@ -0,0 +1,34 @@ +# Tinkers Construct -- Access Transformer +# Required for any build system. +# Last update: Minecraft 1.7.2 - 2014 Feb 02 by Progwml6 +# EntityArrow - Grabbed 'em all, since so much is accessed +public net.minecraft.entity.projectile.EntityArrow field_145789_f +public net.minecraft.entity.projectile.EntityArrow field_145790_g +public net.minecraft.entity.projectile.EntityArrow field_145791_d +public net.minecraft.entity.projectile.EntityArrow field_145792_e +public net.minecraft.entity.projectile.EntityArrow field_70254_i +public net.minecraft.entity.projectile.EntityArrow field_70252_j +public net.minecraft.entity.projectile.EntityArrow field_70253_h +public net.minecraft.entity.projectile.EntityArrow field_70257_an +public net.minecraft.entity.projectile.EntityArrow field_70255_ao +public net.minecraft.entity.projectile.EntityArrow field_70256_ap +public net.minecraft.entity.projectile.EntityArrow *() #we need waaaaaaay to much in here to bother going through it +# RenderGlobal +public net.minecraft.client.renderer.RenderGlobal field_147592_B +# Blocks +public-f net.minecraft.block.Block field_149764_J +public net.minecraft.block.BlockLeavesBase field_150121_P +public net.minecraft.block.BlockRailBase$Rail func_150650_a()I +# GuiContainer +public net.minecraft.client.gui.inventory.GuiContainer field_146999_f +public net.minecraft.client.gui.inventory.GuiContainer field_147009_r +public net.minecraft.client.gui.inventory.GuiContainer field_147003_i +# GuiScreen +public net.minecraft.client.gui.GuiScreen field_146292_n #buttonList +# ThreadDownloadImageData +public net.minecraft.client.renderer.ThreadDownloadImageData field_110559_g #field_110559_g +public net.minecraft.client.renderer.ThreadDownloadImageData field_110560_d #field_110560_d +public net.minecraft.world.gen.structure.StructureVillagePieces$Village #cant make village houses w/o this +public net.minecraft.client.renderer.Tessellator field_78415_z +public net.minecraft.client.renderer.entity.RenderPlayer field_77109_a #modelBipedMain +# needs to have a space at the end of every line or SS will derp diff --git a/src/main/resources/hee_at.cfg b/src/main/resources/hee_at.cfg new file mode 100644 index 0000000..421fc37 --- /dev/null +++ b/src/main/resources/hee_at.cfg @@ -0,0 +1,20 @@ +# C:\Gradle\caches\minecraft\net\minecraftforge\forge\1.7.10-10.13.0.1208\unpacked\conf + +public net.minecraft.util.RegistrySimple field_82596_a # registryObjects +public net.minecraft.util.RegistryNamespaced field_148759_a # underlyingIntegerMap +public net.minecraft.entity.EntityLivingBase field_110153_bc # lastDamage +public net.minecraft.entity.EntityLiving field_82174_bp # equipmentDropChances +public net.minecraft.entity.Entity field_70151_c # fire +public net.minecraft.entity.monster.EntityGhast field_70792_g # targetedEntity +public net.minecraft.network.NetHandlerPlayServer field_147365_f # floatingTickCount +public net.minecraft.network.NetHandlerPlayServer field_147373_o # lastPosX +public net.minecraft.network.NetHandlerPlayServer field_147382_p # lastPosY +public net.minecraft.network.NetHandlerPlayServer field_147381_q # lastPosZ +public net.minecraft.world.gen.ChunkProviderEnd field_73204_i # endRNG +public-f net.minecraft.world.biome.BiomeGenBase field_76779_k # sky +public net.minecraft.world.World field_73020_y # chunkProvider + +public net.minecraft.client.Minecraft field_147126_aw # mcMusicTicker +public net.minecraft.client.gui.inventory.GuiContainer field_146999_f # xSize +public net.minecraft.client.gui.inventory.GuiContainer field_147000_g # ySize +public net.minecraft.client.renderer.RenderGlobal field_147593_P # mapSoundPositions \ No newline at end of file diff --git a/src/main/resources/mariculture_at.cfg b/src/main/resources/mariculture_at.cfg new file mode 100644 index 0000000..8155760 --- /dev/null +++ b/src/main/resources/mariculture_at.cfg @@ -0,0 +1,12 @@ +public net.minecraft.client.gui.inventory.GuiContainer field_146999_f #xSize +public net.minecraft.client.gui.inventory.GuiContainer field_147000_g #ySize +public net.minecraft.entity.projectile.EntityFishHook * +public net.minecraft.util.WeightedRandomFishable * +public net.minecraft.client.renderer.EntityRenderer * +public net.minecraft.world.biome.BiomeGenMutated * +public net.minecraft.entity.item.EntityBoat * +public net.minecraft.world.gen.ChunkProviderGenerate * +public net.minecraft.inventory.Container field_94535_f +public net.minecraft.inventory.Container field_94536_g +public net.minecraft.inventory.Container field_94537_h +public net.minecraft.entity.player.EntityPlayer func_70693_a(Lnet/minecraft/entity/player/EntityPlayer;)I \ No newline at end of file