summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLance5057 <Lance5057@gmail.com>2016-04-14 01:15:14 -0500
committerLance5057 <Lance5057@gmail.com>2016-04-14 01:15:14 -0500
commit03b859cf0b85c9ad5ce10d71164634091b0acb4b (patch)
tree4f7e67164f5a7e8b771c28e2d3d4062a30dbd564 /src
parent9d618ac01c99846faeda71bc4c4c5f5324aeef51 (diff)
Added Thaum api, new modifiers, hauberd -> hauberk, fixed finishing anvil bug
Diffstat (limited to 'src')
-rw-r--r--src/api/java/thaumcraft/api/BlockCoordinates.java108
-rw-r--r--src/api/java/thaumcraft/api/IArchitect.java27
-rw-r--r--src/api/java/thaumcraft/api/IGoggles.java22
-rw-r--r--src/api/java/thaumcraft/api/IRepairable.java13
-rw-r--r--src/api/java/thaumcraft/api/IRepairableExtended.java17
-rw-r--r--src/api/java/thaumcraft/api/IRunicArmor.java22
-rw-r--r--src/api/java/thaumcraft/api/IScribeTools.java14
-rw-r--r--src/api/java/thaumcraft/api/IVisDiscountGear.java20
-rw-r--r--src/api/java/thaumcraft/api/IWarpingGear.java22
-rw-r--r--src/api/java/thaumcraft/api/ItemApi.java70
-rw-r--r--src/api/java/thaumcraft/api/ItemRunic.java21
-rw-r--r--src/api/java/thaumcraft/api/ThaumcraftApi.java588
-rw-r--r--src/api/java/thaumcraft/api/ThaumcraftApiHelper.java467
-rw-r--r--src/api/java/thaumcraft/api/TileThaumcraft.java63
-rw-r--r--src/api/java/thaumcraft/api/WorldCoordinates.java117
-rw-r--r--src/api/java/thaumcraft/api/aspects/Aspect.java201
-rw-r--r--src/api/java/thaumcraft/api/aspects/AspectList.java292
-rw-r--r--src/api/java/thaumcraft/api/aspects/AspectSourceHelper.java58
-rw-r--r--src/api/java/thaumcraft/api/aspects/IAspectContainer.java80
-rw-r--r--src/api/java/thaumcraft/api/aspects/IAspectSource.java16
-rw-r--r--src/api/java/thaumcraft/api/aspects/IEssentiaContainerItem.java37
-rw-r--r--src/api/java/thaumcraft/api/aspects/IEssentiaTransport.java100
-rw-r--r--src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java91
-rw-r--r--src/api/java/thaumcraft/api/crafting/IArcaneRecipe.java35
-rw-r--r--src/api/java/thaumcraft/api/crafting/IInfusionStabiliser.java19
-rw-r--r--src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java154
-rw-r--r--src/api/java/thaumcraft/api/crafting/InfusionRecipe.java133
-rw-r--r--src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java261
-rw-r--r--src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java161
-rw-r--r--src/api/java/thaumcraft/api/damagesource/DamageSourceIndirectThaumcraftEntity.java32
-rw-r--r--src/api/java/thaumcraft/api/damagesource/DamageSourceThaumcraft.java47
-rw-r--r--src/api/java/thaumcraft/api/entities/IEldritchMob.java5
-rw-r--r--src/api/java/thaumcraft/api/entities/ITaintedMob.java5
-rw-r--r--src/api/java/thaumcraft/api/internal/DummyInternalMethodHandler.java78
-rw-r--r--src/api/java/thaumcraft/api/internal/IInternalMethodHandler.java25
-rw-r--r--src/api/java/thaumcraft/api/internal/WeightedRandomLoot.java24
-rw-r--r--src/api/java/thaumcraft/api/nodes/INode.java53
-rw-r--r--src/api/java/thaumcraft/api/nodes/IRevealer.java22
-rw-r--r--src/api/java/thaumcraft/api/nodes/NodeModifier.java6
-rw-r--r--src/api/java/thaumcraft/api/nodes/NodeType.java6
-rw-r--r--src/api/java/thaumcraft/api/package-info.java4
-rw-r--r--src/api/java/thaumcraft/api/potions/PotionFluxTaint.java67
-rw-r--r--src/api/java/thaumcraft/api/potions/PotionVisExhaust.java48
-rw-r--r--src/api/java/thaumcraft/api/research/IScanEventHandler.java9
-rw-r--r--src/api/java/thaumcraft/api/research/ResearchCategories.java101
-rw-r--r--src/api/java/thaumcraft/api/research/ResearchCategoryList.java37
-rw-r--r--src/api/java/thaumcraft/api/research/ResearchItem.java369
-rw-r--r--src/api/java/thaumcraft/api/research/ResearchPage.java193
-rw-r--r--src/api/java/thaumcraft/api/research/ScanResult.java39
-rw-r--r--src/api/java/thaumcraft/api/visnet/TileVisNode.java188
-rw-r--r--src/api/java/thaumcraft/api/visnet/VisNetHandler.java282
-rw-r--r--src/api/java/thaumcraft/api/wands/FocusUpgradeType.java114
-rw-r--r--src/api/java/thaumcraft/api/wands/IWandRodOnUpdate.java16
-rw-r--r--src/api/java/thaumcraft/api/wands/IWandTriggerManager.java15
-rw-r--r--src/api/java/thaumcraft/api/wands/IWandable.java25
-rw-r--r--src/api/java/thaumcraft/api/wands/ItemFocusBasic.java276
-rw-r--r--src/api/java/thaumcraft/api/wands/StaffRod.java48
-rw-r--r--src/api/java/thaumcraft/api/wands/WandCap.java129
-rw-r--r--src/api/java/thaumcraft/api/wands/WandRod.java158
-rw-r--r--src/api/java/thaumcraft/api/wands/WandTriggerRegistry.java126
-rw-r--r--src/main/java/lance5057/tDefense/TD_Commands.java4
-rw-r--r--src/main/java/lance5057/tDefense/TD_Config.java13
-rw-r--r--src/main/java/lance5057/tDefense/TinkersDefense.java4
-rw-r--r--src/main/java/lance5057/tDefense/armor/ArmorCore.java34
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/cloth/TinkersHood.java31
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/cloth/TinkersRobe.java10
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShawl.java11
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShoes.java10
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/heavy/TinkersHelm.java21
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/light/TinkersCoif.java24
-rw-r--r--src/main/java/lance5057/tDefense/armor/items/light/TinkersHauberk.java (renamed from src/main/java/lance5057/tDefense/armor/items/light/TinkersHalberd.java)41
-rw-r--r--src/main/java/lance5057/tDefense/armor/modifiers/ArmorMods.java45
-rw-r--r--src/main/java/lance5057/tDefense/armor/modifiers/Thaumcraft/ThaumArmorMods.java55
-rw-r--r--src/main/java/lance5057/tDefense/armor/modifiers/modifierBoolExclusive.java23
-rw-r--r--src/main/java/lance5057/tDefense/armor/modifiers/modifierIntExclusive.java80
-rw-r--r--src/main/java/lance5057/tDefense/armor/renderers/light/ModelTinkersHauberk.java (renamed from src/main/java/lance5057/tDefense/armor/renderers/light/ModelTinkersHalberd.java)4
-rw-r--r--src/main/java/lance5057/tDefense/finishingAnvil/utilities/ToolCoreTip.java52
-rw-r--r--src/main/java/lance5057/tDefense/proxy/ClientProxy.java4
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/boots/_boots_chain.pngbin290 -> 253 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/boots/_boots_cloth.pngbin154 -> 117 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/boots/_boots_rivet.pngbin151 -> 114 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_chain.pngbin207 -> 144 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_plate.pngbin216 -> 194 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_smallplate.pngbin216 -> 180 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_trim.pngbin227 -> 199 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/blastprotection_breastplate_effect.pngbin212 -> 140 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/fireprotection_breastplate_effect.pngbin210 -> 131 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/projprotection_breastplate_effect.pngbin202 -> 126 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/breastplate/protection_breastplate_effect.pngbin207 -> 168 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_chain.pngbin206 -> 169 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_plate.pngbin278 -> 241 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/coif/_coif_chain.pngbin285 -> 248 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/coif/_coif_circlet.pngbin194 -> 157 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/coif/_coif_cloth.pngbin179 -> 142 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/coif/rebreather_coif_effect.pngbin0 -> 167 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/coif/revealing_coif_effect.pngbin0 -> 149 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_chain.pngbin206 -> 149 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_cod.pngbin195 -> 147 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_plate.pngbin232 -> 196 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_trim.pngbin201 -> 143 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_chain.pngbin306 -> 0 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_plate.pngbin255 -> 0 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_rivet.pngbin160 -> 0 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_chain.pngbin0 -> 269 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_plate.pngbin0 -> 218 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_rivet.pngbin0 -> 123 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_chain.pngbin0 -> 269 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_plate.pngbin0 -> 218 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_rivet.pngbin0 -> 123 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/helm/_helm_chain.pngbin293 -> 241 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/helm/_helm_top.pngbin324 -> 165 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/helm/_helm_visor.pngbin229 -> 158 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/helm/revealing_helm_effect.pngbin0 -> 119 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/_hood_cloth.pngbin232 -> 195 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/_hood_rivet.pngbin154 -> 117 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/_hood_trim.pngbin221 -> 184 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_helm_effect.pngbin0 -> 167 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_hood_effect.pngbin0 -> 204 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/revealing_hood_effect.pngbin0 -> 134 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/vis_hood_effect.pngbin0 -> 135 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/hood/visembroidery_hood_effect.pngbin0 -> 135 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/robe/_robe_cloth.pngbin262 -> 225 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/robe/_robe_trim.pngbin225 -> 195 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/robe/vis_robe_effect.pngbin0 -> 237 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/robe/visembroidery_robe_effect.pngbin0 -> 237 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_caps.pngbin287 -> 203 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_plates.pngbin281 -> 202 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_soles.pngbin250 -> 129 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_trim.pngbin264 -> 159 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/blastprotection_sabatons_effect.pngbin267 -> 151 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/depthstrider_sabatons_effect.pngbin278 -> 173 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/featherfall_sabatons_effect.pngbin293 -> 258 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/fireprotection_sabatons_effect.pngbin258 -> 140 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/firewalk_sabatons_effect.pngbin283 -> 196 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/frostwalk_sabatons_effect.pngbin283 -> 190 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/glowstep_sabatons_effect.pngbin263 -> 158 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/projprotection_sabatons_effect.pngbin253 -> 121 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/sabatons/protection_sabatons_effect.pngbin302 -> 229 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_clasp.pngbin157 -> 120 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_cloth.pngbin300 -> 263 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_trim.pngbin218 -> 181 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shawl/vis_shawl_effect.pngbin0 -> 153 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shawl/visembroidery_shawl_effect.pngbin0 -> 158 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_clasp.pngbin153 -> 116 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_cloth.pngbin262 -> 225 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_rivet.pngbin152 -> 115 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shoes/vis_shoes_effect.pngbin0 -> 136 bytes
-rw-r--r--src/main/resources/assets/tinker/textures/items/armor/shoes/visembroidery_shoes_effect.pngbin0 -> 136 bytes
-rw-r--r--src/main/resources/assets/tinkersdefense/lang/en_US.lang8
149 files changed, 6148 insertions, 102 deletions
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<BlockCoordinates> 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<Block> portableHoleBlackList = new ArrayList<Block>();
+
+ //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<IScanEventHandler> scanEventhandlers = new ArrayList<IScanEventHandler>();
+ public static ArrayList<EntityTags> scanEntities = new ArrayList<EntityTags>();
+ public static class EntityTagsNBT {
+ public EntityTagsNBT(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+ public String name;
+ public Object value;
+ }
+ public static class EntityTags {
+ public EntityTags(String entityName, AspectList aspects, EntityTagsNBT... nbts) {
+ this.entityName = entityName;
+ this.nbts = nbts;
+ this.aspects = aspects;
+ }
+ public String entityName;
+ public EntityTagsNBT[] nbts;
+ public AspectList aspects;
+ }
+
+ /**
+ * 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. <br>For example the normal and wither skeleton:
+ * <br>ThaumcraftApi.registerEntityTag("Skeleton", (new AspectList()).add(Aspect.DEATH, 5));
+ * <br>ThaumcraftApi.registerEntityTag("Skeleton", (new AspectList()).add(Aspect.DEATH, 8), new NBTTagByte("SkeletonType",(byte) 1));
+ */
+ public static void registerEntityTag(String entityName, AspectList aspects, EntityTagsNBT... nbt ) {
+ scanEntities.add(new EntityTags(entityName,aspects,nbt));
+ }
+
+ //RECIPES/////////////////////////////////////////
+ private static ArrayList craftingRecipes = new ArrayList();
+ private static HashMap<Object,ItemStack> smeltingBonus = new HashMap<Object,ItemStack>();
+
+ /**
+ * This method is used to determine what bonus items are generated when the infernal furnace smelts items
+ * @param in The input of the smelting operation. e.g. new ItemStack(Block.oreGold)
+ * @param out The bonus item that can be produced from the smelting operation e.g. new ItemStack(nuggetGold,0,0).
+ * Stacksize should be 0 unless you want to guarantee that at least 1 item is always produced.
+ */
+ public static void addSmeltingBonus(ItemStack in, ItemStack out) {
+ smeltingBonus.put(
+ Arrays.asList(in.getItem(),in.getItemDamage()),
+ new ItemStack(out.getItem(),0,out.getItemDamage()));
+ }
+
+ /**
+ * This method is used to determine what bonus items are generated when the infernal furnace smelts items
+ * @param in The ore dictionary input of the smelting operation. e.g. "oreGold"
+ * @param out The bonus item that can be produced from the smelting operation e.g. new ItemStack(nuggetGold,0,0).
+ * Stacksize should be 0 unless you want to guarantee that at least 1 item is always produced.
+ */
+ public static void addSmeltingBonus(String in, ItemStack out) {
+ smeltingBonus.put( in, new ItemStack(out.getItem(),0,out.getItemDamage()));
+ }
+
+ /**
+ * Returns the bonus item produced from a smelting operation in the infernal furnace
+ * @param in The input of the smelting operation. e.g. new ItemStack(oreGold)
+ * @return the The bonus item that can be produced
+ */
+ public static ItemStack getSmeltingBonus(ItemStack in) {
+ ItemStack out = smeltingBonus.get(Arrays.asList(in.getItem(),in.getItemDamage()));
+ if (out==null) {
+ out = smeltingBonus.get(Arrays.asList(in.getItem(),OreDictionary.WILDCARD_VALUE));
+ }
+ if (out==null) {
+ 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<int[],Object[]> keyCache = new HashMap<int[],Object[]>();
+
+ public static Object[] getCraftingRecipeKey(EntityPlayer player, ItemStack stack) {
+ int[] key = new int[] {Item.getIdFromItem(stack.getItem()),stack.getItemDamage()};
+ if (keyCache.containsKey(key)) {
+ if (keyCache.get(key)==null) return null;
+ if (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<ri.getPages().length;a++) {
+ ResearchPage page = ri.getPages()[a];
+ if (page.recipe!=null && page.recipe instanceof CrucibleRecipe[]) {
+ CrucibleRecipe[] crs = (CrucibleRecipe[]) page.recipe;
+ for (CrucibleRecipe cr:crs) {
+ if (cr.getRecipeOutput().isItemEqual(stack)) {
+ keyCache.put(key,new Object[] {ri.key,a});
+ if (ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), ri.key))
+ return new Object[] {ri.key,a};
+ }
+ }
+ } else
+ if (page.recipeOutput!=null && stack !=null && page.recipeOutput.isItemEqual(stack)) {
+ keyCache.put(key,new Object[] {ri.key,a});
+ if (ThaumcraftApiHelper.isResearchComplete(player.getCommandSenderName(), ri.key))
+ return new Object[] {ri.key,a};
+ else
+ return null;
+ }
+ }
+ }
+ }
+ keyCache.put(key,null);
+ return null;
+ }
+
+ //ASPECTS////////////////////////////////////////
+
+ public static ConcurrentHashMap<List,AspectList> objectTags = new ConcurrentHashMap<List,AspectList>();
+ public static ConcurrentHashMap<List,int[]> groupedObjectTags = new ConcurrentHashMap<List,int[]>();
+
+ /**
+ * Checks to see if the passed item/block already has aspects associated with it.
+ * @param id
+ * @param meta
+ * @return
+ */
+ public static boolean exists(Item item, int meta) {
+ AspectList tmp = ThaumcraftApi.objectTags.get(Arrays.asList(item,meta));
+ if (tmp==null) {
+ tmp = ThaumcraftApi.objectTags.get(Arrays.asList(item,OreDictionary.WILDCARD_VALUE));
+ if (meta==OreDictionary.WILDCARD_VALUE && tmp==null) {
+ int index=0;
+ do {
+ tmp = ThaumcraftApi.objectTags.get(Arrays.asList(item,index));
+ index++;
+ } while (index<16 && tmp==null);
+ }
+ if (tmp==null) return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Used to assign apsects to the given item/block. Here is an example of the declaration for cobblestone:<p>
+ * <i>ThaumcraftApi.registerObjectTag(new ItemStack(Blocks.cobblestone), (new AspectList()).add(Aspect.ENTROPY, 1).add(Aspect.EARTH, 1));</i>
+ * @param item the item passed. Pass OreDictionary.WILDCARD_VALUE if all damage values of this item/block should have the same aspects
+ * @param aspects A ObjectTags object of the associated aspects
+ */
+ public static void registerObjectTag(ItemStack item, AspectList aspects) {
+ if (aspects==null) aspects=new AspectList();
+ try {
+ objectTags.put(Arrays.asList(item.getItem(),item.getItemDamage()), aspects);
+ } catch (Exception e) {}
+ }
+
+
+ /**
+ * Used to assign apsects to the given item/block. Here is an example of the declaration for cobblestone:<p>
+ * <i>ThaumcraftApi.registerObjectTag(new ItemStack(Blocks.cobblestone), new int[]{0,1}, (new AspectList()).add(Aspect.ENTROPY, 1).add(Aspect.EARTH, 1));</i>
+ * @param item
+ * @param meta A range of meta values if you wish to lump several item meta's together as being the "same" item (i.e. stair orientations)
+ * @param aspects A ObjectTags object of the associated aspects
+ */
+ public static void registerObjectTag(ItemStack item, int[] meta, AspectList aspects) {
+ if (aspects==null) aspects=new AspectList();
+ try {
+ objectTags.put(Arrays.asList(item.getItem(),meta[0]), aspects);
+ for (int m:meta) {
+ groupedObjectTags.put(Arrays.asList(item.getItem(),m), meta);
+ }
+
+ } catch (Exception e) {}
+ }
+
+ /**
+ * Used to assign apsects to the given ore dictionary item.
+ * @param oreDict the ore dictionary name
+ * @param aspects A ObjectTags object of the associated aspects
+ */
+ public static void registerObjectTag(String oreDict, AspectList aspects) {
+ if (aspects==null) aspects=new AspectList();
+ ArrayList<ItemStack> ores = OreDictionary.getOres(oreDict);
+ if (ores!=null && ores.size()>0) {
+ for (ItemStack ore:ores) {
+ try {
+ objectTags.put(Arrays.asList(ore.getItem(), ore.getItemDamage()), aspects);
+ } catch (Exception e) {}
+ }
+ }
+ }
+
+ /**
+ * Used to assign aspects to the given item/block.
+ * Attempts to automatically generate aspect tags by checking registered recipes.
+ * Here is an example of the declaration for pistons:<p>
+ * <i>ThaumcraftApi.registerComplexObjectTag(new ItemStack(Blocks.cobblestone), (new AspectList()).add(Aspect.MECHANISM, 2).add(Aspect.MOTION, 4));</i>
+ * IMPORTANT - this should only be used if you are not happy with the default aspects the object would be assigned.
+ * @param item, pass OreDictionary.WILDCARD_VALUE to meta if all damage values of this item/block should have the same aspects
+ * @param aspects A ObjectTags object of the associated aspects
+ */
+ public static void registerComplexObjectTag(ItemStack item, AspectList aspects ) {
+ if (!exists(item.getItem(),item.getItemDamage())) {
+ AspectList tmp = 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<Object,Integer> warpMap = new HashMap<Object,Integer>();
+
+ /**
+ * This method is used to determine how much warp is gained if the item is crafted. The warp
+ * added is "sticky" warp
+ * @param craftresult The item crafted
+ * @param amount how much warp is gained
+ */
+ public static void addWarpToItem(ItemStack craftresult, int amount) {
+ warpMap.put(Arrays.asList(craftresult.getItem(),craftresult.getItemDamage()),amount);
+ }
+
+ /**
+ * This method is used to determine how much permanent warp is gained if the research is completed
+ * @param in The item crafted
+ * @param amount how much warp is gained
+ */
+ public static void addWarpToResearch(String research, int amount) {
+ warpMap.put(research, amount);
+ }
+
+ /**
+ * Returns how much warp is gained from the item or research passed in
+ * @param in itemstack or string
+ * @return how much warp it will give
+ */
+ public static int getWarp(Object in) {
+ if (in==null) return 0;
+ if (in instanceof ItemStack && warpMap.containsKey(Arrays.asList(((ItemStack)in).getItem(),((ItemStack)in).getItemDamage()))) {
+ return warpMap.get(Arrays.asList(((ItemStack)in).getItem(),((ItemStack)in).getItemDamage()));
+ } else
+ if (in instanceof String && warpMap.containsKey((String)in)) {
+ return warpMap.get((String)in);
+ }
+ return 0;
+ }
+
+ //LOOT BAGS //////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Used to add possible loot to treasure bags. As a reference, the weight of gold coins are 2000
+ * and a diamond is 50.
+ * The weights are the same for all loot bag types - the only difference is how many items the bag
+ * contains.
+ * @param item
+ * @param weight
+ * @param bagTypes array of which type of bag to add this loot to. Multiple types can be specified
+ * 0 = common, 1 = uncommon, 2 = rare
+ */
+ public static void addLootBagItem(ItemStack item, int weight, int... bagTypes) {
+ if (bagTypes==null || bagTypes.length==0)
+ WeightedRandomLoot.lootBagCommon.add(new WeightedRandomLoot(item,weight));
+ else {
+ for (int rarity:bagTypes) {
+ switch(rarity) {
+ case 0: WeightedRandomLoot.lootBagCommon.add(new WeightedRandomLoot(item,weight)); break;
+ case 1: WeightedRandomLoot.lootBagUncommon.add(new WeightedRandomLoot(item,weight)); break;
+ case 2: WeightedRandomLoot.lootBagRare.add(new WeightedRandomLoot(item,weight)); break;
+ }
+ }
+ }
+ }
+
+ //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<low) {
+ low = ta;
+ lowest = tag;
+ }
+ }
+ temp2.aspects.remove(lowest);
+ }
+ return temp2;
+ }
+
+ public static boolean areItemsEqual(ItemStack s1,ItemStack s2)
+ {
+ if (s1.isItemStackDamageable() && s2.isItemStackDamageable())
+ {
+ return s1.getItem() == s2.getItem();
+ } else
+ return s1.getItem() == s2.getItem() && s1.getItemDamage() == s2.getItemDamage();
+ }
+
+ public static boolean isResearchComplete(String username, String researchkey) {
+ return ThaumcraftApi.internalMethods.isResearchComplete(username, researchkey);
+ }
+
+ public static boolean hasDiscoveredAspect(String username, Aspect aspect) {
+ return ThaumcraftApi.internalMethods.hasDiscoveredAspect(username, aspect);
+ }
+
+ public static AspectList getDiscoveredAspects(String username) {
+ return ThaumcraftApi.internalMethods.getDiscoveredAspects(username);
+ }
+
+ public static ItemStack getStackInRowAndColumn(Object instance, int row, int column) {
+ return ThaumcraftApi.internalMethods.getStackInRowAndColumn(instance, row, column);
+ }
+
+ public static AspectList getObjectAspects(ItemStack is) {
+ return ThaumcraftApi.internalMethods.getObjectAspects(is);
+ }
+
+ public static AspectList getBonusObjectTags(ItemStack is,AspectList ot) {
+ return ThaumcraftApi.internalMethods.getBonusObjectTags(is, ot);
+ }
+
+ public static AspectList generateTags(Item item, int meta) {
+ return ThaumcraftApi.internalMethods.generateTags(item, meta);
+ }
+
+ public static boolean containsMatch(boolean strict, ItemStack[] inputs, ItemStack... targets)
+ {
+ for (ItemStack input : inputs)
+ {
+ for (ItemStack target : targets)
+ {
+ if (itemMatches(target, input, strict))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static boolean areItemStackTagsEqualForCrafting(ItemStack slotItem,ItemStack recipeItem)
+ {
+ if (recipeItem == null || slotItem == null) return false;
+ if (recipeItem.stackTagCompound!=null && slotItem.stackTagCompound==null ) return false;
+ if (recipeItem.stackTagCompound==null ) return true;
+
+ Iterator iterator = recipeItem.stackTagCompound.func_150296_c().iterator();
+ while (iterator.hasNext())
+ {
+ String s = (String)iterator.next();
+ if (slotItem.stackTagCompound.hasKey(s)) {
+ if (!slotItem.stackTagCompound.getTag(s).toString().equals(
+ recipeItem.stackTagCompound.getTag(s).toString())) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ public static boolean itemMatches(ItemStack target, ItemStack input, boolean strict)
+ {
+ if (input == null && target != null || input != null && target == null)
+ {
+ return false;
+ }
+ return (target.getItem() == input.getItem() &&
+ ((target.getItemDamage() == OreDictionary.WILDCARD_VALUE && !strict) || target.getItemDamage() == input.getItemDamage()));
+ }
+
+
+ public static TileEntity getConnectableTile(World world, int x, int y, int z, ForgeDirection face) {
+ TileEntity te = world.getTileEntity(x+face.offsetX, y+face.offsetY, z+face.offsetZ);
+ if (te instanceof IEssentiaTransport && ((IEssentiaTransport)te).isConnectable(face.getOpposite()))
+ return te;
+ else
+ return null;
+ }
+
+ public static TileEntity getConnectableTile(IBlockAccess world, int x, int y, int z, ForgeDirection face) {
+ TileEntity te = world.getTileEntity(x+face.offsetX, y+face.offsetY, z+face.offsetZ);
+ if (te instanceof IEssentiaTransport && ((IEssentiaTransport)te).isConnectable(face.getOpposite()))
+ return te;
+ else
+ return null;
+ }
+
+ private static HashMap<Integer, AspectList> allAspects= new HashMap<Integer, AspectList>();
+ private static HashMap<Integer, AspectList> allCompoundAspects= new HashMap<Integer, AspectList>();
+
+ public static AspectList getAllAspects(int amount) {
+ if (allAspects.get(amount)==null) {
+ AspectList al = new AspectList();
+ for (Aspect aspect:Aspect.aspects.values()) {
+ al.add(aspect, amount);
+ }
+ allAspects.put(amount, al);
+ }
+ return allAspects.get(amount);
+ }
+
+ public static AspectList getAllCompoundAspects(int amount) {
+ if (allCompoundAspects.get(amount)==null) {
+ AspectList al = new AspectList();
+ for (Aspect aspect:Aspect.getCompoundAspects()) {
+ al.add(aspect, amount);
+ }
+ allCompoundAspects.put(amount, al);
+ }
+ return allCompoundAspects.get(amount);
+ }
+
+
+ /**
+ * 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<Aspect> getPrimalAspects() {
+ ArrayList<Aspect> primals = new ArrayList<Aspect>();
+ Collection<Aspect> pa = aspects.values();
+ for (Aspect aspect:pa) {
+ if (aspect.isPrimal()) primals.add(aspect);
+ }
+ return primals;
+ }
+
+ public static ArrayList<Aspect> getCompoundAspects() {
+ ArrayList<Aspect> compounds = new ArrayList<Aspect>();
+ Collection<Aspect> pa = aspects.values();
+ for (Aspect aspect:pa) {
+ if (!aspect.isPrimal()) compounds.add(aspect);
+ }
+ return compounds;
+ }
+
+ public String getChatcolor() {
+ return chatcolor;
+ }
+
+ public void setChatcolor(String chatcolor) {
+ this.chatcolor = chatcolor;
+ }
+
+
+ ///////////////////////////////
+ public static LinkedHashMap<String,Aspect> aspects = new LinkedHashMap<String,Aspect>();
+
+ //PRIMAL
+ public static final Aspect AIR = new Aspect("aer",0xffff7e,"e",1);
+ public static final Aspect EARTH = new Aspect("terra",0x56c000,"2",1);
+ public static final Aspect FIRE = new Aspect("ignis",0xff5a01,"c",1);
+ public static final Aspect WATER = new Aspect("aqua",0x3cd4fc,"3",1);
+ public static final Aspect ORDER = new Aspect("ordo",0xd5d4ec,"7",1);
+ public static final Aspect ENTROPY = new Aspect("perditio",0x404040,"8",771);
+
+ //SECONDARY
+ 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<Aspect,Integer> aspects = new LinkedHashMap<Aspect,Integer>();//aspects associated with this object
+
+
+ /**
+ * this creates a new aspect list with preloaded values based off the aspects of the given item.
+ * @param the itemstack of the given item
+ */
+ public AspectList(ItemStack stack) {
+ try {
+ AspectList temp = 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;a<out.length-1;a++) {
+ Aspect e1 = out[a];
+ Aspect e2 = out[a+1];
+ if (e1!=null && e2!=null && e1.getTag().compareTo(e2.getTag())>0) {
+ out[a] = e2;
+ out[a+1] = e1;
+ change = true;
+ break;
+ }
+ }
+ } while (change==true);
+ return out;
+ } catch (Exception e) {
+ return this.getAspects();
+ }
+ }
+
+ /**
+ * @return an array of all the aspects in this collection sorted by amount
+ */
+ public Aspect[] getAspectsSortedAmount() {
+ try {
+ Aspect[] out = aspects.keySet().toArray(new Aspect[1]);
+ boolean change=false;
+ do {
+ change=false;
+ for(int a=0;a<out.length-1;a++) {
+ int e1 = getAmount(out[a]);
+ int e2 = getAmount(out[a+1]);
+ if (e1>0 && e2>0 && e2>e1) {
+ Aspect ea = out[a];
+ Aspect eb = out[a+1];
+ out[a] = eb;
+ out[a+1] = ea;
+ change = true;
+ break;
+ }
+ }
+ } while (change==true);
+ return out;
+ } catch (Exception e) {
+ return this.getAspects();
+ }
+ }
+
+ /**
+ * @param key
+ * @return the amount associated with the given aspect in this collection
+ */
+ public int getAmount(Aspect key) {
+ return aspects.get(key)==null?0:aspects.get(key);
+ }
+
+ /**
+ * Reduces the amount of an aspect in this collection by the given amount.
+ * @param key
+ * @param amount
+ * @return
+ */
+ public boolean reduce(Aspect key, int amount) {
+ if (getAmount(key)>=amount) {
+ int am = getAmount(key)-amount;
+ aspects.put(key, am);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Reduces the amount of an aspect in this collection by the given amount.
+ * If reduced to 0 or less the aspect will be removed completely.
+ * @param key
+ * @param amount
+ * @return
+ */
+ public AspectList remove(Aspect key, int amount) {
+ int am = getAmount(key)-amount;
+ if (am<=0) aspects.remove(key); else
+ this.aspects.put(key, am);
+ return this;
+ }
+
+ /**
+ * Simply removes the aspect from the list
+ * @param key
+ * @param amount
+ * @return
+ */
+ public AspectList remove(Aspect key) {
+ aspects.remove(key);
+ return this;
+ }
+
+ /**
+ * Adds this aspect and amount to the collection.
+ * If the aspect exists then its value will be increased by the given amount.
+ * @param aspect
+ * @param amount
+ * @return
+ */
+ public AspectList add(Aspect aspect, int amount) {
+ if (this.aspects.containsKey(aspect)) {
+ int oldamount = this.aspects.get(aspect);
+ amount+=oldamount;
+ }
+ this.aspects.put( aspect, amount );
+ return this;
+ }
+
+
+ /**
+ * Adds this aspect and amount to the collection.
+ * If the aspect exists then only the highest of the old or new amount will be used.
+ * @param aspect
+ * @param amount
+ * @return
+ */
+ public AspectList merge(Aspect aspect, int amount) {
+ if (this.aspects.containsKey(aspect)) {
+ int oldamount = this.aspects.get(aspect);
+ if (amount<oldamount) amount=oldamount;
+
+ }
+ this.aspects.put( aspect, amount );
+ return this;
+ }
+
+ public AspectList add(AspectList in) {
+ for (Aspect a:in.getAspects())
+ this.add(a, in.getAmount(a));
+ return this;
+ }
+
+ public AspectList merge(AspectList in) {
+ for (Aspect a:in.getAspects())
+ this.merge(a, in.getAmount(a));
+ return this;
+ }
+
+ /**
+ * Reads the list of aspects from nbt
+ * @param nbttagcompound
+ * @return
+ */
+ public void readFromNBT(NBTTagCompound nbttagcompound)
+ {
+ aspects.clear();
+ NBTTagList tlist = nbttagcompound.getTagList("Aspects",(byte)10);
+ for (int j = 0; j < tlist.tagCount(); j++) {
+ NBTTagCompound rs = (NBTTagCompound) tlist.getCompoundTagAt(j);
+ if (rs.hasKey("key")) {
+ add( Aspect.getAspect(rs.getString("key")),
+ rs.getInteger("amount"));
+ }
+ }
+ }
+
+ public void readFromNBT(NBTTagCompound nbttagcompound, String label)
+ {
+ aspects.clear();
+ NBTTagList tlist = nbttagcompound.getTagList(label,(byte)10);
+ for (int j = 0; j < tlist.tagCount(); j++) {
+ NBTTagCompound rs = (NBTTagCompound) tlist.getCompoundTagAt(j);
+ if (rs.hasKey("key")) {
+ add( Aspect.getAspect(rs.getString("key")),
+ rs.getInteger("amount"));
+ }
+ }
+ }
+
+ /**
+ * Writes the list of aspects to nbt
+ * @param nbttagcompound
+ * @return
+ */
+ public void writeToNBT(NBTTagCompound nbttagcompound)
+ {
+ NBTTagList tlist = new NBTTagList();
+ nbttagcompound.setTag("Aspects", tlist);
+ for (Aspect aspect : getAspects())
+ if (aspect != null) {
+ NBTTagCompound f = new NBTTagCompound();
+ f.setString("key", aspect.getTag());
+ f.setInteger("amount", getAmount(aspect));
+ tlist.appendTag(f);
+ }
+ }
+
+ public void writeToNBT(NBTTagCompound nbttagcompound, String label)
+ {
+ NBTTagList tlist = new NBTTagList();
+ nbttagcompound.setTag(label, tlist);
+ for (Aspect aspect : getAspects())
+ if (aspect != null) {
+ NBTTagCompound f = new NBTTagCompound();
+ f.setString("key", aspect.getTag());
+ f.setInteger("amount", getAmount(aspect));
+ tlist.appendTag(f);
+ }
+ }
+
+}
diff --git a/src/api/java/thaumcraft/api/aspects/AspectSourceHelper.java b/src/api/java/thaumcraft/api/aspects/AspectSourceHelper.java
new file mode 100644
index 0000000..f22d8ce
--- /dev/null
+++ b/src/api/java/thaumcraft/api/aspects/AspectSourceHelper.java
@@ -0,0 +1,58 @@
+package thaumcraft.api.aspects;
+
+import java.lang.reflect.Method;
+
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+import cpw.mods.fml.common.FMLLog;
+
+public class AspectSourceHelper {
+
+ static Method drainEssentia;
+ static Method findEssentia;
+ /**
+ * This method is what is used to drain essentia from jars and other sources for things like
+ * infusion crafting or powering the arcane furnace. A record of possible sources are kept track of
+ * and refreshed as needed around the calling tile entity. This also renders the essentia trail particles.
+ * Only 1 essentia is drained at a time
+ * @param tile the tile entity that is draining the essentia
+ * @param aspect the aspect that you are looking for
+ * @param direction the direction from which you wish to drain. Forgedirection.Unknown simply seeks in all directions.
+ * @param range how many blocks you wish to search for essentia sources.
+ * @return boolean returns true if essentia was found and removed from a source.
+ */
+ public static boolean drainEssentia(TileEntity tile, Aspect aspect, ForgeDirection direction, int range) {
+ try {
+ if(drainEssentia == null) {
+ Class fake = Class.forName("thaumcraft.common.lib.events.EssentiaHandler");
+ drainEssentia = fake.getMethod("drainEssentia", TileEntity.class, Aspect.class, ForgeDirection.class, int.class);
+ }
+ return (Boolean) drainEssentia.invoke(null, tile, aspect, direction, range);
+ } catch(Exception ex) {
+ FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.lib.events.EssentiaHandler method drainEssentia");
+ }
+ return false;
+ }
+
+ /**
+ * This method returns if there is any essentia of the passed type that can be drained. It in no way checks how
+ * much there is, only if an essentia container nearby contains at least 1 point worth.
+ * @param tile the tile entity that is checking the essentia
+ * @param aspect the aspect that you are looking for
+ * @param direction the direction from which you wish to drain. Forgedirection.Unknown simply seeks in all directions.
+ * @param range how many blocks you wish to search for essentia sources.
+ * @return boolean returns true if essentia was found and removed from a source.
+ */
+ public static boolean findEssentia(TileEntity tile, Aspect aspect, ForgeDirection direction, int range) {
+ try {
+ if(findEssentia == null) {
+ Class fake = Class.forName("thaumcraft.common.lib.events.EssentiaHandler");
+ findEssentia = fake.getMethod("findEssentia", TileEntity.class, Aspect.class, ForgeDirection.class, int.class);
+ }
+ return (Boolean) findEssentia.invoke(null, tile, aspect, direction, range);
+ } catch(Exception ex) {
+ FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.lib.events.EssentiaHandler method findEssentia");
+ }
+ return false;
+ }
+}
diff --git a/src/api/java/thaumcraft/api/aspects/IAspectContainer.java b/src/api/java/thaumcraft/api/aspects/IAspectContainer.java
new file mode 100644
index 0000000..bb34ae8
--- /dev/null
+++ b/src/api/java/thaumcraft/api/aspects/IAspectContainer.java
@@ -0,0 +1,80 @@
+package thaumcraft.api.aspects;
+
+
+/**
+ *
+ * @author azanor
+ *
+ * Used by blocks like the crucible and alembic to hold their aspects.
+ * Tiles extending this interface will have their aspects show up when viewed by goggles of revealing
+ *
+ */
+public interface IAspectContainer {
+ public AspectList getAspects();
+
+
+ public void setAspects(AspectList aspects);
+
+
+ /**
+ * This method is used to determine of a specific aspect can be added to this container.
+ * @param tag
+ * @return true or false
+ */
+ public boolean doesContainerAccept(Aspect tag);
+
+ /**
+ * This method is used to add a certain amount of an aspect to the tile entity.
+ * @param tag
+ * @param amount
+ * @return the amount of aspect left over that could not be added.
+ */
+ public int addToContainer(Aspect tag, int amount);
+
+ /**
+ * Removes a certain amount of a specific aspect from the tile entity
+ * @param tag
+ * @param amount
+ * @return true if that amount of aspect was available and was removed
+ */
+ public boolean takeFromContainer(Aspect tag, int amount);
+
+ /**
+ * removes a bunch of different aspects and amounts from the tile entity.
+ * @param ot the ObjectTags object that contains the aspects and their amounts.
+ * @return true if all the aspects and their amounts were available and successfully removed
+ *
+ * Going away in the next major patch
+ */
+ @Deprecated
+ public boolean takeFromContainer(AspectList ot);
+
+ /**
+ * Checks if the tile entity contains the listed amount (or more) of the aspect
+ * @param tag
+ * @param amount
+ * @return
+ */
+ public boolean doesContainerContainAmount(Aspect tag,int amount);
+
+ /**
+ * Checks if the tile entity contains all the listed aspects and their amounts
+ * @param ot the ObjectTags object that contains the aspects and their amounts.
+ * @return
+ *
+ * Going away in the next major patch
+ */
+ @Deprecated
+ public boolean doesContainerContain(AspectList ot);
+
+ /**
+ * Returns how much of the aspect this tile entity contains
+ * @param tag
+ * @return the amount of that aspect found
+ */
+ public int containerContains(Aspect tag);
+
+}
+
+
+
diff --git a/src/api/java/thaumcraft/api/aspects/IAspectSource.java b/src/api/java/thaumcraft/api/aspects/IAspectSource.java
new file mode 100644
index 0000000..c01f569
--- /dev/null
+++ b/src/api/java/thaumcraft/api/aspects/IAspectSource.java
@@ -0,0 +1,16 @@
+package thaumcraft.api.aspects;
+
+
+
+/**
+ * @author Azanor
+ *
+ * This interface is implemented by tile entites (or possibly anything else) like jars
+ * so that they can act as an essentia source for blocks like the infusion altar.
+ *
+ */
+public interface IAspectSource extends IAspectContainer {
+
+
+
+}
diff --git a/src/api/java/thaumcraft/api/aspects/IEssentiaContainerItem.java b/src/api/java/thaumcraft/api/aspects/IEssentiaContainerItem.java
new file mode 100644
index 0000000..6a82c0e
--- /dev/null
+++ b/src/api/java/thaumcraft/api/aspects/IEssentiaContainerItem.java
@@ -0,0 +1,37 @@
+package thaumcraft.api.aspects;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+/**
+ *
+ * @author azanor
+ *
+ * Used by wispy essences and essentia phials to hold their aspects.
+ * Useful for similar item containers that store their aspect information in nbt form so TC
+ * automatically picks up the aspects they contain
+ *
+ */
+public interface IEssentiaContainerItem {
+ public AspectList getAspects(ItemStack itemstack);
+ public void setAspects(ItemStack itemstack, AspectList aspects);
+}
+
+//Example implementation
+/*
+ @Override
+ public AspectList getAspects(ItemStack itemstack) {
+ if (itemstack.hasTagCompound()) {
+ AspectList aspects = new AspectList();
+ aspects.readFromNBT(itemstack.getTagCompound());
+ return aspects.size()>0?aspects:null;
+ }
+ return null;
+ }
+
+ @Override
+ public void setAspects(ItemStack itemstack, AspectList aspects) {
+ if (!itemstack.hasTagCompound()) itemstack.setTagCompound(new NBTTagCompound());
+ aspects.writeToNBT(itemstack.getTagCompound());
+ }
+*/ \ 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<ItemStack>)catalyst).size()>0) {
+ for (ItemStack is :(ArrayList<ItemStack>)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<ItemStack>)catalyst).size()>0) {
+ ItemStack[] ores = ((ArrayList<ItemStack>)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)<aspects.getAmount(tag)) return false;
+ }
+ return true;
+ }
+
+ public boolean catalystMatches(ItemStack cat) {
+ if (catalyst instanceof ItemStack && ThaumcraftApiHelper.itemMatches((ItemStack) catalyst,cat,false)) {
+ return true;
+ } else
+ if (catalyst instanceof ArrayList && ((ArrayList<ItemStack>)catalyst).size()>0) {
+ ItemStack[] ores = ((ArrayList<ItemStack>)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..bdc5f50
--- /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<ItemStack> 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<ItemStack> ii = new ArrayList<ItemStack>();
+ for (ItemStack is:input) {
+ ii.add(is.copy());
+ }
+
+ for (ItemStack comp:components) {
+ boolean b=false;
+ for (int a=0;a<ii.size();a++) {
+ i2 = ii.get(a).copy();
+ if (comp.getItemDamage()==OreDictionary.WILDCARD_VALUE) {
+ i2.setItemDamage(OreDictionary.WILDCARD_VALUE);
+ }
+ if (areItemStacksEqual(i2, comp,true)) {
+ ii.remove(a);
+ b=true;
+ break;
+ }
+ }
+ if (!b) return false;
+ }
+// System.out.println(ii.size());
+ return ii.size()==0?true:false;
+ }
+
+ protected boolean areItemStacksEqual(ItemStack stack0, ItemStack stack1, boolean fuzzy)
+ {
+ if (stack0==null && stack1!=null) return false;
+ if (stack0!=null && stack1==null) return false;
+ if (stack0==null && stack1==null) return true;
+ boolean t1=ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(stack0, stack1);
+ if (!t1) return false;
+ if (fuzzy) {
+ Integer od = OreDictionary.getOreID(stack0);
+ if (od!=-1) {
+ ItemStack[] ores = OreDictionary.getOres(od).toArray(new ItemStack[]{});
+ if (ThaumcraftApiHelper.containsMatch(false, new ItemStack[]{stack1}, ores))
+ return true;
+ }
+ }
+ return stack0.getItem() != stack1.getItem() ? false : (stack0.getItemDamage() != stack1.getItemDamage() ? false : stack0.stackSize <= stack0.getMaxStackSize() );
+ }
+
+
+ public Enchantment getEnchantment() {
+ return enchantment;
+
+ }
+
+ public AspectList getAspects() {
+ return aspects;
+
+ }
+
+ public String getResearch() {
+ return research;
+
+ }
+
+ public int calcInstability(ItemStack recipeInput) {
+ int i = 0;
+ Map map1 = EnchantmentHelper.getEnchantments(recipeInput);
+ Iterator iterator = map1.keySet().iterator();
+ while (iterator.hasNext())
+ {
+ int j1 = ((Integer)iterator.next()).intValue();
+ i += EnchantmentHelper.getEnchantmentLevel(j1, recipeInput);
+ }
+ return (i/2) + instability;
+ }
+
+ public int calcXP(ItemStack recipeInput) {
+ return recipeXP * (1+EnchantmentHelper.getEnchantmentLevel(enchantment.effectId, recipeInput));
+ }
+
+ public float getEssentiaMod(ItemStack recipeInput) {
+ float mod = EnchantmentHelper.getEnchantmentLevel(enchantment.effectId, recipeInput);
+ Map map1 = EnchantmentHelper.getEnchantments(recipeInput);
+ Iterator iterator = map1.keySet().iterator();
+ while (iterator.hasNext())
+ {
+ int j1 = ((Integer)iterator.next()).intValue();
+ if (j1 != enchantment.effectId)
+ mod += EnchantmentHelper.getEnchantmentLevel(j1, recipeInput) * .1f;
+ }
+ return mod;
+ }
+
+}
diff --git a/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java b/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java
new file mode 100644
index 0000000..d786b81
--- /dev/null
+++ b/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java
@@ -0,0 +1,133 @@
+package thaumcraft.api.crafting;
+
+import java.util.ArrayList;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.world.World;
+import net.minecraftforge.oredict.OreDictionary;
+import thaumcraft.api.ThaumcraftApiHelper;
+import thaumcraft.api.aspects.AspectList;
+
+public class InfusionRecipe
+{
+ protected AspectList aspects;
+ protected String research;
+ private ItemStack[] components;
+ private ItemStack recipeInput;
+ protected Object recipeOutput;
+ protected int instability;
+
+ public InfusionRecipe(String research, Object output, int inst,
+ AspectList aspects2, ItemStack input, ItemStack[] recipe) {
+ this.research = research;
+ this.recipeOutput = output;
+ this.recipeInput = input;
+ this.aspects = aspects2;
+ this.components = recipe;
+ this.instability = inst;
+ }
+
+ /**
+ * Used to check if a recipe matches current crafting inventory
+ * @param player
+ */
+ public boolean matches(ArrayList<ItemStack> input, ItemStack central, World world, EntityPlayer player) {
+ if (getRecipeInput()==null) return false;
+
+ if (research.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<ItemStack> ii = new ArrayList<ItemStack>();
+ for (ItemStack is:input) {
+ ii.add(is.copy());
+ }
+
+ for (ItemStack comp:getComponents()) {
+ boolean b=false;
+ for (int a=0;a<ii.size();a++) {
+ i2 = ii.get(a).copy();
+ if (comp.getItemDamage()==OreDictionary.WILDCARD_VALUE) {
+ i2.setItemDamage(OreDictionary.WILDCARD_VALUE);
+ }
+ if (areItemStacksEqual(i2, comp,true)) {
+ ii.remove(a);
+ b=true;
+ break;
+ }
+ }
+ if (!b) return false;
+ }
+ return ii.size()==0?true:false;
+ }
+
+ public static boolean areItemStacksEqual(ItemStack stack0, ItemStack stack1, boolean fuzzy)
+ {
+ if (stack0==null && stack1!=null) return false;
+ if (stack0!=null && stack1==null) return false;
+ if (stack0==null && stack1==null) return true;
+
+ //nbt
+ boolean t1=ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(stack0, stack1);
+ if (!t1) return false;
+
+ if (fuzzy) {
+ Integer od = OreDictionary.getOreID(stack0);
+ if (od!=-1) {
+ ItemStack[] ores = OreDictionary.getOres(od).toArray(new ItemStack[]{});
+ if (ThaumcraftApiHelper.containsMatch(false, new ItemStack[]{stack1}, ores))
+ return true;
+ }
+ }
+
+ //damage
+ boolean damage = stack0.getItemDamage() == stack1.getItemDamage() ||
+ stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE;
+
+ return stack0.getItem() != stack1.getItem() ? false : (!damage ? false : stack0.stackSize <= stack0.getMaxStackSize() );
+ }
+
+ public Object getRecipeOutput() {
+ return getRecipeOutput(this.getRecipeInput());
+ }
+
+ public AspectList getAspects() {
+ return getAspects(this.getRecipeInput());
+ }
+
+ public int getInstability() {
+ return getInstability(this.getRecipeInput());
+ }
+
+ public String getResearch() {
+ return research;
+ }
+
+ public ItemStack getRecipeInput() {
+ return recipeInput;
+ }
+
+ public ItemStack[] getComponents() {
+ return components;
+ }
+
+ public Object getRecipeOutput(ItemStack input) {
+ return recipeOutput;
+ }
+
+ public AspectList getAspects(ItemStack input) {
+ return aspects;
+ }
+
+ public int getInstability(ItemStack input) {
+ return instability;
+ }
+}
diff --git a/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java b/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java
new file mode 100644
index 0000000..1490110
--- /dev/null
+++ b/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java
@@ -0,0 +1,261 @@
+package thaumcraft.api.crafting;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+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 ShapedArcaneRecipe implements IArcaneRecipe
+{
+ //Added in for future ease of change, but hard coded for now.
+ private static final int MAX_CRAFT_GRID_WIDTH = 3;
+ private static final int MAX_CRAFT_GRID_HEIGHT = 3;
+
+ public ItemStack output = null;
+ public Object[] input = null;
+ public AspectList aspects = null;
+ public String research;
+ public int width = 0;
+ public int height = 0;
+ private boolean mirrored = true;
+
+ public ShapedArcaneRecipe(String research, Block result, AspectList aspects, Object... recipe){ this(research, new ItemStack(result), aspects, recipe); }
+ public ShapedArcaneRecipe(String research, Item result, AspectList aspects, Object... recipe){ this(research, new ItemStack(result), aspects, recipe); }
+ public ShapedArcaneRecipe(String research, ItemStack result, AspectList aspects, Object... recipe)
+ {
+ output = result.copy();
+ this.research = research;
+ this.aspects = aspects;
+ String shape = "";
+
+ int idx = 0;
+
+ if (recipe[idx] instanceof Boolean)
+ {
+ mirrored = (Boolean)recipe[idx];
+ if (recipe[idx+1] instanceof Object[])
+ {
+ recipe = (Object[])recipe[idx+1];
+ }
+ else
+ {
+ idx = 1;
+ }
+ }
+
+ if (recipe[idx] instanceof String[])
+ {
+ String[] parts = ((String[])recipe[idx++]);
+
+ for (String s : parts)
+ {
+ width = s.length();
+ shape += s;
+ }
+
+ height = parts.length;
+ }
+ else
+ {
+ while (recipe[idx] instanceof String)
+ {
+ String s = (String)recipe[idx++];
+ shape += s;
+ width = s.length();
+ height++;
+ }
+ }
+
+ if (width * height != shape.length())
+ {
+ String ret = "Invalid shaped ore recipe: ";
+ for (Object tmp : recipe)
+ {
+ ret += tmp + ", ";
+ }
+ ret += output;
+ throw new RuntimeException(ret);
+ }
+
+ HashMap<Character, Object> itemMap = new HashMap<Character, Object>();
+
+ for (; idx < recipe.length; idx += 2)
+ {
+ Character chr = (Character)recipe[idx];
+ Object in = recipe[idx + 1];
+
+ if (in instanceof ItemStack)
+ {
+ itemMap.put(chr, ((ItemStack)in).copy());
+ }
+ else if (in instanceof Item)
+ {
+ itemMap.put(chr, new ItemStack((Item)in));
+ }
+ else if (in instanceof Block)
+ {
+ itemMap.put(chr, new ItemStack((Block)in, 1, OreDictionary.WILDCARD_VALUE));
+ }
+ else if (in instanceof String)
+ {
+ itemMap.put(chr, OreDictionary.getOres((String)in));
+ }
+ else
+ {
+ String ret = "Invalid shaped ore recipe: ";
+ for (Object tmp : recipe)
+ {
+ ret += tmp + ", ";
+ }
+ ret += output;
+ throw new RuntimeException(ret);
+ }
+ }
+
+ input = new Object[width * height];
+ int x = 0;
+ for (char chr : shape.toCharArray())
+ {
+ input[x++] = itemMap.get(chr);
+ }
+ }
+
+ @Override
+ public ItemStack getCraftingResult(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<ItemStack>)target)
+ {
+ matched = matched || checkItemEquals(item, slot);
+ }
+
+ if (!matched)
+ {
+ return false;
+ }
+ }
+ else if (target == null && slot != null)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private boolean checkItemEquals(ItemStack target, ItemStack input)
+ {
+ if (input == null && target != null || input != null && target == null)
+ {
+ return false;
+ }
+ return (target.getItem() == input.getItem() &&
+ (!target.hasTagCompound() || ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(input,target)) &&
+ (target.getItemDamage() == OreDictionary.WILDCARD_VALUE|| target.getItemDamage() == input.getItemDamage()));
+ }
+
+ public ShapedArcaneRecipe setMirrored(boolean mirror)
+ {
+ mirrored = mirror;
+ return this;
+ }
+
+ /**
+ * Returns the input for this recipe, any mod accessing this value should never
+ * manipulate the values in this array as it will effect the recipe itself.
+ * @return The recipes input vales.
+ */
+ public Object[] getInput()
+ {
+ return this.input;
+ }
+
+ @Override
+ public AspectList getAspects() {
+ return aspects;
+ }
+
+ @Override
+ public AspectList getAspects(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<ItemStack>)next)
+ {
+ match = match || checkItemEquals(item, slot);
+ }
+ }
+
+ if (match)
+ {
+ inRecipe = true;
+ required.remove(next);
+ break;
+ }
+ }
+
+ if (!inRecipe)
+ {
+ return false;
+ }
+ }
+ }
+
+ return required.isEmpty();
+ }
+
+ private boolean checkItemEquals(ItemStack target, ItemStack input)
+ {
+ if (input == null && target != null || input != null && target == null)
+ {
+ return false;
+ }
+ return (target.getItem() == input.getItem() &&
+ (!target.hasTagCompound() || ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(input,target)) &&
+ (target.getItemDamage() == OreDictionary.WILDCARD_VALUE|| target.getItemDamage() == input.getItemDamage()));
+ }
+
+ /**
+ * Returns the input for this recipe, any mod accessing this value should never
+ * manipulate the values in this array as it will effect the recipe itself.
+ * @return The recipes input vales.
+ */
+ public ArrayList getInput()
+ {
+ return this.input;
+ }
+
+ @Override
+ public AspectList getAspects() {
+ return aspects;
+ }
+
+ @Override
+ public AspectList getAspects(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<WeightedRandomLoot> lootBagCommon = new ArrayList<WeightedRandomLoot>();
+ public static ArrayList<WeightedRandomLoot> lootBagUncommon = new ArrayList<WeightedRandomLoot>();
+ public static ArrayList<WeightedRandomLoot> lootBagRare = new ArrayList<WeightedRandomLoot>();
+
+}
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..61da1f7
--- /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);
+
+ /**
+ * Set the node modifier
+ * @return
+ */
+ public void setNodeModifier(NodeModifier nodeModifier);
+
+ /**
+ * Return 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 <String, ResearchCategoryList> researchCategories = new LinkedHashMap <String,ResearchCategoryList>();
+
+ /**
+ * @param key
+ * @return the research item linked to this key
+ */
+ public static ResearchCategoryList getResearchList(String key) {
+ return researchCategories.get(key);
+ }
+
+ /**
+ * @param key
+ * @return the name of the research category linked to this key.
+ * Must be stored as localization information in the LanguageRegistry.
+ */
+ public static String getCategoryName(String key) {
+ return StatCollector.translateToLocal("tc.research_category."+key);
+ }
+
+ /**
+ * @param key the research key
+ * @return the ResearchItem object.
+ */
+ public static ResearchItem getResearch(String key) {
+ Collection rc = researchCategories.values();
+ for (Object cat:rc) {
+ Collection rl = ((ResearchCategoryList)cat).research.values();
+ for (Object ri:rl) {
+ if ((((ResearchItem)ri).key).equals(key)) return (ResearchItem)ri;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This should only be done at the PostInit stage
+ * @param key the key used for this category
+ * @param 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<String, ResearchItem> research = new HashMap<String,ResearchItem>();
+
+
+
+
+}
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<TileVisNode> parent = null;
+ ArrayList<WeakReference<TileVisNode>> children = new ArrayList<WeakReference<TileVisNode>>();
+
+ /**
+ * @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<TileVisNode> n:getChildren()) {
+ if (n!=null && n.get()!=null) {
+ n.get().removeThisNode();
+ }
+ }
+
+ children = new ArrayList<WeakReference<TileVisNode>>();
+ if (VisNetHandler.isNodeValid(this.getParent())) {
+ this.getParent().get().nodeRefresh=true;
+ }
+ this.setParent(null);
+ this.parentChanged();
+
+ if (this.isSource()) {
+ HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = VisNetHandler.sources.get(worldObj.provider.dimensionId);
+ if (sourcelist==null) {
+ sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
+ }
+ 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<TileVisNode> getParent() {
+ return parent;
+ }
+
+ /**
+ * @return
+ */
+ public WeakReference<TileVisNode> getRootSource() {
+ return VisNetHandler.isNodeValid(getParent()) ?
+ getParent().get().getRootSource() : this.isSource() ?
+ new WeakReference(this) : null;
+ }
+
+ /**
+ * @param parent
+ */
+ public void setParent(WeakReference<TileVisNode> parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * @return
+ */
+ public ArrayList<WeakReference<TileVisNode>> 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<TileVisNode> n:children) {
+ if (n==null || n.get()==null || !VisNetHandler.canNodeBeSeen(this, n.get())) {
+ nodeRefresh=true;
+ break;
+ }
+ }
+ }
+
+ //refresh linked nodes
+ if (nodeRefresh) {
+ for (WeakReference<TileVisNode> 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..7ac4c69
--- /dev/null
+++ b/src/api/java/thaumcraft/api/visnet/VisNetHandler.java
@@ -0,0 +1,282 @@
+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<WeakReference<TileVisNode>> nodes = nearbyNodes.get(drainer);
+ if (nodes!=null && nodes.size()>0)
+ for (WeakReference<TileVisNode> 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<Integer, HashMap<WorldCoordinates, WeakReference<TileVisNode>>> sources = new HashMap<Integer, HashMap<WorldCoordinates, WeakReference<TileVisNode>>>();
+
+ public static void addSource(World world, TileVisNode vs) {
+ HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = sources
+ .get(world.provider.dimensionId);
+ if (sourcelist == null) {
+ sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
+ }
+ sourcelist.put(vs.getLocation(), new WeakReference(vs));
+ sources.put(world.provider.dimensionId, sourcelist);
+ nearbyNodes.clear();
+ }
+
+ public static boolean isNodeValid(WeakReference<TileVisNode> node) {
+ if (node == null || node.get() == null || node.get().isInvalid())
+ return false;
+ return true;
+ }
+
+ public static WeakReference<TileVisNode> addNode(World world, TileVisNode vn) {
+ WeakReference ref = new WeakReference(vn);
+
+ HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = sources
+ .get(world.provider.dimensionId);
+ if (sourcelist == null) {
+ sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
+ return null;
+ }
+
+ ArrayList<Object[]> nearby = new ArrayList<Object[]>();
+
+ for (WeakReference<TileVisNode> 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<WorldCoordinates> cache = new ArrayList<WorldCoordinates>();
+ public static ArrayList<Object[]> findClosestNodes(TileVisNode target,
+ TileVisNode parent, ArrayList<Object[]> in) {
+
+ if (cache.size() > 512 || cache.contains(new WorldCoordinates(parent))) return in;
+ cache.add(new WorldCoordinates(parent));
+
+ for (WeakReference<TileVisNode> 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<WorldCoordinates, ArrayList<WeakReference<TileVisNode>>> nearbyNodes = new HashMap<WorldCoordinates, ArrayList<WeakReference<TileVisNode>>>();
+
+ private static void calculateNearbyNodes(World world, int x, int y, int z) {
+
+ HashMap<WorldCoordinates, WeakReference<TileVisNode>> sourcelist = sources
+ .get(world.provider.dimensionId);
+ if (sourcelist == null) {
+ sourcelist = new HashMap<WorldCoordinates, WeakReference<TileVisNode>>();
+ return;
+ }
+
+ ArrayList<WeakReference<TileVisNode>> cn = new ArrayList<WeakReference<TileVisNode>>();
+ WorldCoordinates drainer = new WorldCoordinates(x, y, z,
+ world.provider.dimensionId);
+
+ ArrayList<Object[]> nearby = new ArrayList<Object[]>();
+
+ for (WeakReference<TileVisNode> 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<WeakReference<TileVisNode>> children = new ArrayList<WeakReference<TileVisNode>>();
+ children = getAllChildren(source,children);
+
+ for (WeakReference<TileVisNode> 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<WeakReference<TileVisNode>> getAllChildren(TileVisNode source, ArrayList<WeakReference<TileVisNode>> list) {
+ for (WeakReference<TileVisNode> child : source.getChildren()) {
+ TileVisNode n = child.get();
+
+ if (n != null && n.getWorldObj()!=null && isChunkLoaded(n.getWorldObj(), n.xCoord, n.zCoord)) {
+ list.add(child);
+ list = getAllChildren(n,list);
+ }
+ }
+ return list;
+ }
+
+ public static boolean isChunkLoaded(World world, int x, int z) {
+ int xx = x >> 4;
+ int zz = z >> 4;
+ return world.getChunkProvider().chunkExists(xx, zz);
+ }
+
+ 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<WorldCoordinates,WeakReference<TileVisNode>>
+ // noderef = new HashMap<WorldCoordinates,WeakReference<TileVisNode>>();
+ //
+ // 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<radius*radius && noderef.get(wc).get()!=null &&
+ // !noderef.get(wc).get().isReceiver() &&
+ // isNodeValid(noderef.get(wc).get().getParent())
+ // ) {
+ // out = noderef.get(wc).get();
+ // cd = d;
+ // }
+ // }
+ // }
+ // }
+ // }
+ // return out;
+ // }
+
+}
diff --git a/src/api/java/thaumcraft/api/wands/FocusUpgradeType.java b/src/api/java/thaumcraft/api/wands/FocusUpgradeType.java
new file mode 100644
index 0000000..5c4269e
--- /dev/null
+++ b/src/api/java/thaumcraft/api/wands/FocusUpgradeType.java
@@ -0,0 +1,114 @@
+package thaumcraft.api.wands;
+
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.StatCollector;
+
+import org.apache.logging.log4j.LogManager;
+
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+
+public class FocusUpgradeType {
+
+ public static FocusUpgradeType[] types = new FocusUpgradeType[20];
+
+ public short id;
+
+ public ResourceLocation icon;
+
+ public String name;
+
+ public String text;
+
+ /**
+ * What aspects are used to calculate the cost of this upgrade. The amounts given is ignored, just the type is used for the calculation.
+ */
+ public AspectList aspects;
+
+
+
+ public FocusUpgradeType(int id, ResourceLocation icon, String name, String text, AspectList aspects) {
+ this.id = (short) id;
+ this.icon = icon;
+ this.name = name;
+ this.text = text;
+ this.aspects = aspects;
+
+ if (id<types.length && types[id]!=null) {
+ LogManager.getLogger("THAUMCRAFT").fatal("Focus Upgrade id "+id+" already occupied. Ignoring.");
+ return;
+ }
+
+ // allocate space
+ if (id>=types.length) {
+ FocusUpgradeType[] temp = new FocusUpgradeType[id+1];
+ System.arraycopy(types, 0, temp, 0, types.length);
+ types = temp;
+ }
+
+ types[id] = this;
+ }
+
+ public String getLocalizedName() {
+ return StatCollector.translateToLocal(name);
+ }
+
+ public String getLocalizedText() {
+ return StatCollector.translateToLocal(text);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof FocusUpgradeType) {
+ return this.id == ((FocusUpgradeType)obj).id;
+ } else return false;
+ }
+
+ // basic upgrade types
+ public static FocusUpgradeType potency = new FocusUpgradeType( 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..e8938e9
--- /dev/null
+++ b/src/api/java/thaumcraft/api/wands/ItemFocusBasic.java
@@ -0,0 +1,276 @@
+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 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<Short, Integer> map = new LinkedHashMap<Short, Integer>();
+ for (short id:this.getAppliedUpgrades(focusstack)) {
+ if (id>=0) {
+ int amt = 1;
+ if (map.containsKey(id)) {
+ amt = map.get(id) + 1;
+ }
+ map.put(id, amt);
+ }
+ }
+ for (Short id:map.keySet()) {
+ list.add(EnumChatFormatting.DARK_PURPLE +FocusUpgradeType.types[id].getLocalizedName()+
+ (map.get(id)>1?" "+StatCollector.translateToLocal("enchantment.level." + map.get(id)):""));
+ }
+ }
+
+ /**
+ * Purely for display on the focus tooltip (see addInformation method above)
+ */
+ public boolean isVisCostPerTick(ItemStack focusstack) {
+ return false;
+ }
+
+ @Override
+ public EnumRarity getRarity(ItemStack focusstack)
+ {
+ return EnumRarity.rare;
+ }
+
+ /**
+ * What color will the focus orb be rendered on the held wand
+ */
+ public int getFocusColor(ItemStack focusstack) {
+ return 0;
+ }
+
+
+ /**
+ * 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 AspectList getVisCost(ItemStack focusstack) {
+ return null;
+ }
+
+ /**
+ * This returns how many milliseconds must pass before the focus can be activated again.
+ */
+ public int getActivationCooldown(ItemStack focusstack) {
+ return 0;
+ }
+
+ /**
+ * Used by foci like equal trade to determine their area in artchitect mode
+ */
+ public int getMaxAreaSize(ItemStack focusstack) {
+ return 1;
+ }
+
+ /**
+ * What upgrades can be applied to this focus for ranks 1 to 5
+ */
+ public FocusUpgradeType[] getPossibleUpgradesByRank(ItemStack focusstack, int rank) {
+ return null;
+ }
+
+ /**
+ * What upgrades does the focus currently have
+ */
+ public short[] getAppliedUpgrades(ItemStack focusstack) {
+ short[] l = new short[] {-1,-1,-1,-1,-1};
+ NBTTagList nbttaglist = getFocusUpgradeTagList(focusstack);
+ if (nbttaglist == null)
+ {
+ return l;
+ }
+ else
+ {
+ for (int j = 0; j < nbttaglist.tagCount(); ++j)
+ {
+ if (j>=5) break;
+ l[j] = nbttaglist.getCompoundTagAt(j).getShort("id");
+ }
+
+ return l;
+ }
+ }
+
+ public boolean applyUpgrade(ItemStack focusstack, FocusUpgradeType type, int rank) {
+ short[] upgrades = getAppliedUpgrades(focusstack);
+ if (upgrades[rank-1]!=-1 || rank<1 || rank>5) {
+ return false;
+ }
+ upgrades[rank-1] = type.id;
+ setFocusUpgradeTagList(focusstack, upgrades);
+ return true;
+ }
+
+ /**
+ * Use this method to define custom logic about which upgrades can be applied. This can be used to set up upgrade "trees"
+ * that make certain upgrades available only when others are unlocked first, when certain research is completed, or similar logic.
+ *
+ */
+ public boolean canApplyUpgrade(ItemStack focusstack, EntityPlayer player, FocusUpgradeType type, int rank) {
+ return true;
+ }
+
+ /**
+ * Does this focus have the passed upgrade type
+ */
+ public boolean isUpgradedWith(ItemStack focusstack, FocusUpgradeType focusUpgradetype) {
+ return getUpgradeLevel(focusstack,focusUpgradetype)>0;
+ }
+
+ /**
+ * What level is the passed upgrade type on the focus. If it is not present it returns 0
+ */
+ public int getUpgradeLevel(ItemStack focusstack, FocusUpgradeType focusUpgradetype) {
+ short[] list = getAppliedUpgrades(focusstack);
+ int level=0;
+ for (short id:list) {
+ if (id == focusUpgradetype.id)
+ {
+ level++;
+ }
+ }
+ return level;
+ }
+
+ 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<Aspect> specialCostModifierAspects;
+
+ /**
+ * the amount by which the specified aspect costs are multiplied
+ */
+ float specialCostModifier;
+
+ /**
+ * The texture that will be used for the ingame wand cap
+ */
+ ResourceLocation texture;
+
+ /**
+ * the actual item that makes up this cap and will be used to generate the wand recipes
+ */
+ ItemStack item;
+
+ public static LinkedHashMap<String,WandCap> caps = new LinkedHashMap<String,WandCap>();
+
+ public WandCap (String tag, float discount, 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<Aspect> 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<Aspect> 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<String,WandRod> rods = new LinkedHashMap<String,WandRod>();
+
+ 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<String,HashMap<List,List>> triggers = new HashMap<String,HashMap<List,List>>();
+ private static final String DEFAULT = "default";
+
+ /**
+ * Registers an action to perform when a casting wand right clicks on a specific block.
+ * A manager class needs to be created that implements IWandTriggerManager.
+ * @param manager
+ * @param event a logical number that you can use to differentiate different events or actions
+ * @param 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<List,List>());
+ }
+ HashMap<List,List> 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<List,List> 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<List,List> 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<List,List> 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<List,List> 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/lance5057/tDefense/TD_Commands.java b/src/main/java/lance5057/tDefense/TD_Commands.java
index 258480f..8fc4eec 100644
--- a/src/main/java/lance5057/tDefense/TD_Commands.java
+++ b/src/main/java/lance5057/tDefense/TD_Commands.java
@@ -16,7 +16,7 @@ import lance5057.tDefense.armor.renderers.heavy.ModelTinkersSabatons;
import lance5057.tDefense.armor.renderers.light.ModelTinkersBoots;
import lance5057.tDefense.armor.renderers.light.ModelTinkersChausses;
import lance5057.tDefense.armor.renderers.light.ModelTinkersCoif;
-import lance5057.tDefense.armor.renderers.light.ModelTinkersHalberd;
+import lance5057.tDefense.armor.renderers.light.ModelTinkersHauberk;
import lance5057.tDefense.proxy.ClientProxy;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommand;
@@ -122,7 +122,7 @@ public class TD_Commands extends CommandBase implements ICommand
ClientProxy.shoes = new ModelTinkersBoots();
ClientProxy.coif = new ModelTinkersCoif();
- ClientProxy.halberd = new ModelTinkersHalberd();
+ ClientProxy.hauberk = new ModelTinkersHauberk();
ClientProxy.chausses = new ModelTinkersChausses();
ClientProxy.boots = new ModelTinkersBoots();
}
diff --git a/src/main/java/lance5057/tDefense/TD_Config.java b/src/main/java/lance5057/tDefense/TD_Config.java
index 6035707..4421675 100644
--- a/src/main/java/lance5057/tDefense/TD_Config.java
+++ b/src/main/java/lance5057/tDefense/TD_Config.java
@@ -1,10 +1,7 @@
package lance5057.tDefense;
-import java.util.Vector;
-
-import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.common.config.Configuration;
-import net.minecraftforge.common.config.Property;
+import cpw.mods.fml.common.event.FMLPreInitializationEvent;
public class TD_Config
{
@@ -37,6 +34,10 @@ public class TD_Config
public boolean BotaniaAddon;
public int CorpseIvyModID;
+ public boolean ThaumcraftAddon;
+ public int RevealingModID;
+ public int VisDiscountModID;
+
public TD_Config(FMLPreInitializationEvent e)
{
Configuration config = new Configuration(e.getSuggestedConfigurationFile());
@@ -72,6 +73,10 @@ public class TD_Config
BotaniaAddon = config.getBoolean("Enable Botania Addon", "Botania Addon", true, "Still requires Botania to use");
CorpseIvyModID = config.getInt("Corpse Drinker Ivy Modifier ID", "Botania Addon", 60, 0, Integer.MAX_VALUE, "");
+ ThaumcraftAddon = config.getBoolean("Enable Thaumcraft Addon", "Thaumcraft Addon", true, "Requires Thaumcraft to use");
+ RevealingModID = config.getInt("Revealing Modifier ID", "Thaumcraft Addon", 70, 0, Integer.MAX_VALUE, "");
+ VisDiscountModID = config.getInt("Vis Discount Modifier ID", "Thaumcraft Addon", 71, 0, Integer.MAX_VALUE, "");
+
config.save();
}
}
diff --git a/src/main/java/lance5057/tDefense/TinkersDefense.java b/src/main/java/lance5057/tDefense/TinkersDefense.java
index 04421fc..43261aa 100644
--- a/src/main/java/lance5057/tDefense/TinkersDefense.java
+++ b/src/main/java/lance5057/tDefense/TinkersDefense.java
@@ -25,7 +25,7 @@ import lance5057.tDefense.armor.items.heavy.TinkersSabatons;
import lance5057.tDefense.armor.items.light.TinkersBoots;
import lance5057.tDefense.armor.items.light.TinkersChausses;
import lance5057.tDefense.armor.items.light.TinkersCoif;
-import lance5057.tDefense.armor.items.light.TinkersHalberd;
+import lance5057.tDefense.armor.items.light.TinkersHauberk;
import lance5057.tDefense.armor.parts.Cloth;
import lance5057.tDefense.armor.parts.ClothMaterial;
import lance5057.tDefense.blocks.JewelersBench;
@@ -406,7 +406,7 @@ public class TinkersDefense
armor_TinkerShoes = new TinkersShoes();
armor_TinkerCoif = new TinkersCoif();
- armor_TinkerHalberd = new TinkersHalberd();
+ armor_TinkerHalberd = new TinkersHauberk();
armor_TinkerChausses = new TinkersChausses();
armor_TinkerBoots = new TinkersBoots();
diff --git a/src/main/java/lance5057/tDefense/armor/ArmorCore.java b/src/main/java/lance5057/tDefense/armor/ArmorCore.java
index 6405da0..b68210c 100644
--- a/src/main/java/lance5057/tDefense/armor/ArmorCore.java
+++ b/src/main/java/lance5057/tDefense/armor/ArmorCore.java
@@ -1,7 +1,6 @@
package lance5057.tDefense.armor;
import lance5057.tDefense.TinkersDefense;
-import lance5057.tDefense.armor.modifiers.ArmorMods;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -14,15 +13,19 @@ import net.minecraft.world.World;
import net.minecraftforge.common.ISpecialArmor;
import tconstruct.library.tools.AbilityHelper;
import tconstruct.library.tools.ToolCore;
+import thaumcraft.api.IRunicArmor;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
-public class ArmorCore extends ToolCore implements ISpecialArmor
+public class ArmorCore extends ToolCore implements ISpecialArmor, IRunicArmor
{
int slot;
public float reductionPercent = 0f;
protected int maxReduction = 100;
+ //Thaumcraft
+ boolean Charge = false;
+
public ArmorCore(int baseProtection, int slot)
{
super(baseProtection);
@@ -126,4 +129,31 @@ public class ArmorCore extends ToolCore implements ISpecialArmor
TinkersDefense.mods.AMod.UpdateAll((ToolCore) itemStack.getItem(), itemStack, world, player, itemStack.getTagCompound().getCompoundTag("InfiTool"));
}
+ @Override
+ public int getRunicCharge(ItemStack itemstack)
+ {
+ return 0;
+ }
+
+ @Override
+ public void onUpdate(ItemStack stack, World world, Entity ent, int p_77663_4_, boolean p_77663_5_)
+ {
+ //Check if runic shielding level has changed
+
+ NBTTagCompound tcTag = stack.getTagCompound();
+ NBTTagCompound ticoTag = stack.getTagCompound().getCompoundTag("InfiTool");
+
+ byte rs = tcTag.getByte("RS.HARDEN");
+ if(!Charge && rs > 0)
+ {
+ if(ticoTag.getInteger("Modifiers") > 0)
+ {
+ ticoTag.setInteger("Modifiers", ticoTag.getInteger("Modifiers") - 1);
+ Charge = true;
+ }
+ else
+ tcTag.setByte("RS.HARDEN", (byte) 0);
+ }
+ }
+
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersHood.java b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersHood.java
index 361bf54..f723793 100644
--- a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersHood.java
+++ b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersHood.java
@@ -1,11 +1,8 @@
package lance5057.tDefense.armor.items.cloth;
-import cpw.mods.fml.relauncher.Side;
-import cpw.mods.fml.relauncher.SideOnly;
import lance5057.tDefense.TinkersDefense;
import lance5057.tDefense.armor.ArmorCore;
import lance5057.tDefense.armor.parts.ClothMaterial;
-import lance5057.tDefense.armor.renderers.cloth.ModelTinkersHood;
import lance5057.tDefense.proxy.ClientProxy;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
@@ -14,12 +11,16 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.DamageSource;
-import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.tools.CustomMaterial;
+import thaumcraft.api.IGoggles;
+import thaumcraft.api.IVisDiscountGear;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.nodes.IRevealer;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
-public class TinkersHood extends ArmorCore
+public class TinkersHood extends ArmorCore implements IRevealer, IGoggles, IVisDiscountGear
{
public TinkersHood()
{
@@ -152,4 +153,22 @@ public class TinkersHood extends ArmorCore
{
return 0;
}
+
+ @Override
+ public boolean showIngamePopups(ItemStack itemstack, EntityLivingBase player)
+ {
+ return itemstack.getTagCompound().getCompoundTag("InfiTool").getBoolean("Revealing");
+ }
+
+ @Override
+ public boolean showNodes(ItemStack itemstack, EntityLivingBase player)
+ {
+ return itemstack.getTagCompound().getCompoundTag("InfiTool").getBoolean("Revealing");
+ }
+
+ @Override
+ public int getVisDiscount(ItemStack stack, EntityPlayer player, Aspect aspect)
+ {
+ return stack.getTagCompound().getCompoundTag("InfiTool").getInteger("Vis Embroidery");
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersRobe.java b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersRobe.java
index 394267c..beaae18 100644
--- a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersRobe.java
+++ b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersRobe.java
@@ -4,6 +4,8 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.tools.CustomMaterial;
+import thaumcraft.api.IVisDiscountGear;
+import thaumcraft.api.aspects.Aspect;
import lance5057.tDefense.TinkersDefense;
import lance5057.tDefense.armor.ArmorCore;
import lance5057.tDefense.armor.parts.ClothMaterial;
@@ -17,7 +19,7 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
-public class TinkersRobe extends ArmorCore
+public class TinkersRobe extends ArmorCore implements IVisDiscountGear
{
public TinkersRobe()
{
@@ -142,4 +144,10 @@ public class TinkersRobe extends ArmorCore
{
return 0;
}
+
+ @Override
+ public int getVisDiscount(ItemStack stack, EntityPlayer player, Aspect aspect)
+ {
+ return stack.getTagCompound().getCompoundTag("InfiTool").getInteger("Vis Embroidery");
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShawl.java b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShawl.java
index 9afc5f1..64eebae 100644
--- a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShawl.java
+++ b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShawl.java
@@ -18,8 +18,10 @@ import net.minecraft.nbt.NBTTagCompound;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.tools.CustomMaterial;
import tconstruct.tools.TinkerTools;
+import thaumcraft.api.IVisDiscountGear;
+import thaumcraft.api.aspects.Aspect;
-public class TinkersShawl extends ArmorCore
+public class TinkersShawl extends ArmorCore implements IVisDiscountGear
{
public TinkersShawl()
{
@@ -152,4 +154,11 @@ public class TinkersShawl extends ArmorCore
{
return 0;
}
+
+ @Override
+ public int getVisDiscount(ItemStack stack, EntityPlayer player, Aspect aspect)
+ {
+ int test = stack.getTagCompound().getCompoundTag("InfiTool").getInteger("VisEmbroidery");
+ return test;
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShoes.java b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShoes.java
index 1b481be..2289c4e 100644
--- a/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShoes.java
+++ b/src/main/java/lance5057/tDefense/armor/items/cloth/TinkersShoes.java
@@ -16,8 +16,10 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.tools.CustomMaterial;
+import thaumcraft.api.IVisDiscountGear;
+import thaumcraft.api.aspects.Aspect;
-public class TinkersShoes extends ArmorCore
+public class TinkersShoes extends ArmorCore implements IVisDiscountGear
{
public TinkersShoes()
{
@@ -146,4 +148,10 @@ public class TinkersShoes extends ArmorCore
{
return 0;
}
+
+ @Override
+ public int getVisDiscount(ItemStack stack, EntityPlayer player, Aspect aspect)
+ {
+ return stack.getTagCompound().getCompoundTag("InfiTool").getInteger("Vis Embroidery");
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/heavy/TinkersHelm.java b/src/main/java/lance5057/tDefense/armor/items/heavy/TinkersHelm.java
index 23287b9..e06009a 100644
--- a/src/main/java/lance5057/tDefense/armor/items/heavy/TinkersHelm.java
+++ b/src/main/java/lance5057/tDefense/armor/items/heavy/TinkersHelm.java
@@ -2,22 +2,19 @@ package lance5057.tDefense.armor.items.heavy;
import lance5057.tDefense.TinkersDefense;
import lance5057.tDefense.armor.ArmorCore;
-import lance5057.tDefense.armor.renderers.heavy.ModelTinkersHelm;
import lance5057.tDefense.proxy.ClientProxy;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
-import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.DamageSource;
-import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
import tconstruct.tools.TinkerTools;
+import thaumcraft.api.IGoggles;
+import thaumcraft.api.nodes.IRevealer;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
-public class TinkersHelm extends ArmorCore
+public class TinkersHelm extends ArmorCore implements IRevealer, IGoggles
{
public TinkersHelm()
{
@@ -137,4 +134,16 @@ public class TinkersHelm extends ArmorCore
ClientProxy.helm.SetColors(color, this.getDefaultFolder(), textures);
return ClientProxy.helm;
}
+
+ @Override
+ public boolean showIngamePopups(ItemStack itemstack, EntityLivingBase player)
+ {
+ return itemstack.getTagCompound().getCompoundTag("InfiTool").getBoolean("Revealing");
+ }
+
+ @Override
+ public boolean showNodes(ItemStack itemstack, EntityLivingBase player)
+ {
+ return itemstack.getTagCompound().getCompoundTag("InfiTool").getBoolean("Revealing");
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/light/TinkersCoif.java b/src/main/java/lance5057/tDefense/armor/items/light/TinkersCoif.java
index 4e1b538..d83c9d3 100644
--- a/src/main/java/lance5057/tDefense/armor/items/light/TinkersCoif.java
+++ b/src/main/java/lance5057/tDefense/armor/items/light/TinkersCoif.java
@@ -1,12 +1,8 @@
package lance5057.tDefense.armor.items.light;
-import cpw.mods.fml.relauncher.Side;
-import cpw.mods.fml.relauncher.SideOnly;
import lance5057.tDefense.TinkersDefense;
import lance5057.tDefense.armor.ArmorCore;
import lance5057.tDefense.armor.parts.ClothMaterial;
-import lance5057.tDefense.armor.renderers.cloth.ModelTinkersHood;
-import lance5057.tDefense.armor.renderers.light.ModelTinkersCoif;
import lance5057.tDefense.proxy.ClientProxy;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
@@ -14,14 +10,16 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
-import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
import tconstruct.library.TConstructRegistry;
import tconstruct.library.tools.CustomMaterial;
import tconstruct.tools.TinkerTools;
+import thaumcraft.api.IGoggles;
+import thaumcraft.api.nodes.IRevealer;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
-public class TinkersCoif extends ArmorCore
+public class TinkersCoif extends ArmorCore implements IRevealer, IGoggles
{
public TinkersCoif()
{
@@ -160,4 +158,16 @@ public class TinkersCoif extends ArmorCore
//((EntityPlayer)player).addChatComponentMessage(new ChatComponentText(Double.toString(damage)));
return armorp;
}
+
+ @Override
+ public boolean showIngamePopups(ItemStack itemstack, EntityLivingBase player)
+ {
+ return itemstack.getTagCompound().getCompoundTag("InfiTool").getBoolean("Revealing");
+ }
+
+ @Override
+ public boolean showNodes(ItemStack itemstack, EntityLivingBase player)
+ {
+ return itemstack.getTagCompound().getCompoundTag("InfiTool").getBoolean("Revealing");
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/items/light/TinkersHalberd.java b/src/main/java/lance5057/tDefense/armor/items/light/TinkersHauberk.java
index 3c7ca44..061f7fe 100644
--- a/src/main/java/lance5057/tDefense/armor/items/light/TinkersHalberd.java
+++ b/src/main/java/lance5057/tDefense/armor/items/light/TinkersHauberk.java
@@ -1,12 +1,7 @@
package lance5057.tDefense.armor.items.light;
-import cpw.mods.fml.relauncher.Side;
-import cpw.mods.fml.relauncher.SideOnly;
import lance5057.tDefense.TinkersDefense;
import lance5057.tDefense.armor.ArmorCore;
-import lance5057.tDefense.armor.parts.ClothMaterial;
-import lance5057.tDefense.armor.renderers.cloth.ModelTinkersHood;
-import lance5057.tDefense.armor.renderers.light.ModelTinkersHalberd;
import lance5057.tDefense.proxy.ClientProxy;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
@@ -14,19 +9,15 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.DamageSource;
-import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
-import tconstruct.library.TConstructRegistry;
-import tconstruct.library.tools.CustomMaterial;
-import tconstruct.tools.TinkerTools;
-
-public class TinkersHalberd extends ArmorCore
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+
+public class TinkersHauberk extends ArmorCore
{
- public TinkersHalberd()
+ public TinkersHauberk()
{
super(1, 1);
- this.setUnlocalizedName("tinkershalberd");
+ this.setUnlocalizedName("tinkershauberk");
this.maxReduction = 100;
this.reductionPercent = 0.24f;
}
@@ -85,13 +76,13 @@ public class TinkersHalberd extends ArmorCore
switch(partType)
{
case 0:
- return "_halberd_chain";
+ return "_hauberk_chain";
case 1:
- return "_halberd_chain_broken";
+ return "_hauberk_chain_broken";
case 2:
- return "_halberd_plate";
+ return "_hauberk_plate";
case 3:
- return "_halberd_rivet";
+ return "_hauberk_rivet";
default:
return "";
}
@@ -100,13 +91,13 @@ public class TinkersHalberd extends ArmorCore
@Override
public String getEffectSuffix()
{
- return "_halberd_effect";
+ return "_hauberk_effect";
}
@Override
public String getDefaultFolder()
{
- return "armor/halberd";
+ return "armor/hauberk";
}
// @Override
@@ -119,13 +110,13 @@ public class TinkersHalberd extends ArmorCore
@Override
public String getArmorTexture(ItemStack stack, Entity entity, int slot, String type)
{
- return "tinkersdefense:textures/armor/TinkersHalberd.png";
+ return "tinkersdefense:textures/armor/TinkersHauberk.png";
}
@Override
public String[] getTraits()
{
- return new String[] {"armor", "chest", "halberd", "lightarmor"};
+ return new String[] {"armor", "chest", "hauberk", "lightarmor"};
}
@Override
@@ -138,8 +129,8 @@ public class TinkersHalberd extends ArmorCore
color[j] = Integer.toHexString(itemStack.getItem().getColorFromItemStack(itemStack, j));
String[] textures = {this.getIconSuffix(2), this.getIconSuffix(0), this.getIconSuffix(3)};
- ClientProxy.halberd.SetColors(color, this.getDefaultFolder(), textures);
- return ClientProxy.halberd;
+ ClientProxy.hauberk.SetColors(color, this.getDefaultFolder(), textures);
+ return ClientProxy.hauberk;
}
@Override
diff --git a/src/main/java/lance5057/tDefense/armor/modifiers/ArmorMods.java b/src/main/java/lance5057/tDefense/armor/modifiers/ArmorMods.java
index 9bc1766..183d746 100644
--- a/src/main/java/lance5057/tDefense/armor/modifiers/ArmorMods.java
+++ b/src/main/java/lance5057/tDefense/armor/modifiers/ArmorMods.java
@@ -2,6 +2,7 @@ package lance5057.tDefense.armor.modifiers;
import lance5057.tDefense.Reference;
import lance5057.tDefense.TinkersDefense;
+import lance5057.tDefense.armor.modifiers.Thaumcraft.ThaumArmorMods;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
@@ -22,11 +23,13 @@ import cpw.mods.fml.common.registry.GameRegistry;
public class ArmorMods
{
+ ThaumArmorMods tcmods;
+
+ public ArmorMods()
+ {
+ tcmods = new ThaumArmorMods();
+ }
- // public ArmorMods()
- // {
- //
- // }
Item item_Canister;
Item item_Emptycanister;
Item item_Rebreather;
@@ -52,46 +55,50 @@ public class ArmorMods
GameRegistry.registerItem(item_Canister, "FilledCart");
GameRegistry.registerItem(item_Emptycanister, "EmptyCart");
GameRegistry.registerItem(item_Rebreather, "Rebreather");
-
+
GameRegistry.registerItem(item_Feathersole, "FeatherSole");
GameRegistry.registerItem(item_Firesole, "FireSole");
GameRegistry.registerItem(item_Icesole, "IceSole");
GameRegistry.registerItem(item_Glowsole, "GlowSole");
GameRegistry.registerItem(item_Flippers, "Flippers");
+
+ tcmods.LoadItems();
+
}
public void RegisterRecipes()
{
GameRegistry.addShapedRecipe(new ItemStack(item_Canister), new Object[] {"-c-", "ses", "-s-", 'c', new ItemStack(Items.coal, 1, 1), 's', new ItemStack(Blocks.sapling, 1), 'e', new ItemStack(item_Emptycanister, 1, 0)});
GameRegistry.addShapedRecipe(new ItemStack(item_Emptycanister), new Object[] {"gsg", "lil", "gig", 'g', new ItemStack(Items.gold_nugget, 1, 0), 's', new ItemStack(Items.slime_ball, 1, 0), 'l', new ItemStack(Items.dye, 1, 4), 'i', new ItemStack(Items.iron_ingot, 1, 0)});
- GameRegistry.addShapedRecipe(new ItemStack(item_Rebreather), new Object[] {"-s-", "eie", "-d-", 's', new ItemStack(Items.slime_ball, 1, 0), 'e', new ItemStack(item_Emptycanister, 1, 0), 'i', new ItemStack(TinkersDefense.partArmorplate,1,2), 'd', new ItemStack(Items.dye, 1, 0)});
+ GameRegistry.addShapedRecipe(new ItemStack(item_Rebreather), new Object[] {"-s-", "eie", "-d-", 's', new ItemStack(Items.slime_ball, 1, 0), 'e', new ItemStack(item_Emptycanister, 1, 0), 'i', new ItemStack(TinkersDefense.partArmorplate, 1, 2), 'd', new ItemStack(Items.dye, 1, 0)});
GameRegistry.addShapedRecipe(new ItemStack(item_Glowsole), new Object[] {"ggg", "ala", "ggg", 'g', new ItemStack(Blocks.glowstone, 1, 0), 'a', new ItemStack(Items.glowstone_dust, 1, 0), 'l', TConstructRegistry.getItemStack("lavaCrystal")});
GameRegistry.addShapedRecipe(new ItemStack(item_Glowsole), new Object[] {"gag", "glg", "gag", 'g', new ItemStack(Blocks.glowstone, 1, 0), 'a', new ItemStack(Items.glowstone_dust, 1, 0), 'l', TConstructRegistry.getItemStack("lavaCrystal")});
GameRegistry.addShapedRecipe(new ItemStack(item_Feathersole), new Object[] {"fgf", 'g', new ItemStack(Items.gold_nugget, 1, 0), 'f', new ItemStack(Items.feather, 1, 0)});
GameRegistry.addShapedRecipe(new ItemStack(item_Firesole), new Object[] {"lol", "oao", "lol", 'o', new ItemStack(Blocks.obsidian, 1, 0), 'a', TConstructRegistry.getItemStack("ingotArdite"), 'l', TConstructRegistry.getItemStack("lavaCrystal")});
GameRegistry.addShapedRecipe(new ItemStack(item_Icesole), new Object[] {"ili", "lcl", "ili", 'l', new ItemStack(Blocks.lapis_block, 1, 0), 'i', new ItemStack(Blocks.ice, 1, 0), 'c', TConstructRegistry.getItemStack("ingotCobalt")});
- GameRegistry.addShapedRecipe(new ItemStack(item_Flippers), new Object[] {"-b-", "rlr", "-s-", 'b', new ItemStack(Items.leather_boots, 1, 0), 'l', new ItemStack(Items.leather, 1, 0), 'r', new ItemStack(TinkerTools.toolRod,1,2), 's', new ItemStack(Items.slime_ball, 1, 0)});
+ GameRegistry.addShapedRecipe(new ItemStack(item_Flippers), new Object[] {"-b-", "rlr", "-s-", 'b', new ItemStack(Items.leather_boots, 1, 0), 'l', new ItemStack(Items.leather, 1, 0), 'r', new ItemStack(TinkerTools.toolRod, 1, 2), 's', new ItemStack(Items.slime_ball, 1, 0)});
+ tcmods.RegisterRecipes();
}
public void RegisterModifiers()
{
//Head only
- ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Rebreather, 1, 0)}, TinkersDefense.config.ArmorRebreatherID, "Rebreather", "\u00A76", "Rebreather", new String[] {"head"}));
-
+ ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Rebreather, 1, 0)}, TinkersDefense.config.ArmorRebreatherID, "Rebreather", "\u00A76", "Rebreather", new String[] {"head"}, 1));
+
//Excluding Cloth
ModifyBuilder.registerModifier(new modifierProtection(new ItemStack[] {new ItemStack(TinkersDefense.partArmorplate, 1, 2)}, TinkersDefense.config.ArmorProtectionID, 1, "\u00A77", "Protection"));
ModifyBuilder.registerModifier(new modifierProtection(new ItemStack[] {new ItemStack(Items.magma_cream, 1)}, TinkersDefense.config.ArmorFireProtectionID, 1, "\u00A7c", "Fire Protection"));
ModifyBuilder.registerModifier(new modifierProtection(new ItemStack[] {new ItemStack(Blocks.wool, 1)}, TinkersDefense.config.ArmorBlastProtectionID, 1, "\u00A72", "Blast Protection"));
ModifyBuilder.registerModifier(new modifierProtection(new ItemStack[] {new ItemStack(TinkersDefense.partRivet, 1, 2)}, TinkersDefense.config.ArmorProjectileProtectionID, 1, "\u00A7f", "Projectile Protection"));
ModifyBuilder.registerModifier(new modifierProtection(new ItemStack[] {new ItemStack(item_Feathersole, 1, 0)}, TinkersDefense.config.ArmorFeatherfallID, 1, "\u00A7f", "Featherfall"));
-
+
//Feet only
- ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Glowsole, 1, 0)}, TinkersDefense.config.ArmorGlowstepID, "GlowStep", "\u00A76", "GlowStep", new String[] {"feet"}));
- ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Firesole, 1, 0)}, TinkersDefense.config.ArmorFirewalkerID, "Firewalker", "\u00A74", "Firewalker", new String[] {"feet"}));
- ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Icesole, 1, 0)}, TinkersDefense.config.ArmorFrostwalkerID, "Frostwalker", "\u00A7b", "Frostwalker", new String[] {"feet"}));
- ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Flippers, 1, 0)}, TinkersDefense.config.ArmorDepthstriderID, "Depthstrider", "\u00A71", "Depthstrider", new String[] {"feet"}));
+ ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Glowsole, 1, 0)}, TinkersDefense.config.ArmorGlowstepID, "GlowStep", "\u00A76", "GlowStep", new String[] {"feet"}, 1));
+ ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Firesole, 1, 0)}, TinkersDefense.config.ArmorFirewalkerID, "Firewalker", "\u00A74", "Firewalker", new String[] {"feet"}, 1));
+ ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Icesole, 1, 0)}, TinkersDefense.config.ArmorFrostwalkerID, "Frostwalker", "\u00A7b", "Frostwalker", new String[] {"feet"}, 1));
+ ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {new ItemStack(item_Flippers, 1, 0)}, TinkersDefense.config.ArmorDepthstriderID, "Depthstrider", "\u00A71", "Depthstrider", new String[] {"feet"}, 1));
for(ToolCore tool : TConstructRegistry.getToolMapping())
{
@@ -102,13 +109,15 @@ public class ArmorMods
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorBlastProtectionID, "tinker", "blastprotection", true);
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorProjectileProtectionID, "tinker", "projprotection", true);
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorFeatherfallID, "tinker", "featherfall", true);
-
+
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorGlowstepID, "tinker", "glowstep", true);
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorFirewalkerID, "tinker", "firewalk", true);
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorFrostwalkerID, "tinker", "frostwalk", true);
TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.ArmorDepthstriderID, "tinker", "depthstrider", true);
}
+
+ tcmods.RegisterModifiers();
}
public void UpdateAll(ToolCore tool, ItemStack stack, World world, Entity entity, NBTTagCompound tags)
@@ -129,6 +138,8 @@ public class ArmorMods
if(tags.hasKey("Depthstrider"))
UpdateFlippers(tool, stack, world, entity);
}
+
+ tcmods.UpdateAll(tool, stack, world, entity, tags);
}
public void UpdateWalker(ToolCore tool, ItemStack stack, World world, Entity entity, Material mat, Block replacement, int meta)
@@ -181,7 +192,7 @@ public class ArmorMods
prevX = x;
prevZ = z;
}
-
+
public void UpdateFlippers(ToolCore tool, ItemStack stack, World world, Entity entity)
{
if(entity.isInWater())
@@ -191,7 +202,7 @@ public class ArmorMods
entity.motionZ *= 1.2;
}
}
-
+
public void UpdateRebreather(ToolCore tool, ItemStack stack, World world, Entity entity)
{
EntityPlayer player = (EntityPlayer) entity;
diff --git a/src/main/java/lance5057/tDefense/armor/modifiers/Thaumcraft/ThaumArmorMods.java b/src/main/java/lance5057/tDefense/armor/modifiers/Thaumcraft/ThaumArmorMods.java
new file mode 100644
index 0000000..ec0a444
--- /dev/null
+++ b/src/main/java/lance5057/tDefense/armor/modifiers/Thaumcraft/ThaumArmorMods.java
@@ -0,0 +1,55 @@
+package lance5057.tDefense.armor.modifiers.Thaumcraft;
+
+import lance5057.tDefense.Reference;
+import lance5057.tDefense.TinkersDefense;
+import lance5057.tDefense.armor.modifiers.modifierBoolExclusive;
+import lance5057.tDefense.armor.modifiers.modifierIntExclusive;
+import lance5057.tDefense.armor.modifiers.modifierProtection;
+import net.minecraft.block.material.Material;
+import net.minecraft.entity.Entity;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import tconstruct.library.TConstructRegistry;
+import tconstruct.library.client.TConstructClientRegistry;
+import tconstruct.library.crafting.ModifyBuilder;
+import tconstruct.library.tools.ToolCore;
+import tconstruct.modifiers.tools.ModInteger;
+import tconstruct.tools.TinkerTools;
+import thaumcraft.api.ItemApi;
+import cpw.mods.fml.common.registry.GameRegistry;
+
+public class ThaumArmorMods
+{
+
+ //Runic Shielding is handled in ArmorCore.java
+
+ public void LoadItems()
+ {
+ }
+
+ public void RegisterRecipes()
+ {
+ }
+
+ public void RegisterModifiers()
+ {
+ ModifyBuilder.registerModifier(new modifierBoolExclusive(new ItemStack[] {ItemApi.getItem("itemGoggles", 0)}, TinkersDefense.config.RevealingModID, "Revealing", "\u00A75", "Revealing", new String[] {"head"}, 0));
+
+ ModifyBuilder.registerModifier(new modifierIntExclusive(new ItemStack[] {ItemApi.getItem("itemResource", 7)}, TinkersDefense.config.VisDiscountModID, "VisEmbroidery", 1, "\u00A79", "Vis Embroidery", new String[] {"cloth"}, 1));
+
+ for(ToolCore tool : TConstructRegistry.getToolMapping())
+ {
+ TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.RevealingModID, "tinker", "revealing", true);
+ TConstructClientRegistry.addEffectRenderMapping(tool, TinkersDefense.config.VisDiscountModID, "tinker", "vis", true);
+
+ }
+ }
+
+ public void UpdateAll(ToolCore tool, ItemStack stack, World world, Entity entity, NBTTagCompound tags)
+ {
+ }
+}
diff --git a/src/main/java/lance5057/tDefense/armor/modifiers/modifierBoolExclusive.java b/src/main/java/lance5057/tDefense/armor/modifiers/modifierBoolExclusive.java
index f573ada..aa55571 100644
--- a/src/main/java/lance5057/tDefense/armor/modifiers/modifierBoolExclusive.java
+++ b/src/main/java/lance5057/tDefense/armor/modifiers/modifierBoolExclusive.java
@@ -11,10 +11,17 @@ import tconstruct.modifiers.tools.ModBoolean;
public class modifierBoolExclusive extends ModBoolean
{
String[] exclusive;
- public modifierBoolExclusive(ItemStack[] items, int effect, String tag, String c, String tip, String[] exclusive)
+ int modsNeeded = 0;
+ String color;
+ String tooltipName;
+
+ public modifierBoolExclusive(ItemStack[] items, int effect, String tag, String c, String tip, String[] exclusive, int modsNeeded)
{
super(items, effect, tag, c, tip);
this.exclusive = exclusive;
+ this.modsNeeded = modsNeeded;
+ this.color = c;
+ this.tooltipName = tip;
}
@Override
@@ -33,4 +40,18 @@ public class modifierBoolExclusive extends ModBoolean
return false;
}
+
+ @Override
+ public void modify (ItemStack[] input, ItemStack tool)
+ {
+ NBTTagCompound tags = tool.getTagCompound().getCompoundTag("InfiTool");
+
+ tags.setBoolean(key, true);
+
+ int modifiers = tags.getInteger("Modifiers");
+ modifiers -= modsNeeded;
+ tags.setInteger("Modifiers", modifiers);
+
+ addToolTip(tool, color + tooltipName, color + key);
+ }
}
diff --git a/src/main/java/lance5057/tDefense/armor/modifiers/modifierIntExclusive.java b/src/main/java/lance5057/tDefense/armor/modifiers/modifierIntExclusive.java
new file mode 100644
index 0000000..77116ee
--- /dev/null
+++ b/src/main/java/lance5057/tDefense/armor/modifiers/modifierIntExclusive.java
@@ -0,0 +1,80 @@
+package lance5057.tDefense.armor.modifiers;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import tconstruct.library.tools.ToolCore;
+import tconstruct.modifiers.tools.ModInteger;
+
+public class modifierIntExclusive extends ModInteger
+{
+ String[] exclusive;
+ int modsNeeded = 0;
+ String color;
+ String tooltipName;
+ int initialIncrease;
+ int secondaryIncrease;
+ int max = 5;
+
+ public modifierIntExclusive(ItemStack[] items, int effect, String dataKey, int increase, String c, String tip, String[] exclusive, int modsNeeded)
+ {
+ super(items, effect, dataKey, increase, c, tip);
+ this.exclusive = exclusive;
+ this.modsNeeded = modsNeeded;
+ initialIncrease = secondaryIncrease = increase;
+ color = c;
+ tooltipName = tip;
+ }
+
+ public modifierIntExclusive(ItemStack[] items, int effect, String dataKey, int increase, String c, String tip, String[] exclusive, int modsNeeded, int max)
+ {
+ super(items, effect, dataKey, increase, c, tip);
+ this.exclusive = exclusive;
+ this.modsNeeded = modsNeeded;
+ initialIncrease = secondaryIncrease = increase;
+ color = c;
+ tooltipName = tip;
+ this.max = max;
+ }
+
+ @Override
+ protected boolean canModify(ItemStack tool, ItemStack[] input)
+ {
+ List list = Arrays.asList(((ToolCore) tool.getItem()).getTraits());
+ NBTTagCompound tags = tool.getTagCompound().getCompoundTag("InfiTool");
+
+ for(int i = 0; i < exclusive.length; i++)
+ {
+ if(list.contains(exclusive[i]))
+ {
+ return tags.getInteger(tooltipName) < max;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void modify(ItemStack[] input, ItemStack tool)
+ {
+ NBTTagCompound tags = tool.getTagCompound().getCompoundTag("InfiTool");
+ if(tags.hasKey(key))
+ {
+ int increase = tags.getInteger(key);
+ increase += secondaryIncrease;
+ tags.setInteger(key, increase);
+ }
+ else
+ {
+ tags.setInteger(key, initialIncrease);
+ }
+
+ int modifiers = tags.getInteger("Modifiers");
+ modifiers -= modsNeeded;
+ tags.setInteger("Modifiers", modifiers);
+
+ addToolTip(tool, color + tooltipName, color + key);
+ }
+}
diff --git a/src/main/java/lance5057/tDefense/armor/renderers/light/ModelTinkersHalberd.java b/src/main/java/lance5057/tDefense/armor/renderers/light/ModelTinkersHauberk.java
index 0eff717..455ac3b 100644
--- a/src/main/java/lance5057/tDefense/armor/renderers/light/ModelTinkersHalberd.java
+++ b/src/main/java/lance5057/tDefense/armor/renderers/light/ModelTinkersHauberk.java
@@ -14,7 +14,7 @@ import cpw.mods.fml.client.FMLClientHandler;
* ModelBiped - Either Mojang or a mod author
* Created using Tabula 4.1.1
*/
-public class ModelTinkersHalberd extends ArmorRenderer
+public class ModelTinkersHauberk extends ArmorRenderer
{
public ModelRenderer Pauldron1;
public ModelRenderer Pauldron2;
@@ -26,7 +26,7 @@ public class ModelTinkersHalberd extends ArmorRenderer
public ModelRenderer Pauldron3_1;
public ModelRenderer ArmL;
- public ModelTinkersHalberd()
+ public ModelTinkersHauberk()
{
super(1.1f, 0, 64, 64);
diff --git a/src/main/java/lance5057/tDefense/finishingAnvil/utilities/ToolCoreTip.java b/src/main/java/lance5057/tDefense/finishingAnvil/utilities/ToolCoreTip.java
index 1948779..7da31f0 100644
--- a/src/main/java/lance5057/tDefense/finishingAnvil/utilities/ToolCoreTip.java
+++ b/src/main/java/lance5057/tDefense/finishingAnvil/utilities/ToolCoreTip.java
@@ -4,42 +4,56 @@ import java.util.ArrayList;
import java.util.List;
public class ToolCoreTip
-{
- String head;
- String handle;
- String accessory;
- String extra;
-
+{
+ String head = "";
+ String handle = "";
+ String accessory = "";
+ String extra = "";
+
List<String> headTT = new ArrayList<String>();
List<String> accessoryTT = new ArrayList<String>();
List<String> handleTT = new ArrayList<String>();
List<String> extraTT = new ArrayList<String>();
-
+
public ToolCoreTip()
{
}
-
+
public String getPart(int id /*1-4*/)
{
switch(id)
{
- case 1: return head;
- case 2: return handle;
- case 3: return accessory;
- case 4: return extra;
- default: return "";
+ case 1:
+ return head;
+ case 2:
+ return handle;
+ case 3:
+ return accessory;
+ case 4:
+ return extra;
+ default:
+ return "";
}
}
-
+
public String getPartName(int partId /*1-4*/, int id)
{
switch(partId)
{
- case 1: return headTT.get(id);
- case 2: return handleTT.get(id);
- case 3: return accessoryTT.get(id);
- case 4: return extraTT.get(id);
- default: return "";
+ case 1:
+ if(headTT.size() > 0 && headTT.size() >= id - 1 && headTT.get(id) != null)
+ return headTT.get(id);
+ case 2:
+ if(handleTT.size() > 0 && handleTT.size() >= id - 1 && handleTT.get(id) != null)
+ return handleTT.get(id);
+ case 3:
+ if(accessoryTT.size() > 0 && accessoryTT.size() >= id - 1 && accessoryTT.get(id) != null)
+ return accessoryTT.get(id);
+ case 4:
+ if(extraTT.size() > 0 && extraTT.size() >= id - 1 && extraTT.get(id) != null)
+ return extraTT.get(id);
+ default:
+ return "";
}
}
}
diff --git a/src/main/java/lance5057/tDefense/proxy/ClientProxy.java b/src/main/java/lance5057/tDefense/proxy/ClientProxy.java
index 9358e69..dbd2492 100644
--- a/src/main/java/lance5057/tDefense/proxy/ClientProxy.java
+++ b/src/main/java/lance5057/tDefense/proxy/ClientProxy.java
@@ -14,7 +14,7 @@ import lance5057.tDefense.armor.renderers.heavy.ModelTinkersSabatons;
import lance5057.tDefense.armor.renderers.light.ModelTinkersBoots;
import lance5057.tDefense.armor.renderers.light.ModelTinkersChausses;
import lance5057.tDefense.armor.renderers.light.ModelTinkersCoif;
-import lance5057.tDefense.armor.renderers.light.ModelTinkersHalberd;
+import lance5057.tDefense.armor.renderers.light.ModelTinkersHauberk;
import lance5057.tDefense.core.blocks.crestMount.Renderer_CrestMount;
import lance5057.tDefense.core.blocks.crestMount.TileEntity_CrestMount;
import lance5057.tDefense.core.renderer.BigFlexibleToolRenderer;
@@ -45,7 +45,7 @@ public class ClientProxy extends CommonProxy
public static ModelTinkersBoots shoes = new ModelTinkersBoots();
public static ModelTinkersCoif coif = new ModelTinkersCoif();
- public static ModelTinkersHalberd halberd = new ModelTinkersHalberd();
+ public static ModelTinkersHauberk hauberk = new ModelTinkersHauberk();
public static ModelTinkersChausses chausses = new ModelTinkersChausses();
public static ModelTinkersBoots boots = new ModelTinkersBoots();
diff --git a/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_chain.png b/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_chain.png
index ee7114a..2315c6f 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_chain.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_cloth.png b/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_cloth.png
index c6e4b69..40cc82a 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_cloth.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_cloth.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_rivet.png b/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_rivet.png
index a088dcb..1883d37 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_rivet.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/boots/_boots_rivet.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_chain.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_chain.png
index 9f291cd..5b242c1 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_chain.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_plate.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_plate.png
index 9b6ca9f..624403e 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_plate.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_plate.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_smallplate.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_smallplate.png
index 4564e58..9d8aa6b 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_smallplate.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_smallplate.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_trim.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_trim.png
index 2c3b447..5eea928 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_trim.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/_breastplate_trim.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/blastprotection_breastplate_effect.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/blastprotection_breastplate_effect.png
index a2a60da..062bf61 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/blastprotection_breastplate_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/blastprotection_breastplate_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/fireprotection_breastplate_effect.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/fireprotection_breastplate_effect.png
index c959767..f45cb6f 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/fireprotection_breastplate_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/fireprotection_breastplate_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/projprotection_breastplate_effect.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/projprotection_breastplate_effect.png
index 8f1957d..4fb0442 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/projprotection_breastplate_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/projprotection_breastplate_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/breastplate/protection_breastplate_effect.png b/src/main/resources/assets/tinker/textures/items/armor/breastplate/protection_breastplate_effect.png
index 53ccbd9..9667d71 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/breastplate/protection_breastplate_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/breastplate/protection_breastplate_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_chain.png b/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_chain.png
index 9afc12c..f51da74 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_chain.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_plate.png b/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_plate.png
index bb2e6e3..f099cc7 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_plate.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/chausses/_chausses_plate.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_chain.png b/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_chain.png
index d441377..250ea54 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_chain.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_circlet.png b/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_circlet.png
index b676d00..d1aa716 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_circlet.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_circlet.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_cloth.png b/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_cloth.png
index c6dd513..35ee80f 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_cloth.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/coif/_coif_cloth.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/coif/rebreather_coif_effect.png b/src/main/resources/assets/tinker/textures/items/armor/coif/rebreather_coif_effect.png
new file mode 100644
index 0000000..bf253bf
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/coif/rebreather_coif_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/coif/revealing_coif_effect.png b/src/main/resources/assets/tinker/textures/items/armor/coif/revealing_coif_effect.png
new file mode 100644
index 0000000..e502cf4
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/coif/revealing_coif_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_chain.png b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_chain.png
index 956dc16..fc720ed 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_chain.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_cod.png b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_cod.png
index d8659d1..a32b425 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_cod.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_cod.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_plate.png b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_plate.png
index 36bf369..a0f6319 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_plate.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_plate.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_trim.png b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_trim.png
index 24b236f..ac57140 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_trim.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/grieves/_grieves_trim.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_chain.png b/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_chain.png
deleted file mode 100644
index 7e05331..0000000
--- a/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_chain.png
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_plate.png b/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_plate.png
deleted file mode 100644
index 84fc5c7..0000000
--- a/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_plate.png
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_rivet.png b/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_rivet.png
deleted file mode 100644
index ba81fcc..0000000
--- a/src/main/resources/assets/tinker/textures/items/armor/halberd/_halberd_rivet.png
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_chain.png b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_chain.png
new file mode 100644
index 0000000..e0b54f2
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_plate.png b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_plate.png
new file mode 100644
index 0000000..7a94bbc
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_plate.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_rivet.png b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_rivet.png
new file mode 100644
index 0000000..d9cecac
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_halberd_rivet.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_chain.png b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_chain.png
new file mode 100644
index 0000000..e0b54f2
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_plate.png b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_plate.png
new file mode 100644
index 0000000..7a94bbc
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_plate.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_rivet.png b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_rivet.png
new file mode 100644
index 0000000..d9cecac
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hauberk/_hauberk_rivet.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_chain.png b/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_chain.png
index 9e69358..4dc7c7c 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_chain.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_chain.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_top.png b/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_top.png
index 3815d7e..114d587 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_top.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_top.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_visor.png b/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_visor.png
index 7159d57..2d896d1 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_visor.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/helm/_helm_visor.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/helm/revealing_helm_effect.png b/src/main/resources/assets/tinker/textures/items/armor/helm/revealing_helm_effect.png
new file mode 100644
index 0000000..b7eb4e5
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/helm/revealing_helm_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_cloth.png b/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_cloth.png
index 3c07d84..9c2af8b 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_cloth.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_cloth.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_rivet.png b/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_rivet.png
index 4e64ffd..fa36c37 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_rivet.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_rivet.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_trim.png b/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_trim.png
index 418b28e..4bbe71c 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_trim.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/_hood_trim.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_helm_effect.png b/src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_helm_effect.png
new file mode 100644
index 0000000..bf253bf
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_helm_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_hood_effect.png b/src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_hood_effect.png
new file mode 100644
index 0000000..dbea83d
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/rebreather_hood_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/revealing_hood_effect.png b/src/main/resources/assets/tinker/textures/items/armor/hood/revealing_hood_effect.png
new file mode 100644
index 0000000..689c9c9
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/revealing_hood_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/vis_hood_effect.png b/src/main/resources/assets/tinker/textures/items/armor/hood/vis_hood_effect.png
new file mode 100644
index 0000000..f0e40e6
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/vis_hood_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/hood/visembroidery_hood_effect.png b/src/main/resources/assets/tinker/textures/items/armor/hood/visembroidery_hood_effect.png
new file mode 100644
index 0000000..f0e40e6
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/hood/visembroidery_hood_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_cloth.png b/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_cloth.png
index 474fb43..100b1ea 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_cloth.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_cloth.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_trim.png b/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_trim.png
index 3951ec8..37a4677 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_trim.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/robe/_robe_trim.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/robe/vis_robe_effect.png b/src/main/resources/assets/tinker/textures/items/armor/robe/vis_robe_effect.png
new file mode 100644
index 0000000..c7f7c01
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/robe/vis_robe_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/robe/visembroidery_robe_effect.png b/src/main/resources/assets/tinker/textures/items/armor/robe/visembroidery_robe_effect.png
new file mode 100644
index 0000000..c7f7c01
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/robe/visembroidery_robe_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_caps.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_caps.png
index 816650a..8225f2f 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_caps.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_caps.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_plates.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_plates.png
index dae8c9a..a841231 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_plates.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_plates.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_soles.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_soles.png
index aa1a902..4bf2a87 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_soles.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_soles.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_trim.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_trim.png
index b56b653..54ac3e9 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_trim.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/_sabatons_trim.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/blastprotection_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/blastprotection_sabatons_effect.png
index b3b8740..60a2638 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/blastprotection_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/blastprotection_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/depthstrider_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/depthstrider_sabatons_effect.png
index f750ed2..4ce2437 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/depthstrider_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/depthstrider_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/featherfall_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/featherfall_sabatons_effect.png
index 48c9dff..5e9f2f1 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/featherfall_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/featherfall_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/fireprotection_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/fireprotection_sabatons_effect.png
index 1eb9482..db5a7f0 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/fireprotection_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/fireprotection_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/firewalk_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/firewalk_sabatons_effect.png
index 1cb5883..ce914a7 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/firewalk_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/firewalk_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/frostwalk_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/frostwalk_sabatons_effect.png
index acae962..8a85b87 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/frostwalk_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/frostwalk_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/glowstep_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/glowstep_sabatons_effect.png
index f0a3230..b7ab1cb 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/glowstep_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/glowstep_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/projprotection_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/projprotection_sabatons_effect.png
index 6b35e70..a563a2c 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/projprotection_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/projprotection_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/sabatons/protection_sabatons_effect.png b/src/main/resources/assets/tinker/textures/items/armor/sabatons/protection_sabatons_effect.png
index 7920e89..60a4577 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/sabatons/protection_sabatons_effect.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/sabatons/protection_sabatons_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_clasp.png b/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_clasp.png
index 9139857..5e4bc9b 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_clasp.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_clasp.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_cloth.png b/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_cloth.png
index 7d59967..ed81f20 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_cloth.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_cloth.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_trim.png b/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_trim.png
index bfb88f7..004cced 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_trim.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/shawl/_shawl_trim.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shawl/vis_shawl_effect.png b/src/main/resources/assets/tinker/textures/items/armor/shawl/vis_shawl_effect.png
new file mode 100644
index 0000000..1b141c3
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/shawl/vis_shawl_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shawl/visembroidery_shawl_effect.png b/src/main/resources/assets/tinker/textures/items/armor/shawl/visembroidery_shawl_effect.png
new file mode 100644
index 0000000..3dd7490
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/shawl/visembroidery_shawl_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_clasp.png b/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_clasp.png
index 74076b6..360a239 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_clasp.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_clasp.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_cloth.png b/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_cloth.png
index 2a32e22..e34fc7e 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_cloth.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_cloth.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_rivet.png b/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_rivet.png
index b62a69f..d2b5efc 100644
--- a/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_rivet.png
+++ b/src/main/resources/assets/tinker/textures/items/armor/shoes/_shoes_rivet.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shoes/vis_shoes_effect.png b/src/main/resources/assets/tinker/textures/items/armor/shoes/vis_shoes_effect.png
new file mode 100644
index 0000000..902b94c
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/shoes/vis_shoes_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinker/textures/items/armor/shoes/visembroidery_shoes_effect.png b/src/main/resources/assets/tinker/textures/items/armor/shoes/visembroidery_shoes_effect.png
new file mode 100644
index 0000000..902b94c
--- /dev/null
+++ b/src/main/resources/assets/tinker/textures/items/armor/shoes/visembroidery_shoes_effect.png
Binary files differ
diff --git a/src/main/resources/assets/tinkersdefense/lang/en_US.lang b/src/main/resources/assets/tinkersdefense/lang/en_US.lang
index 5c27b74..0a5a2b6 100644
--- a/src/main/resources/assets/tinkersdefense/lang/en_US.lang
+++ b/src/main/resources/assets/tinkersdefense/lang/en_US.lang
@@ -40,10 +40,10 @@ gui.toolstation.heatershield.desc=A simple shield with high durability and high
item.Crest_Feathers.name=Crest of Feathers
-toolpart.Chainmaille=Chainmail
-toolpart.Rivets=Rivets
-toolpart.Clasp=Clasp
-toolpart.Armor Plate=Armor Plate
+toolpart.Chainmaille=%%material Chainmail
+toolpart.Rivets=%%material Rivets
+toolpart.Clasp=%%material Clasp
+toolpart.Armor Plate=%%material Armor Plate
item.TD.Cloth.white.name=White Cloth
item.TD.Cloth.orange.name=Orange Cloth