From 0f6790b505b165df18f86ac8e69b6abde6242824 Mon Sep 17 00:00:00 2001 From: Jeremy Diamond Date: Fri, 17 Oct 2014 23:07:53 -0700 Subject: [PATCH] API Stuff --- src/api/java/am2/api/ArsMagicaApi.java | 278 ++++++++++++ src/api/java/am2/api/IAMRecipeManager.java | 12 + src/api/java/am2/api/IAffinityData.java | 28 ++ src/api/java/am2/api/IExtendedProperties.java | 25 ++ src/api/java/am2/api/ISkillData.java | 66 +++ src/api/java/am2/api/SkillTreeEntry.java | 32 ++ .../am2/api/blocks/IKeystoneLockable.java | 22 + .../blocks/MultiblockStructureDefinition.java | 405 ++++++++++++++++++ .../api/enchantment/IAMEnchantmentHelper.java | 12 + .../java/am2/api/entities/IEntityManager.java | 12 + .../java/am2/api/events/ManaCostEvent.java | 24 ++ .../api/events/ModifierCalculatedEvent.java | 41 ++ .../events/PlayerMagicLevelChangeEvent.java | 19 + .../api/events/ReconstructorRepairEvent.java | 22 + .../api/events/RegisterSkillTreeIcons.java | 12 + .../am2/api/events/SkillLearnedEvent.java | 20 + .../am2/api/events/SpellCastingEvent.java | 93 ++++ .../am2/api/events/SpellRecipeItemsEvent.java | 33 ++ .../am2/api/flickers/IFlickerController.java | 9 + .../api/flickers/IFlickerFunctionality.java | 15 + .../am2/api/flickers/IFlickerRegistry.java | 11 + .../java/am2/api/illeffect/BadThingTypes.java | 6 + .../java/am2/api/illeffect/IIllEffect.java | 38 ++ .../java/am2/api/illeffect/IllEffectBase.java | 41 ++ .../am2/api/illeffect/IllEffectSeverity.java | 14 + .../java/am2/api/items/IKeystoneHelper.java | 30 ++ .../api/items/armor/ArmorTextureEvent.java | 16 + .../am2/api/items/armor/IArmorImbuement.java | 60 +++ .../api/items/armor/IImbuementRegistry.java | 28 ++ .../armor/ImbuementApplicationTypes.java | 10 + .../am2/api/items/armor/ImbuementTiers.java | 8 + src/api/java/am2/api/math/AMLineSegment.java | 42 ++ src/api/java/am2/api/math/AMMatrix4.java | 56 +++ src/api/java/am2/api/math/AMPlane.java | 47 ++ src/api/java/am2/api/math/AMVector2.java | 32 ++ src/api/java/am2/api/math/AMVector3.java | 246 +++++++++++ .../java/am2/api/particles/IBeamParticle.java | 26 ++ .../am2/api/power/IObeliskFuelHelper.java | 16 + src/api/java/am2/api/power/IPowerNode.java | 54 +++ src/api/java/am2/api/power/PowerTypes.java | 69 +++ .../java/am2/api/spell/ISkillTreeManager.java | 19 + .../java/am2/api/spell/ISpellIconManager.java | 20 + .../am2/api/spell/ISpellModifierManager.java | 8 + .../java/am2/api/spell/ISpellPartManager.java | 27 ++ .../am2/api/spell/ISpellShapeManager.java | 8 + src/api/java/am2/api/spell/ItemSpellBase.java | 28 ++ .../interfaces/IRitualInteraction.java | 23 + .../component/interfaces/ISkillTreeEntry.java | 9 + .../component/interfaces/ISpellComponent.java | 72 ++++ .../component/interfaces/ISpellModifier.java | 43 ++ .../component/interfaces/ISpellPart.java | 28 ++ .../component/interfaces/ISpellShape.java | 54 +++ .../java/am2/api/spell/enums/Affinity.java | 193 +++++++++ .../am2/api/spell/enums/BuffPowerLevel.java | 7 + .../am2/api/spell/enums/ContingencyTypes.java | 10 + .../java/am2/api/spell/enums/LearnStates.java | 9 + .../am2/api/spell/enums/SkillPointTypes.java | 8 + .../java/am2/api/spell/enums/SkillTrees.java | 11 + .../am2/api/spell/enums/SpellCastResult.java | 11 + .../am2/api/spell/enums/SpellModifiers.java | 30 ++ src/api/java/thaumcraft/api/IWarpingGear.java | 22 + .../java/thaumcraft/api/ThaumcraftApi.java | 5 +- .../thaumcraft/api/ThaumcraftApiHelper.java | 47 +- .../thaumcraft/api/aspects/AspectList.java | 26 +- .../api/crafting/CrucibleRecipe.java | 30 +- .../crafting/InfusionEnchantmentRecipe.java | 10 +- .../api/crafting/InfusionRecipe.java | 11 +- .../api/crafting/ShapedArcaneRecipe.java | 2 +- .../api/crafting/ShapelessArcaneRecipe.java | 10 +- .../java/vazkii/botania/api/BotaniaAPI.java | 72 +++- .../api/internal/DummyMethodHandler.java | 17 + .../api/internal/IInternalMethodHandler.java | 8 + .../botania/api/item/IExoflameHeatable.java | 44 ++ .../api/item/IExtendedPlayerController.java | 2 +- .../botania/api/item/IPetalApothecary.java | 30 ++ .../botania/api/lexicon/LexiconEntry.java | 7 +- .../botania/api/lexicon/LexiconPage.java | 14 + .../vazkii/botania/api/mana/IManaItem.java | 4 +- .../api/mana/spark/ISparkAttachable.java | 54 +++ .../botania/api/mana/spark/ISparkEntity.java | 65 +++ .../botania/api/mana/spark/SparkHelper.java | 33 ++ .../java/vazkii/botania/api/package-info.java | 2 +- .../api/subtile/ISubTileContainer.java | 30 ++ .../botania/api/subtile/SubTileEntity.java | 15 + .../api/subtile/SubTileFunctional.java | 22 + .../api/subtile/SubTileGenerating.java | 43 +- .../api/subtile/signature/BasicSignature.java | 58 +++ .../subtile/signature/SubTileSignature.java | 47 ++ .../botania/api/wand/IWandBindable.java | 35 ++ .../vazkii/botania/api/wand/IWandable.java | 2 +- .../botania/api/wiki/IWikiProvider.java | 39 ++ .../botania/api/wiki/SimpleWikiProvider.java | 73 ++++ .../vazkii/botania/api/wiki/WikiHooks.java | 43 ++ 93 files changed, 3519 insertions(+), 51 deletions(-) create mode 100644 src/api/java/am2/api/ArsMagicaApi.java create mode 100644 src/api/java/am2/api/IAMRecipeManager.java create mode 100644 src/api/java/am2/api/IAffinityData.java create mode 100644 src/api/java/am2/api/IExtendedProperties.java create mode 100644 src/api/java/am2/api/ISkillData.java create mode 100644 src/api/java/am2/api/SkillTreeEntry.java create mode 100644 src/api/java/am2/api/blocks/IKeystoneLockable.java create mode 100644 src/api/java/am2/api/blocks/MultiblockStructureDefinition.java create mode 100644 src/api/java/am2/api/enchantment/IAMEnchantmentHelper.java create mode 100644 src/api/java/am2/api/entities/IEntityManager.java create mode 100644 src/api/java/am2/api/events/ManaCostEvent.java create mode 100644 src/api/java/am2/api/events/ModifierCalculatedEvent.java create mode 100644 src/api/java/am2/api/events/PlayerMagicLevelChangeEvent.java create mode 100644 src/api/java/am2/api/events/ReconstructorRepairEvent.java create mode 100644 src/api/java/am2/api/events/RegisterSkillTreeIcons.java create mode 100644 src/api/java/am2/api/events/SkillLearnedEvent.java create mode 100644 src/api/java/am2/api/events/SpellCastingEvent.java create mode 100644 src/api/java/am2/api/events/SpellRecipeItemsEvent.java create mode 100644 src/api/java/am2/api/flickers/IFlickerController.java create mode 100644 src/api/java/am2/api/flickers/IFlickerFunctionality.java create mode 100644 src/api/java/am2/api/flickers/IFlickerRegistry.java create mode 100644 src/api/java/am2/api/illeffect/BadThingTypes.java create mode 100644 src/api/java/am2/api/illeffect/IIllEffect.java create mode 100644 src/api/java/am2/api/illeffect/IllEffectBase.java create mode 100644 src/api/java/am2/api/illeffect/IllEffectSeverity.java create mode 100644 src/api/java/am2/api/items/IKeystoneHelper.java create mode 100644 src/api/java/am2/api/items/armor/ArmorTextureEvent.java create mode 100644 src/api/java/am2/api/items/armor/IArmorImbuement.java create mode 100644 src/api/java/am2/api/items/armor/IImbuementRegistry.java create mode 100644 src/api/java/am2/api/items/armor/ImbuementApplicationTypes.java create mode 100644 src/api/java/am2/api/items/armor/ImbuementTiers.java create mode 100644 src/api/java/am2/api/math/AMLineSegment.java create mode 100644 src/api/java/am2/api/math/AMMatrix4.java create mode 100644 src/api/java/am2/api/math/AMPlane.java create mode 100644 src/api/java/am2/api/math/AMVector2.java create mode 100644 src/api/java/am2/api/math/AMVector3.java create mode 100644 src/api/java/am2/api/particles/IBeamParticle.java create mode 100644 src/api/java/am2/api/power/IObeliskFuelHelper.java create mode 100644 src/api/java/am2/api/power/IPowerNode.java create mode 100644 src/api/java/am2/api/power/PowerTypes.java create mode 100644 src/api/java/am2/api/spell/ISkillTreeManager.java create mode 100644 src/api/java/am2/api/spell/ISpellIconManager.java create mode 100644 src/api/java/am2/api/spell/ISpellModifierManager.java create mode 100644 src/api/java/am2/api/spell/ISpellPartManager.java create mode 100644 src/api/java/am2/api/spell/ISpellShapeManager.java create mode 100644 src/api/java/am2/api/spell/ItemSpellBase.java create mode 100644 src/api/java/am2/api/spell/component/interfaces/IRitualInteraction.java create mode 100644 src/api/java/am2/api/spell/component/interfaces/ISkillTreeEntry.java create mode 100644 src/api/java/am2/api/spell/component/interfaces/ISpellComponent.java create mode 100644 src/api/java/am2/api/spell/component/interfaces/ISpellModifier.java create mode 100644 src/api/java/am2/api/spell/component/interfaces/ISpellPart.java create mode 100644 src/api/java/am2/api/spell/component/interfaces/ISpellShape.java create mode 100644 src/api/java/am2/api/spell/enums/Affinity.java create mode 100644 src/api/java/am2/api/spell/enums/BuffPowerLevel.java create mode 100644 src/api/java/am2/api/spell/enums/ContingencyTypes.java create mode 100644 src/api/java/am2/api/spell/enums/LearnStates.java create mode 100644 src/api/java/am2/api/spell/enums/SkillPointTypes.java create mode 100644 src/api/java/am2/api/spell/enums/SkillTrees.java create mode 100644 src/api/java/am2/api/spell/enums/SpellCastResult.java create mode 100644 src/api/java/am2/api/spell/enums/SpellModifiers.java create mode 100644 src/api/java/thaumcraft/api/IWarpingGear.java create mode 100644 src/api/java/vazkii/botania/api/item/IExoflameHeatable.java create mode 100644 src/api/java/vazkii/botania/api/item/IPetalApothecary.java create mode 100644 src/api/java/vazkii/botania/api/mana/spark/ISparkAttachable.java create mode 100644 src/api/java/vazkii/botania/api/mana/spark/ISparkEntity.java create mode 100644 src/api/java/vazkii/botania/api/mana/spark/SparkHelper.java create mode 100644 src/api/java/vazkii/botania/api/subtile/ISubTileContainer.java create mode 100644 src/api/java/vazkii/botania/api/subtile/signature/BasicSignature.java create mode 100644 src/api/java/vazkii/botania/api/subtile/signature/SubTileSignature.java create mode 100644 src/api/java/vazkii/botania/api/wand/IWandBindable.java create mode 100644 src/api/java/vazkii/botania/api/wiki/IWikiProvider.java create mode 100644 src/api/java/vazkii/botania/api/wiki/SimpleWikiProvider.java create mode 100644 src/api/java/vazkii/botania/api/wiki/WikiHooks.java diff --git a/src/api/java/am2/api/ArsMagicaApi.java b/src/api/java/am2/api/ArsMagicaApi.java new file mode 100644 index 0000000..6424ae0 --- /dev/null +++ b/src/api/java/am2/api/ArsMagicaApi.java @@ -0,0 +1,278 @@ +package am2.api; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.attributes.BaseAttribute; +import net.minecraft.entity.ai.attributes.IAttribute; +import net.minecraft.entity.ai.attributes.RangedAttribute; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.util.IIcon; +import am2.api.enchantment.IAMEnchantmentHelper; +import am2.api.entities.IEntityManager; +import am2.api.flickers.IFlickerRegistry; +import am2.api.items.IKeystoneHelper; +import am2.api.items.armor.IImbuementRegistry; +import am2.api.power.IObeliskFuelHelper; +import am2.api.spell.ISkillTreeManager; +import am2.api.spell.ISpellIconManager; +import am2.api.spell.ISpellPartManager; +import am2.api.spell.component.interfaces.ISkillTreeEntry; +import am2.api.spell.enums.SkillPointTypes; +import am2.api.spell.enums.SkillTrees; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class ArsMagicaApi { + public static final ArsMagicaApi instance = new ArsMagicaApi(); + + /** + * Easy access to this mod's ID + */ + public static final String AM2ModID = "arsmagica2"; + + private static String extendedPropertiesIdentifier; + private static String affinityDataIdentifier; + private static String skillDataIdentifier; + private static String riftStorageIdentifier; + + /** + * Attributes for AM2's properties + */ + //Bonus to max mana. Applied additively. + public static final IAttribute maxManaBonus = new RangedAttribute("am2.maxManaBonus", 0.0f, 0.0f, Double.MAX_VALUE).setDescription("Mana Bonus").setShouldWatch(true); + //Bonus to max burnout. Applied additively. + public static final IAttribute maxBurnoutBonus = new RangedAttribute("am2.maxBurnoutBonus", 0.0f, 0.0f, Double.MAX_VALUE).setDescription("Burnout Bonus").setShouldWatch(true); + //Bonus to XP gained. Applied multiplicatively. + public static final IAttribute xpGainModifier = new RangedAttribute("am2.xpMultiplier", 1.0f, 0.0f, Double.MAX_VALUE).setDescription("XP Mutiplier").setShouldWatch(true); + //Bonus to mana regen rate. Applied multiplicatively. + public static final IAttribute manaRegenTimeModifier = new RangedAttribute("am2.manaRegenModifier", 1.0f, 0.5f, 2.0f).setDescription("Mana Regen Rate Multiplier").setShouldWatch(true); + //Bonus to burnout reduction rate. Applied multiplicatively. + public static final IAttribute burnoutReductionRate = new RangedAttribute("am2.burnoutReduction", 1.0f, 0.1f, 2.0f).setDescription("Burnout Reduction Rate").setShouldWatch(true); + + private static final float manaBurnoutRatio = 0.38f; + private ArsMagicaApi(){ + + } + + //================================================================================ + // Getters + //================================================================================ + /** + * Gets the spell part manager. Used to register new shapes/components/modifiers/talents + */ + public final ISpellPartManager getSpellPartManager(){ + return spellPartManager; + } + + /** + * Gets the enchantment helper. Used to resolve current enchantment IDs. + */ + public final IAMEnchantmentHelper getEnchantHelper(){ + return enchantmentHelper; + } + + /** + * Gets the skill tree manager. Used to register spell parts into the skill trees (accessible via occulus) + */ + public final ISkillTreeManager getSkillTreeManager(){ + return this.skillTreeManager; + } + + /** + * Helper method to calculate the burnout for a spell based on mana cost. + */ + public static final float getBurnoutFromMana(float manaCost){ + return manaCost * manaBurnoutRatio; + } + + /** + * Gets the keystone helper instance. Used to check inventories for keys and check access to blocks lockable by keystone. + */ + public final IKeystoneHelper getKeystoneHelper(){ + return this.keystoneHelper; + } + + /** + * Gets the entity manager. Used to blacklist things from the progeny and butchery flicker operators + */ + public final IEntityManager getEntityManager(){ + return this.entityManager; + } + + /** + * Gets the fuel helper instance. Used to register new fuels for the Obelisk. + */ + public final IObeliskFuelHelper getFuelHelper(){ + return this.obeliskFuelHelper; + } + + /** + * Gets the flicker registry. Used to register new flicker operators into the habitat. + */ + public final IFlickerRegistry getFlickerOperatorRegistry(){ + return flickerOperatorRegistry; + } + + /** + * Gets the armor imbuement registry. Used to register new imbuements and check if imbuements are present on a given item stack. + */ + public final IImbuementRegistry getArmorInfusionRegistry(){ + return this.armorInfusionRegistry; + } + + /** + * Gets the AM recipe manager. Used to register new essence refiner recipes. + */ + public final IAMRecipeManager getEssenceRecipeManager(){ + return this.essenceRecipes; + } + + /** + * Is AM2 running in colourblind mode? + */ + public final boolean getColourblindMode(){ + return this.colourblindMode; + } + + /** + * Returns the extended properties for the passed in entity living + */ + public final IExtendedProperties getExtendedProperties(EntityLivingBase entity){ + return (IExtendedProperties) entity.getExtendedProperties(extendedPropertiesIdentifier); + } + + /** + * Returns the skill data instance (known shapes/modifiers/components/talents) + */ + public final ISkillData getSkillData(EntityPlayer entity){ + return (ISkillData) entity.getExtendedProperties(skillDataIdentifier); + } + + /** + * Returns the affinity data for the passed in entity + */ + public final IAffinityData getAffinityData(EntityLivingBase entity){ + return (IAffinityData) entity.getExtendedProperties(affinityDataIdentifier); + } + + /** + * Returns the rift storage for the passed in player. + */ + public final IInventory getRiftStorage(EntityPlayer entity){ + return (IInventory) entity.getExtendedProperties(riftStorageIdentifier); + } + + /** + * Registers a skill tree entry (Shape, Component, Modifier, or Talent) into the mod + * @param entry The skill tree entry to register + * @param name The unlocalized name that is used to identify this entry + * @param tree Which skill tree the entry should be located in + * @param x The x coordinate that the entry should be located at in the tree. Typical increments are of 45 to space the items. + * @param y The y coordinate that the entry should be located at in the tree. Typical increments are of 45 to space the items. + * @param point The type of skill point needed to unlock this entry + * @param prerequs Any skill tree entries that are required as prerequisites for this one. All prerequisites must be registered before the current entry. + */ + public final void registerSkillTreeEntry(ISkillTreeEntry entry, String name, SkillTrees tree, int x, int y, SkillPointTypes point, ISkillTreeEntry...prereqs){ + spellPartManager.registerSkillTreeEntry(entry, name); + skillTreeManager.RegisterPart(entry, x, y, tree, point, prereqs); + } + + /** + * Registers the IIcon to use for the specified skill. This should be called during the API's registerSkillTreeIcons event for each entry that you registered. You get a reference to the ISpellIconManager which has the same method, so this is only here for convenience. + * @param name The unlocalized name that was used to register the spell. See {@link #registerSkillTreeEntry(ISkillTreeEntry, String, SkillTrees, int, int, SkillPointTypes, ISkillTreeEntry...) registerSkillTreeEntry} method for more info on the name. + * @param IIcon The IIcon to use. You need to register these IIcons with the game beforehand during your mod's load phase - AM won't do it for you. + */ + @SideOnly(Side.CLIENT) + public final void registerSkillIcon(String name, IIcon IIcon){ + spellIconManager.registerIcon(name, IIcon); + } + + /** + * Returns the IIcon manager. This is used to register spell IIcons. + */ + @SideOnly(Side.CLIENT) + public final ISpellIconManager getSpellIconManager(){ + return spellIconManager; + } + + //================================================================================ + // Setters - for AM use only, do not call these. + //================================================================================ + public final void setSpellPartManager(ISpellPartManager manager){ + if (this.spellPartManager == null){ + this.spellPartManager = manager; + } + } + public final void setEnchantmentHelper(IAMEnchantmentHelper helper){ + if (this.enchantmentHelper == null){ + this.enchantmentHelper = helper; + } + } + public final void setSkillTreeManager(ISkillTreeManager manager){ + if (this.skillTreeManager == null) + this.skillTreeManager = manager; + } + @SideOnly(Side.CLIENT) + public final void setSpellIconManager(ISpellIconManager manager){ + if (this.spellIconManager == null) + this.spellIconManager = manager; + } + public final void setKeystoneHelper(IKeystoneHelper helper){ + if (this.keystoneHelper == null){ + this.keystoneHelper = helper; + } + } + public final void setExtendedPropertiesID(String identifier){ + if (extendedPropertiesIdentifier == null) + extendedPropertiesIdentifier = identifier; + } + public final void setAffinityDataID(String identifier){ + if (affinityDataIdentifier == null) + affinityDataIdentifier = identifier; + } + public final void setSkillDataID(String identifier){ + if (skillDataIdentifier == null) + skillDataIdentifier = identifier; + } + public final void setRiftStorageID(String identifier){ + if (riftStorageIdentifier == null) + riftStorageIdentifier = identifier; + } + public final void setEntityManager(IEntityManager manager){ + if (entityManager == null) + entityManager = manager; + } + public final void setObeliskFuelHelper(IObeliskFuelHelper manager){ + if (obeliskFuelHelper == null) + obeliskFuelHelper = manager; + } + public final void setFlickerOperatorRegistry(IFlickerRegistry registry){ + if (flickerOperatorRegistry == null) + flickerOperatorRegistry = registry; + } + public final void setInfusionRegistry(IImbuementRegistry registry){ + if (this.armorInfusionRegistry == null) + this.armorInfusionRegistry = registry; + } + public final void setEssenceRecipeHandler(IAMRecipeManager manager){ + if (this.essenceRecipes != null) + this.essenceRecipes = manager; + } + public final void setColourblindMode(boolean colourblindMode){ + this.colourblindMode = colourblindMode; + } + + private ISpellPartManager spellPartManager; + private ISkillTreeManager skillTreeManager; + private IAMEnchantmentHelper enchantmentHelper; + private IEntityManager entityManager; + private IKeystoneHelper keystoneHelper; + private IObeliskFuelHelper obeliskFuelHelper; + private IFlickerRegistry flickerOperatorRegistry; + private IImbuementRegistry armorInfusionRegistry; + private IAMRecipeManager essenceRecipes; + @SideOnly(Side.CLIENT) + private ISpellIconManager spellIconManager; + private boolean colourblindMode; + +} diff --git a/src/api/java/am2/api/IAMRecipeManager.java b/src/api/java/am2/api/IAMRecipeManager.java new file mode 100644 index 0000000..140b2ad --- /dev/null +++ b/src/api/java/am2/api/IAMRecipeManager.java @@ -0,0 +1,12 @@ +package am2.api; + +import net.minecraft.item.ItemStack; + +public interface IAMRecipeManager { + /** + * Adds a recipe to the essence refiner. + * @param output The output created + * @param components The components required. Must be a length of 5. + */ + public void addRefinerRecipe(ItemStack output, ItemStack[] components); +} diff --git a/src/api/java/am2/api/IAffinityData.java b/src/api/java/am2/api/IAffinityData.java new file mode 100644 index 0000000..e3adf27 --- /dev/null +++ b/src/api/java/am2/api/IAffinityData.java @@ -0,0 +1,28 @@ +package am2.api; + +import am2.api.spell.enums.Affinity; + +public interface IAffinityData { + + /** + * Gets the depth of the specified affinity as a percentage. + */ + float getAffinityDepth(Affinity affinity); + /** + * Gets the factor at which affinity gains are currently reduced. + */ + float getDiminishingReturnsFactor(); + /** + * Directly sets an affinity. Does not take into account oppositions. Use sparingly. + * @param affinity The affinity to set + * @param depth The depth to set + */ + void setAffinityAndDepth(Affinity affinity, float depth); + /** + * Increments the affinity by the specified amount, and decrements other affinities by an amount related to + * how much in opposition they are to the specified affinity. + * @param affinity The affinity to increase + * @param amt The amount to increase the affinity by + */ + void incrementAffinity(Affinity affinity, float amt); +} diff --git a/src/api/java/am2/api/IExtendedProperties.java b/src/api/java/am2/api/IExtendedProperties.java new file mode 100644 index 0000000..b822a6f --- /dev/null +++ b/src/api/java/am2/api/IExtendedProperties.java @@ -0,0 +1,25 @@ +package am2.api; + +import am2.api.math.AMVector3; + +/** + * Extended properties on EntityLiving used in Ars Magica. + * @author Mithion + * + */ +public interface IExtendedProperties { + public float getCurrentMana(); + public float getMaxMana(); + + public int getMarkDimension(); + public int getMagicLevel(); + public int getNumSummons(); + + public AMVector3 getMarkLocation(); + + public boolean getHasUnlockedAugmented(); + public boolean getMarkSet(); + + public boolean setMagicLevelWithMana(int magicLevel); + public void setCurrentMana(float currentMana); +} diff --git a/src/api/java/am2/api/ISkillData.java b/src/api/java/am2/api/ISkillData.java new file mode 100644 index 0000000..4c663c6 --- /dev/null +++ b/src/api/java/am2/api/ISkillData.java @@ -0,0 +1,66 @@ +package am2.api; + +import net.minecraft.entity.player.EntityPlayer; +import am2.api.spell.component.interfaces.ISkillTreeEntry; +import am2.api.spell.enums.LearnStates; +import am2.api.spell.enums.SkillPointTypes; + +public interface ISkillData { + /** + * Checks if the specified skill tree entry is known + */ + boolean isEntryKnown(SkillTreeEntry entry); + /** + * Returns the number of skill points of the given type that this skill data has + */ + int getSpellPoints(SkillPointTypes type); + /** + * Sets the number of skill points of the given type that this skill data has + */ + void setSpellPoints(int spellPoints, SkillPointTypes type); + /** + * Sets the number of skill points for all types that this skill data has + */ + void setSpellPoints(int spellPoints_blue, int spellPoints_green, int spellPoints_red); + /** + * Increments the skill points of the specified type. + */ + void incrementSpellPoints(SkillPointTypes type); + /** + * Decrements the skill points of the specified type. Cannot go below 0. + */ + void decrementSpellPoints(SkillPointTypes type); + /** + * Learns the specified entry. This will attempt to decrement skill points but is not bounded by it - make sure you check {@link #getLearnState(SkillTreeEntry, EntityPlayer)} first! + * @param entry + */ + void learn(ISkillTreeEntry entry); + /** + * Returns an array of shifted IDs representing the known shapes. + */ + Integer[] getKnownShapes(); + /** + * Returns an array of shifted IDs representing the known components. + */ + Integer[] getKnownComponents(); + /** + * Returns an array of shifted IDs representing the known modifiers. + */ + Integer[] getKnownModifiers(); + /** + * Returns an array of shifted IDs representing the known talents. + */ + Integer[] getKnownTalents(); + /** + * Forces changes to sync to appropriate clients. Chances are you won't have to call this, as the sync will happen at regular intervals if there are actually changes to sync. This is for when you need the changes clientside immediately. + */ + void forceSync(); + /** + * Clears all spell knowledge and skill points. Does not do any refunding -- this is NOT a respec! + */ + void clearAllKnowledge(); + /** + * Gets the learn state for the specified skill. + */ + LearnStates getLearnState(SkillTreeEntry entry, EntityPlayer player); +} diff --git a/src/api/java/am2/api/SkillTreeEntry.java b/src/api/java/am2/api/SkillTreeEntry.java new file mode 100644 index 0000000..ab74d6f --- /dev/null +++ b/src/api/java/am2/api/SkillTreeEntry.java @@ -0,0 +1,32 @@ +package am2.api; + +import am2.api.spell.component.interfaces.ISkillTreeEntry; +import am2.api.spell.enums.SkillTrees; + +public class SkillTreeEntry { + public final int x; + public final int y; + public final SkillTrees tree; + public final SkillTreeEntry[] prerequisites; + public final ISkillTreeEntry registeredItem; + public final int tier; + public boolean enabled; + + public SkillTreeEntry(int x, int y, SkillTrees tree, SkillTreeEntry[] prerequisites, ISkillTreeEntry registeredItem, boolean enabled){ + this.x = x; + this.y = y; + this.tree = tree; + this.prerequisites = prerequisites; + this.registeredItem = registeredItem; + this.enabled = enabled; + + int highestTier = 0; + for (SkillTreeEntry entry : prerequisites){ + if (entry.tier >= highestTier){ + highestTier = entry.tier + 1; + } + } + + this.tier = highestTier; + } +} diff --git a/src/api/java/am2/api/blocks/IKeystoneLockable.java b/src/api/java/am2/api/blocks/IKeystoneLockable.java new file mode 100644 index 0000000..c4a7ca1 --- /dev/null +++ b/src/api/java/am2/api/blocks/IKeystoneLockable.java @@ -0,0 +1,22 @@ +package am2.api.blocks; + +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; + +public interface IKeystoneLockable { + /** + * Return a three element array of the three runes in the inventory that make up the current keystone combination. + * Elements can be NULL if there is no rune present. + */ + public ItemStack[] getRunesInKey(); + + /** + * Does the keystone need to be the currently held item? Trumps {@link #keystoneMustBeInActionBar()}. + */ + public boolean keystoneMustBeHeld(); + + /** + * Does the keystone need to be in the action bar? Or can it be anywhere in the inventory? + */ + public boolean keystoneMustBeInActionBar(); +} diff --git a/src/api/java/am2/api/blocks/MultiblockStructureDefinition.java b/src/api/java/am2/api/blocks/MultiblockStructureDefinition.java new file mode 100644 index 0000000..fc8ec78 --- /dev/null +++ b/src/api/java/am2/api/blocks/MultiblockStructureDefinition.java @@ -0,0 +1,405 @@ +package am2.api.blocks; + +import java.util.ArrayList; +import java.util.HashMap; + +import net.minecraft.block.Block; +import net.minecraft.world.World; + +public class MultiblockStructureDefinition{ + public class BlockDec{ + Block block; + int meta; + + public BlockDec(Block block, int meta){ + this.block = block; + this.meta = meta; + } + + public Block getBlock(){ + return block; + } + + public int getMeta(){ + return meta; + } + + @Override + public String toString() { + String blockName = ""; + if (block != null){ + blockName = block.getLocalizedName(); + }else{ + blockName = "Unknown"; + } + return String.format("Block: %s, meta: %d", blockName, meta); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BlockDec){ + return this.block == ((BlockDec)obj).block && (this.meta == -1 || ((BlockDec)obj).meta == -1 || this.meta == ((BlockDec)obj).meta); + } + return false; + } + + @Override + public int hashCode() { + return Block.getIdFromBlock(block); + } + } + + public class BlockCoord implements Comparable{ + public int x; + public int y; + public int z; + + public BlockCoord(int offsetX, int offsetY, int offsetZ){ + this.x = offsetX; + this.y = offsetY; + this.z = offsetZ; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BlockCoord){ + return this.x == ((BlockCoord)obj).x && this.y == ((BlockCoord)obj).y && this.z == ((BlockCoord)obj).z; + } + return false; + } + + @Override + public int hashCode() { + return this.x + this.y + this.z; + } + + + public int getX(){ + return this.x; + } + + public int getY(){ + return this.y; + } + + public int getZ(){ + return this.z; + } + + @Override + public String toString() { + return String.format("BlockCoord: %d, %d, %d", x, y, z); + } + + @Override + public int compareTo(BlockCoord o) { + return this.z > o.z ? 1 : this.z < o.z ? -1 : this.x > o.x ? 1 : this.x < o.x ? -1 : this.y > o.y ? 1 : this.y < o.y ? -1 : 0; + } + } + + public class StructureGroup + { + String name; + int mutex; + HashMap> allowedBlocks; + + public StructureGroup(String name, int mutex){ + this.name = name; + this.mutex = mutex; + allowedBlocks = new HashMap>(); + } + + void addAllowedBlock(int offsetX, int offsetY, int offsetZ, Block block, int meta){ + BlockCoord originOffset = new BlockCoord(offsetX, offsetY, offsetZ); + if (!allowedBlocks.containsKey(originOffset)){ + allowedBlocks.put(originOffset, new ArrayList()); + } + ArrayList positionReplacements = allowedBlocks.get(originOffset); + positionReplacements.add(new BlockDec(block, meta)); + } + + ArrayList getAllowedBlocksAt(BlockCoord coord){ + return allowedBlocks.get(coord); + } + + boolean matchGroup(World world, int originX, int originY, int originZ){ + for (BlockCoord offset : allowedBlocks.keySet()){ + Block block = world.getBlock(originX + offset.x, originY + offset.y, originZ + offset.z); + int meta = world.getBlockMetadata(originX + offset.x, originY + offset.y, originZ + offset.z); + ArrayList positionReplacements = allowedBlocks.get(offset); + boolean valid = false; + for (BlockDec bd : positionReplacements){ + if (bd.block == block && (bd.meta == -1 || bd.meta == meta)){ + valid = true; + } + } + if (!valid) return false; + } + return true; + } + + HashMap> getStructureLayer(int layer){ + HashMap> toReturn = new HashMap>(); + + if (layer > getMaxLayer() || layer < getMinLayer()){ + return toReturn; + } + + for (BlockCoord bc : allowedBlocks.keySet()){ + if (bc.y == layer){ + toReturn.put(bc, allowedBlocks.get(bc)); + } + } + return toReturn; + } + + public void replaceAllBlocksOfType(Block originalBlock, Block newBlock){ + replaceAllBlocksOfType(originalBlock, -1, newBlock, -1); + } + + public void replaceAllBlocksOfType(Block originalBlock, int originalMeta, Block newBlock, int newMeta){ + for (BlockCoord bc : allowedBlocks.keySet()){ + for (BlockDec bd : allowedBlocks.get(bc)){ + if (bd.block == originalBlock){ + if (bd.meta == originalMeta || originalMeta == -1){ + bd.block = newBlock; + if (newMeta != -1){ + bd.meta = newMeta; + } + } + } + } + } + } + + public HashMap> getAllowedBlocks(){ + return (HashMap>) allowedBlocks.clone(); + } + + public void deleteBlocksFromWorld(World world, int x, int y, int z) { + for (BlockCoord offset : allowedBlocks.keySet()){ + world.setBlockToAir(x + offset.x, y + offset.y, z + offset.z); + } + } + } + + private StructureGroup mainGroup; + private ArrayList blockGroups; + private ArrayList mutexCache; + + public static final int MAINGROUP_MUTEX = 1; + + private String id; + + private int maxX = 0; + private int minX = 0; + private int maxY = 0; + private int minY = 0; + private int maxZ = 0; + private int minZ = 0; + + public MultiblockStructureDefinition(String id){ + blockGroups = new ArrayList(); + mutexCache = new ArrayList(); + this.id = id; + + //default group + mainGroup = createGroup("main", MAINGROUP_MUTEX); + } + + public String getID(){ + return this.id; + } + + public ArrayList getMutexList(){ + return mutexCache; + } + + public ArrayList getGroupsForMutex(int mutex){ + ArrayList toReturn = new ArrayList(); + + for (StructureGroup group : blockGroups){ + if (group.mutex == mutex){ + toReturn.add(group); + } + } + + return toReturn; + } + + public ArrayList getAllowedBlocksAt(StructureGroup group, BlockCoord coord){ + return group.getAllowedBlocksAt(coord); + } + + public ArrayList getAllowedBlocksAt(BlockCoord coord){ + return mainGroup.getAllowedBlocksAt(coord); + } + + public void addAllowedBlock(int offsetX, int offsetY, int offsetZ, Block block, int meta){ + + if (offsetY > maxY){ + maxY = offsetY; + }else if (offsetY < minY){ + minY = offsetY; + } + + if (offsetX > maxX){ + maxX = offsetX; + }else if (offsetX < minX){ + minX = offsetX; + } + + if (offsetZ > maxZ){ + maxZ = offsetZ; + }else if (offsetZ < minZ){ + minZ = offsetZ; + } + + mainGroup.addAllowedBlock(offsetX, offsetY, offsetZ, block, meta); + } + + public void addAllowedBlock(int offsetX, int offsetY, int offsetZ, Block block){ + addAllowedBlock(offsetX, offsetY, offsetZ, block, -1); + } + + public void addAllowedBlock(StructureGroup group, int offsetX, int offsetY, int offsetZ, Block block, int meta){ + if (!blockGroups.contains(group)){ + blockGroups.add(group); + } + + if (offsetY > maxY){ + maxY = offsetY; + }else if (offsetY < minY){ + minY = offsetY; + } + + if (offsetX > maxX){ + maxX = offsetX; + }else if (offsetX < minX){ + minX = offsetX; + } + + if (offsetZ > maxZ){ + maxZ = offsetZ; + }else if (offsetZ < minZ){ + minZ = offsetZ; + } + + group.addAllowedBlock(offsetX, offsetY, offsetZ, block, meta); + } + + public void addAllowedBlock(StructureGroup group, int offsetX, int offsetY, int offsetZ, Block block){ + addAllowedBlock(group, offsetX, offsetY, offsetZ, block, -1); + } + + public StructureGroup createGroup(String name, int mutex){ + if (!mutexCache.contains(mutex)){ + mutexCache.add(mutex); + } + StructureGroup group = new StructureGroup(name, mutex); + blockGroups.add(group); + return group; + } + + public StructureGroup copyGroup(String originalName, String destinationName, int newMutex){ + StructureGroup copyGroup = null; + for (StructureGroup group : blockGroups){ + if (group.name.equals(originalName)){ + copyGroup = group; + break; + } + } + + if (copyGroup == null) return null; + + StructureGroup newGroup; + + if (newMutex > -1){ + newGroup = new StructureGroup(destinationName, newMutex); + }else{ + newGroup = new StructureGroup(destinationName, copyGroup.mutex); + } + + for (BlockCoord bc : copyGroup.allowedBlocks.keySet()){ + for (BlockDec bd : copyGroup.allowedBlocks.get(bc)){ + newGroup.addAllowedBlock(bc.x, bc.y, bc.z, bd.block, bd.meta); + } + } + + blockGroups.add(newGroup); + + return newGroup; + } + + public StructureGroup copyGroup(String originalName, String destinationName){ + return copyGroup(originalName, destinationName, -1); + } + + public ArrayList getMatchedGroups(int mutex, World world, int originX, int originY, int originZ){ + ArrayList toReturn = new ArrayList(); + for (StructureGroup group : blockGroups){ + if ((group.mutex & mutex) == group.mutex){ + if (group.matchGroup(world, originX, originY, originZ)){ + toReturn.add(group); + } + } + } + return toReturn; + } + + private boolean matchMutex(int mutex, World world, int originX, int originY, int originZ){ + for (StructureGroup group : blockGroups){ + if ((group.mutex & mutex) == group.mutex){ + if (group.matchGroup(world, originX, originY, originZ)){ + return true; + } + } + } + return false; + } + + public boolean checkStructure(World world, int originX, int originY, int originZ){ + boolean valid = true; + for (int i: mutexCache){ + valid &= matchMutex(i, world, originX, originY, originZ); + if (!valid) break; + } + return valid; + } + + public int getMinLayer(){ + return this.minY; + } + + public int getMaxLayer(){ + return this.maxY; + } + + public int getHeight(){ + return this.maxY - this.minY; + } + + public int getWidth(){ + return this.maxX - this.minX; + } + + public int getLength(){ + return this.maxZ - this.minZ; + } + + public HashMap> getStructureLayer(int layer){ + return mainGroup.getStructureLayer(layer); + } + + public HashMap> getStructureLayer(StructureGroup group, int layer){ + return group.getStructureLayer(layer); + } + + public void removeMutex(int mutex, World world, int x, int y, int z){ + for (StructureGroup group : blockGroups){ + if (group.mutex == mutex){ + group.deleteBlocksFromWorld(world, x, y, z); + } + } + } +} diff --git a/src/api/java/am2/api/enchantment/IAMEnchantmentHelper.java b/src/api/java/am2/api/enchantment/IAMEnchantmentHelper.java new file mode 100644 index 0000000..59c914c --- /dev/null +++ b/src/api/java/am2/api/enchantment/IAMEnchantmentHelper.java @@ -0,0 +1,12 @@ +package am2.api.enchantment; + +public interface IAMEnchantmentHelper { + /** + * Gets the current ID for soulbound enchantment + */ + public int getSoulboundID(); + /** + * Gets the current ID for magic resist enchantment + */ + public int getMagicResistID(); +} diff --git a/src/api/java/am2/api/entities/IEntityManager.java b/src/api/java/am2/api/entities/IEntityManager.java new file mode 100644 index 0000000..b2620df --- /dev/null +++ b/src/api/java/am2/api/entities/IEntityManager.java @@ -0,0 +1,12 @@ +package am2.api.entities; + +public interface IEntityManager { + /** + * Adds the specified entities to the butchery blacklist (won't be affected by sigil of butchery) + */ + public void addButcheryBlacklist(Class...clazz); + /** + * Adds the specified entities to the progeny blacklist (won't be affected by sigil of progeny) + */ + public void addProgenyBlacklist(Class...clazz); +} diff --git a/src/api/java/am2/api/events/ManaCostEvent.java b/src/api/java/am2/api/events/ManaCostEvent.java new file mode 100644 index 0000000..036a0f2 --- /dev/null +++ b/src/api/java/am2/api/events/ManaCostEvent.java @@ -0,0 +1,24 @@ +package am2.api.events; + +import cpw.mods.fml.common.eventhandler.Event; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; + +/** + * Fired whenever mana cost of a spell is calculated, after all predefined calculations. + * @author Mithion + * + */ +public class ManaCostEvent extends Event{ + public final ItemStack spell; + public final EntityLivingBase caster; + public float manaCost; + public float burnout; + + public ManaCostEvent(ItemStack spell, EntityLivingBase caster, float manaCost, float burnout){ + this.spell = spell; + this.caster = caster; + this.manaCost = manaCost; + this.burnout = burnout; + } +} diff --git a/src/api/java/am2/api/events/ModifierCalculatedEvent.java b/src/api/java/am2/api/events/ModifierCalculatedEvent.java new file mode 100644 index 0000000..1df2afe --- /dev/null +++ b/src/api/java/am2/api/events/ModifierCalculatedEvent.java @@ -0,0 +1,41 @@ +package am2.api.events; + +import cpw.mods.fml.common.eventhandler.Event; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import am2.api.spell.enums.SpellModifiers; + +/** + * Called whenever a spell's modified variable is calculated + * @author Mithion + * + */ +public class ModifierCalculatedEvent extends Event { + //The attribute being modified + public final SpellModifiers attribute; + //The caster of the spell + public final EntityLivingBase caster; + //The spell being cast. This is a copy of the ItemStack. + public final ItemStack spell; + //the initial value of the variable + public final double initialValue; + //the type of operation being used to modify the value + public final OperationType operation; + + //the final modified value of the variable + public double modifiedValue; + + public enum OperationType{ + ADD, + MULTIPLY + } + + public ModifierCalculatedEvent(ItemStack spell, EntityLivingBase caster, SpellModifiers attribute, double initialValue, double modifiedValue, OperationType operation){ + this.spell = spell; + this.caster = caster; + this.attribute = attribute; + this.initialValue = initialValue; + this.modifiedValue = modifiedValue; + this.operation = operation; + } +} diff --git a/src/api/java/am2/api/events/PlayerMagicLevelChangeEvent.java b/src/api/java/am2/api/events/PlayerMagicLevelChangeEvent.java new file mode 100644 index 0000000..4da7262 --- /dev/null +++ b/src/api/java/am2/api/events/PlayerMagicLevelChangeEvent.java @@ -0,0 +1,19 @@ +package am2.api.events; + +import net.minecraft.entity.EntityLivingBase; +import cpw.mods.fml.common.eventhandler.Event; + +/** + * Raised when a player's magic level changes. + * @author Mithion + * + */ +public class PlayerMagicLevelChangeEvent extends Event { + public final int level; + public final EntityLivingBase entity; + + public PlayerMagicLevelChangeEvent(EntityLivingBase entity, int level){ + this.entity = entity; + this.level = level; + } +} diff --git a/src/api/java/am2/api/events/ReconstructorRepairEvent.java b/src/api/java/am2/api/events/ReconstructorRepairEvent.java new file mode 100644 index 0000000..d4ee631 --- /dev/null +++ b/src/api/java/am2/api/events/ReconstructorRepairEvent.java @@ -0,0 +1,22 @@ +package am2.api.events; + +import net.minecraft.item.ItemStack; +import cpw.mods.fml.common.eventhandler.Cancelable; +import cpw.mods.fml.common.eventhandler.Event; + +@Cancelable +public class ReconstructorRepairEvent extends Event{ + + /** + * The item being repaired. + */ + public ItemStack item; + + /** + * Called when the arcane reconstructor ticks on repairing an item. + * @param item + */ + public ReconstructorRepairEvent(ItemStack item){ + this.item = item; + } +} diff --git a/src/api/java/am2/api/events/RegisterSkillTreeIcons.java b/src/api/java/am2/api/events/RegisterSkillTreeIcons.java new file mode 100644 index 0000000..4ed371f --- /dev/null +++ b/src/api/java/am2/api/events/RegisterSkillTreeIcons.java @@ -0,0 +1,12 @@ +package am2.api.events; + +import cpw.mods.fml.common.eventhandler.Event; +import am2.api.spell.ISpellIconManager; + +public class RegisterSkillTreeIcons extends Event{ + public final ISpellIconManager manager; + + public RegisterSkillTreeIcons(ISpellIconManager manager){ + this.manager = manager; + } +} diff --git a/src/api/java/am2/api/events/SkillLearnedEvent.java b/src/api/java/am2/api/events/SkillLearnedEvent.java new file mode 100644 index 0000000..1e53eb8 --- /dev/null +++ b/src/api/java/am2/api/events/SkillLearnedEvent.java @@ -0,0 +1,20 @@ +package am2.api.events; + +import net.minecraft.entity.player.EntityPlayer; +import cpw.mods.fml.common.eventhandler.Event; +import am2.api.spell.component.interfaces.ISkillTreeEntry; + +/** + * Raised when a player learns a skill at the Occulus + * @author Mithion + * + */ +public class SkillLearnedEvent extends Event{ + public final EntityPlayer player; + public final ISkillTreeEntry skill; + + public SkillLearnedEvent(EntityPlayer player, ISkillTreeEntry entry){ + this.player = player; + this.skill = entry; + } +} diff --git a/src/api/java/am2/api/events/SpellCastingEvent.java b/src/api/java/am2/api/events/SpellCastingEvent.java new file mode 100644 index 0000000..02c0b51 --- /dev/null +++ b/src/api/java/am2/api/events/SpellCastingEvent.java @@ -0,0 +1,93 @@ +package am2.api.events; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import cpw.mods.fml.common.eventhandler.Cancelable; +import cpw.mods.fml.common.eventhandler.Event; +import am2.api.spell.ItemSpellBase; +import am2.api.spell.enums.SpellCastResult; + +public class SpellCastingEvent{ + @Cancelable + public class Pre extends Event{ + /** + * The spell being cast + */ + public final ItemSpellBase spell; + /** + * The caster of the spell + */ + public final EntityLivingBase caster; + /** + * The calculated mana cost of the spell + */ + public final float manaCost; + /** + * The calculated burnout of the spell + */ + public final float burnout; + /** + * The itemstack representing the spell + */ + public final ItemStack stack; + /** + * The result to be returned after casting the spell + */ + public SpellCastResult castResult; + /** + * Is the spell channeled (maintained in any way, not the shape, so beam counts too) + */ + public final boolean isChanneled; + + public Pre(ItemStack stack, ItemSpellBase spell, EntityLivingBase caster, float manaCost, float burnout, boolean isChanneled){ + this.caster = caster; + this.spell = spell; + this.manaCost = manaCost; + this.burnout = burnout; + this.stack = stack; + this.isChanneled = isChanneled; + } + } + + @Cancelable + public class Post extends Event{ + /** + * The spell being cast + */ + public final ItemSpellBase spell; + /** + * The caster of the spell + */ + public final EntityLivingBase caster; + /** + * The calculated mana cost of the spell + */ + public final float manaCost; + /** + * The calculated burnout of the spell + */ + public final float burnout; + /** + * The itemstack representing the spell + */ + public final ItemStack stack; + /** + * The result to be returned after casting the spell + */ + public final SpellCastResult castResult; + /** + * Is the spell channeled (maintained in any way, not the shape, so beam counts too) + */ + public final boolean isChanneled; + + public Post(ItemStack stack, ItemSpellBase spell, EntityLivingBase caster, float manaCost, float burnout, boolean isChanneled, SpellCastResult castResult){ + this.caster = caster; + this.spell = spell; + this.manaCost = manaCost; + this.burnout = burnout; + this.stack = stack; + this.isChanneled = isChanneled; + this.castResult = castResult; + } + } +} diff --git a/src/api/java/am2/api/events/SpellRecipeItemsEvent.java b/src/api/java/am2/api/events/SpellRecipeItemsEvent.java new file mode 100644 index 0000000..1186c1b --- /dev/null +++ b/src/api/java/am2/api/events/SpellRecipeItemsEvent.java @@ -0,0 +1,33 @@ +package am2.api.events; + +import cpw.mods.fml.common.eventhandler.Event; + +public class SpellRecipeItemsEvent extends Event{ + public final String registeredName; //The registered name of the spell part. Used to identify what spell shape/component/modifier we are working with + public final int ID; //The ID of the spell part. Also can be used to identify what we are working with, if you don't like strings. + + /** + * recipe items, in order, that need to be thrown into the crafting altar in order to create the item. + *
+ * Use Items for items, Blocks for blocks, Strings for OreDictionary items, and E:[type flag] followed by an integer for essence amounts. + *
+ * Use itemstacks for items/blocks/oredict when meta is required. By default it is meta 0. Quantity (stack size) is ignored. + *
+ * Integer pairs represent the type (*=any, 1=neutral, 2=light, 4=dark, etc.), and the quantity of essence required. The type can be used as flags, + *
+ * For example: + *
+	 *     new Object[]{ "E:1|2", 1500 } //require 1500 of neutral or 1500 of light power.
+	 *     new Object[]{ "E:*", 1500 } //require 1500 of any kind of power
+	 *     etc.
+	 *
+ */ + public Object[] recipeItems; //The actual recipe items. Change or verify them here. + + public SpellRecipeItemsEvent(String name, int ID, Object[] recipeItems){ + registeredName = name; + this.ID = ID; + this.recipeItems = recipeItems; + } + +} diff --git a/src/api/java/am2/api/flickers/IFlickerController.java b/src/api/java/am2/api/flickers/IFlickerController.java new file mode 100644 index 0000000..5259d02 --- /dev/null +++ b/src/api/java/am2/api/flickers/IFlickerController.java @@ -0,0 +1,9 @@ +package am2.api.flickers; + +import net.minecraft.tileentity.TileEntity; + +public interface IFlickerController { + public byte[] getMetadata(IFlickerFunctionality operator); + public void setMetadata(IFlickerFunctionality operator, byte[] meta); + public void removeMetadata(IFlickerFunctionality operator); +} diff --git a/src/api/java/am2/api/flickers/IFlickerFunctionality.java b/src/api/java/am2/api/flickers/IFlickerFunctionality.java new file mode 100644 index 0000000..0073993 --- /dev/null +++ b/src/api/java/am2/api/flickers/IFlickerFunctionality.java @@ -0,0 +1,15 @@ +package am2.api.flickers; + +import net.minecraft.world.World; +import am2.api.spell.enums.Affinity; + +public interface IFlickerFunctionality { + boolean RequiresPower(); + int PowerPerOperation(); + boolean DoOperation(World worldObj, IFlickerController controller, boolean powered); + boolean DoOperation(World worldObj, IFlickerController controller, boolean powered, Affinity[] flickers); + void RemoveOperator(World worldObj, IFlickerController controller, boolean powered); + int TimeBetweenOperation(boolean powered, Affinity[] flickers); + void RemoveOperator(World worldObj, IFlickerController controller, boolean powered, Affinity[] flickers); + Object[] getRecipe(); +} diff --git a/src/api/java/am2/api/flickers/IFlickerRegistry.java b/src/api/java/am2/api/flickers/IFlickerRegistry.java new file mode 100644 index 0000000..8b8ddc7 --- /dev/null +++ b/src/api/java/am2/api/flickers/IFlickerRegistry.java @@ -0,0 +1,11 @@ +package am2.api.flickers; + +public interface IFlickerRegistry { + /** + * Attempts to register a flicker operator into the flicker network + * @param singleton The instance of the class that should be called upon to perform the operations when loaded into a flicker block + * @param mask The bit mask representing the flicker combination. These are ORed affinity masks. @see am2.api.spell.enums.Affinity.getMask for specific mask flags (flickers represent an affinity) + * @return True if registered, false if the mask is already in use. + */ + public boolean registerFlickerOperator(IFlickerFunctionality singleton, int mask); +} diff --git a/src/api/java/am2/api/illeffect/BadThingTypes.java b/src/api/java/am2/api/illeffect/BadThingTypes.java new file mode 100644 index 0000000..3ac544f --- /dev/null +++ b/src/api/java/am2/api/illeffect/BadThingTypes.java @@ -0,0 +1,6 @@ +package am2.api.illeffect; + +public enum BadThingTypes{ + ALL, + DARKNEXUS +} \ No newline at end of file diff --git a/src/api/java/am2/api/illeffect/IIllEffect.java b/src/api/java/am2/api/illeffect/IIllEffect.java new file mode 100644 index 0000000..2c1f111 --- /dev/null +++ b/src/api/java/am2/api/illeffect/IIllEffect.java @@ -0,0 +1,38 @@ +package am2.api.illeffect; + +import java.util.List; +import java.util.Map; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; + +/** + * Base interface for an ill effect during spell creation.
+ * Included for compatibility; do not directly inherit.
+ * Use IllEffectBase instead. + * @author Mithion + * + */ +public interface IIllEffect extends Comparable { + /** + * The severity level of the effect. Controls at what instability level the effect could be applied. + * @return One of the values in the IllEffectSeverity enum. + */ + public IllEffectSeverity GetSeverity(); + + /** + * Callback to actually apply the ill effect. + * @param world The world the effect is happening in + * @param x The x coordinate of the vinteum crystal + * @param y The y coordinate of the vinteum crystal + * @param z The z coordinate of the vinteum crystal + * @return A map of entity players affected, as well as any metadata relevant to the effect applied on that player. + */ + public Map ApplyIllEffect(World world, int x, int y, int z); + + /** + * Gets the localized description of this ill effect as pertains to the affected entity player. + * This will only be called based on your own class, so you can assume the metadata matches your metadata output from ApplyIllEffect. + */ + public String getDescription(EntityPlayer player, Object metadata); +} diff --git a/src/api/java/am2/api/illeffect/IllEffectBase.java b/src/api/java/am2/api/illeffect/IllEffectBase.java new file mode 100644 index 0000000..4ca2293 --- /dev/null +++ b/src/api/java/am2/api/illeffect/IllEffectBase.java @@ -0,0 +1,41 @@ +package am2.api.illeffect; + +import java.util.List; +import java.util.Map; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; + +/** + * Base class for all ill effects. + * @author Mithion + * + */ +public abstract class IllEffectBase implements IIllEffect{ + + @Override + public final int compareTo(Object o) { + if (!(o instanceof IIllEffect)) return 0; + IIllEffect right = (IIllEffect)o; + int myOrdinal = this.GetSeverity().ordinal(); + int theirOrdinal = right.GetSeverity().ordinal(); + + if (myOrdinal == theirOrdinal){ + return 0; + }else if (myOrdinal < theirOrdinal){ + return -1; + }else{ + return 1; + } + } + + @Override + public abstract IllEffectSeverity GetSeverity(); + + @Override + public abstract String getDescription(EntityPlayer player, Object metadata); + + @Override + public abstract Map ApplyIllEffect(World world, int x, int y, int z); + +} diff --git a/src/api/java/am2/api/illeffect/IllEffectSeverity.java b/src/api/java/am2/api/illeffect/IllEffectSeverity.java new file mode 100644 index 0000000..d86c9bb --- /dev/null +++ b/src/api/java/am2/api/illeffect/IllEffectSeverity.java @@ -0,0 +1,14 @@ +package am2.api.illeffect; + +/** + * Varying severities for ill effects during spell creation. + * @author Mithion + * + */ +public enum IllEffectSeverity { + MINOR, + MODERATE, + MAJOR, + SEVERE, + FATAL +} diff --git a/src/api/java/am2/api/items/IKeystoneHelper.java b/src/api/java/am2/api/items/IKeystoneHelper.java new file mode 100644 index 0000000..7b0b192 --- /dev/null +++ b/src/api/java/am2/api/items/IKeystoneHelper.java @@ -0,0 +1,30 @@ +package am2.api.items; + +import java.util.ArrayList; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import am2.api.blocks.IKeystoneLockable; + +public interface IKeystoneHelper { + /** + * Gets all the keys from all keystones in the entity's inventory + */ + public ArrayList GetKeysInInvenory(EntityLivingBase ent); + + /** + * Returns the key combination made by the specified runes + * @param runes An array of runes no larger than three elements (anything above will be ignored) + * @return + */ + public long getKeyFromRunes(ItemStack[] runes); + + /** + * Returns true or false based on whether the passed in player meets the keystone requirements needed to access the specified container + * @param inventory The inventory the player is trying to access + * @param player The player attempting the access check + * @return True if the conditions are met, otherwise false + */ + public boolean canPlayerAccess(IKeystoneLockable inventory, EntityPlayer player); +} diff --git a/src/api/java/am2/api/items/armor/ArmorTextureEvent.java b/src/api/java/am2/api/items/armor/ArmorTextureEvent.java new file mode 100644 index 0000000..2701d9b --- /dev/null +++ b/src/api/java/am2/api/items/armor/ArmorTextureEvent.java @@ -0,0 +1,16 @@ +package am2.api.items.armor; + +import cpw.mods.fml.common.eventhandler.Event; + + +public class ArmorTextureEvent extends Event{ + public final int slot; + public final int renderIndex; + + public String texture; + + public ArmorTextureEvent(int slot, int renderIndex){ + this.slot = slot; + this.renderIndex = renderIndex; + } +} diff --git a/src/api/java/am2/api/items/armor/IArmorImbuement.java b/src/api/java/am2/api/items/armor/IArmorImbuement.java new file mode 100644 index 0000000..fe71ed7 --- /dev/null +++ b/src/api/java/am2/api/items/armor/IArmorImbuement.java @@ -0,0 +1,60 @@ +package am2.api.items.armor; + +import java.util.EnumSet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; + +public interface IArmorImbuement { + /** + * Gets the ID of the infusion effect. Must be unique. + */ + String getID(); + /** + * Gets the IIcon index for the texture in the GUI + */ + int getIconIndex(); + /** + * Gets the tier for this infusion + */ + ImbuementTiers getTier(); + /** + * Gets all situations under which this infusion applies + */ + EnumSet getApplicationTypes(); + /** + * Applies the effect. This will be called when any of the application types is matched in an event. + * @param player The player wearing the armor + * @param world The world the player is in + * @param stack The itemstack that was matched + * @param matchedType The application type that was matched. + * @param params Depends on the application type. + *
+ * In the case of ON_TICK, it will be a 1-length array with the first element being the LivingEvent event
+ * In the case of ON_JUMP, it will be a 1-length array with the first element being the LivingJumpEvent event
+ * In the case of ON_HIT, it will be a 1-length array with the first element being the LivingHurtEvent event
+ * In the case of ON_MINING_SPEED, it will be a 1-length array with the first element being the BreakSpeed event
+ */ + boolean applyEffect(EntityPlayer player, World world, ItemStack stack, ImbuementApplicationTypes matchedType, Object...params); + + /** + * Gets all armor slots that this effect can be applied to + */ + int[] getValidSlots(); + + /** + * If the slot is on cooldown, can the effect still apply? + */ + boolean canApplyOnCooldown(); + + /** + * Get the amount of cooldown to add to the slot once the effect applies + */ + int getCooldown(); + + /** + * How much does the infusion damage the armor? + */ + int getArmorDamage(); +} diff --git a/src/api/java/am2/api/items/armor/IImbuementRegistry.java b/src/api/java/am2/api/items/armor/IImbuementRegistry.java new file mode 100644 index 0000000..fad9d28 --- /dev/null +++ b/src/api/java/am2/api/items/armor/IImbuementRegistry.java @@ -0,0 +1,28 @@ +package am2.api.items.armor; + +import net.minecraft.item.ItemStack; + + +public interface IImbuementRegistry { + /** + * Registers a new imbuement instance into the system + */ + void registerImbuement(IArmorImbuement imbuementInstance); + /** + * Locates the specified imbuement registered to the passed-in ID. + * Returns null if not found. + */ + IArmorImbuement getImbuementByID(String ID); + /** + * Returns all imbuements registered into the specified tier for the given armor type (slot). + */ + IArmorImbuement[] getImbuementsForTier(ImbuementTiers tier, int armorType); + /** + * Is the given imbuement instance present on the passed-in item stack? + */ + boolean isImbuementPresent(ItemStack stack, IArmorImbuement imbuement); + /** + * Is the given imbuement ID present on the passed-in item stack? + */ + boolean isImbuementPresent(ItemStack stack, String id); +} diff --git a/src/api/java/am2/api/items/armor/ImbuementApplicationTypes.java b/src/api/java/am2/api/items/armor/ImbuementApplicationTypes.java new file mode 100644 index 0000000..4eb633a --- /dev/null +++ b/src/api/java/am2/api/items/armor/ImbuementApplicationTypes.java @@ -0,0 +1,10 @@ +package am2.api.items.armor; + +public enum ImbuementApplicationTypes { + NONE, + ON_TICK, + ON_HIT, + ON_JUMP, + ON_MINING_SPEED, + ON_DEATH +} diff --git a/src/api/java/am2/api/items/armor/ImbuementTiers.java b/src/api/java/am2/api/items/armor/ImbuementTiers.java new file mode 100644 index 0000000..b6c8b90 --- /dev/null +++ b/src/api/java/am2/api/items/armor/ImbuementTiers.java @@ -0,0 +1,8 @@ +package am2.api.items.armor; + +public enum ImbuementTiers { + FIRST, + SECOND, + THIRD, + FOURTH +} diff --git a/src/api/java/am2/api/math/AMLineSegment.java b/src/api/java/am2/api/math/AMLineSegment.java new file mode 100644 index 0000000..d723ab0 --- /dev/null +++ b/src/api/java/am2/api/math/AMLineSegment.java @@ -0,0 +1,42 @@ +package am2.api.math; + +public class AMLineSegment { + private AMVector3 a,b; + + public AMLineSegment(AMVector3 a, AMVector3 b){ + this.a = a; + this.b = b; + } + + public AMVector3 closestPointOnLine(AMVector3 vPoint) + { + + // Create the vector from end point vA to our point vPoint. + AMVector3 vVector1 = vPoint.copy().sub(a); + + // Create a normalized direction vector from end point vA to end point vB + AMVector3 vVector2 = b.copy().sub(a).normalize(); + + // Use the distance formula to find the distance of the line segment (or magnitude) + float d = (float) a.distanceTo(b); + + // Using the dot product, we project the vVector1 onto the vector vVector2. + // This essentially gives us the distance from our projected vector from vA. + float t = AMVector3.dotProduct(vVector2, vVector1); + + // If our projected distance from vA, "t", is less than or equal to 0, it must + // be closest to the end point vA. We want to return this end point. + if (t <= 0) + return a.copy(); + + // If our projected distance from vA, "t", is greater than or equal to the magnitude + // or distance of the line segment, it must be closest to the end point vB. So, return vB. + if (t >= d) + return b.copy(); + + AMVector3 vVector3 = vVector2.copy().scale(t); + AMVector3 vClosestPoint = a.copy().add(vVector3); + + return vClosestPoint; + } +} diff --git a/src/api/java/am2/api/math/AMMatrix4.java b/src/api/java/am2/api/math/AMMatrix4.java new file mode 100644 index 0000000..402d9e5 --- /dev/null +++ b/src/api/java/am2/api/math/AMMatrix4.java @@ -0,0 +1,56 @@ +package am2.api.math; + + +public class AMMatrix4 +{ + float[] mat; + + public AMMatrix4() + { + loadIdentity(); + } + + public AMMatrix4 loadIdentity() + { + this.mat = new float[16]; + float tmp35_34 = (this.mat[10] = this.mat[15] = 1.0F); + this.mat[5] = tmp35_34; + this.mat[0] = tmp35_34; + return this; + } + + public AMVector3 translate(AMVector3 vec) + { + float x = vec.x * this.mat[0] + vec.y * this.mat[1] + vec.z * this.mat[2] + this.mat[3]; + float y = vec.x * this.mat[4] + vec.y * this.mat[5] + vec.z * this.mat[6] + this.mat[7]; + float z = vec.x * this.mat[8] + vec.y * this.mat[9] + vec.z * this.mat[10] + this.mat[11]; + vec.x = x; + vec.y = y; + vec.z = z; + return vec; + } + + public static AMMatrix4 rotationMat(double angle, AMVector3 axis) + { + axis = axis.copy().normalize(); + float x = axis.x; + float y = axis.y; + float z = axis.z; + angle *= 0.0174532925D; + float cos = (float)Math.cos(angle); + float ocos = 1.0F - cos; + float sin = (float)Math.sin(angle); + AMMatrix4 rotmat = new AMMatrix4(); + rotmat.mat[0] = (x * x * ocos + cos); + rotmat.mat[1] = (y * x * ocos + z * sin); + rotmat.mat[2] = (x * z * ocos - y * sin); + rotmat.mat[4] = (x * y * ocos - z * sin); + rotmat.mat[5] = (y * y * ocos + cos); + rotmat.mat[6] = (y * z * ocos + x * sin); + rotmat.mat[8] = (x * z * ocos + y * sin); + rotmat.mat[9] = (y * z * ocos - x * sin); + rotmat.mat[10] = (z * z * ocos + cos); + rotmat.mat[15] = 1.0F; + return rotmat; + } +} diff --git a/src/api/java/am2/api/math/AMPlane.java b/src/api/java/am2/api/math/AMPlane.java new file mode 100644 index 0000000..28ed9a9 --- /dev/null +++ b/src/api/java/am2/api/math/AMPlane.java @@ -0,0 +1,47 @@ +package am2.api.math; + +public class AMPlane { + AMVector3 planeDef[]; + + public AMPlane(AMVector3...plane){ + planeDef = plane; + } + + private AMVector3 planeNormal(){ + AMVector3 vVector1 = new AMVector3(planeDef[2], planeDef[0]); + AMVector3 vVector2 = new AMVector3(planeDef[1], planeDef[0]); + + AMVector3 vNormal = AMVector3.crossProduct(vVector1, vVector2); + + vNormal.normalize(); + return vNormal; + } + + private float planeDistance(AMVector3 normal, AMVector3 point){ + float distance = 0; + distance = - ((normal.x * point.x) + (normal.y * point.y) + (normal.z * point.z)); + + return distance; + } + + public boolean lineSegmentCrosses(AMVector3 p1, AMVector3 p2){ + float distance1=0, distance2=0; + + AMVector3 vNormal = planeNormal(); + + float originDistance = planeDistance(vNormal, planeDef[0]); + + distance1 = ((vNormal.x * p1.x) + // Ax + + (vNormal.y * p1.y) + // Bx + + (vNormal.z * p1.z)) + originDistance; // Cz + D + + distance2 = ((vNormal.x * p2.x) + // Ax + + (vNormal.y * p2.y) + // Bx + + (vNormal.z * p2.z)) + originDistance; // Cz + D + + if(distance1 * distance2 >= 0) // Check to see if both point's distances are both negative or both positive + return false; // Return false if each point has the same sign. -1 and 1 would mean each point is on either side of the plane. -1 -2 or 3 4 wouldn't... + + return true; // The line intersected the plane, Return TRUE + } +} diff --git a/src/api/java/am2/api/math/AMVector2.java b/src/api/java/am2/api/math/AMVector2.java new file mode 100644 index 0000000..84b7b82 --- /dev/null +++ b/src/api/java/am2/api/math/AMVector2.java @@ -0,0 +1,32 @@ +package am2.api.math; + +public class AMVector2 { + public double x; + public double y; + + public int iX; + public int iY; + + public AMVector2(double x, double y){ + this.x = x; + this.y = y; + this.iX = (int)x; + this.iY = (int)y; + } + + public AMVector2 subtract(AMVector2 vec){ + return new AMVector2(this.x - vec.x, this.y - vec.y); + } + + public AMVector2 add(AMVector2 vec){ + return new AMVector2(this.x + vec.x, this.y + vec.y); + } + + public AMVector2 multiply(AMVector2 vec){ + return new AMVector2(this.x * vec.x, this.y * vec.y); + } + + public AMVector2 divide(AMVector2 vec){ + return new AMVector2(this.x / vec.x, this.y / vec.y); + } +} diff --git a/src/api/java/am2/api/math/AMVector3.java b/src/api/java/am2/api/math/AMVector3.java new file mode 100644 index 0000000..a38c098 --- /dev/null +++ b/src/api/java/am2/api/math/AMVector3.java @@ -0,0 +1,246 @@ +package am2.api.math; + +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; + +public class AMVector3 +{ + public float x; + public float y; + public float z; + + public AMVector3(double x, double y, double z) + { + this.x = (float)x; + this.y = (float)y; + this.z = (float)z; + } + + public AMVector3(TileEntity tile) + { + this.x = (tile.xCoord); + this.y = (tile.yCoord); + this.z = (tile.zCoord); + } + + public AMVector3(Vec3 vec){ + this.x = (float) vec.xCoord; + this.y = (float) vec.yCoord; + this.z = (float) vec.zCoord; + } + + public AMVector3(AMVector3 a, AMVector3 b){ + this.x = a.x - b.x; // Get the X value of our new vector + this.y = a.y - b.y; // Get the Y value of our new vector + this.z = a.z - b.z; // Get the Z value of our new vector + } + + public AMVector3(Entity entity) + { + this(entity.posX, entity.posY, entity.posZ); + } + + public AMVector3 add(AMVector3 vec) + { + this.x += vec.x; + this.y += vec.y; + this.z += vec.z; + return this; + } + + public AMVector3 sub(AMVector3 vec) + { + this.x -= vec.x; + this.y -= vec.y; + this.z -= vec.z; + return this; + } + + public AMVector3 scale(float scale) + { + this.x *= scale; + this.y *= scale; + this.z *= scale; + return this; + } + + public AMVector3 scale(float scalex, float scaley, float scalez) + { + this.x *= scalex; + this.y *= scaley; + this.z *= scalez; + return this; + } + + public AMVector3 modulo(float divisor){ + this.x %= divisor; + this.y %= divisor; + this.z %= divisor; + return this; + } + + public AMVector3 normalize() + { + float length = length(); + this.x /= length; + this.y /= length; + this.z /= length; + return this; + } + + public float length() + { + return (float)Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + + public float lengthPow2() + { + return this.x * this.x + this.y * this.y + this.z * this.z; + } + + public AMVector3 copy() + { + return new AMVector3(this.x, this.y, this.z); + } + + public static AMVector3 crossProduct(AMVector3 vec1, AMVector3 vec2) + { + return new AMVector3(vec1.y * vec2.z - vec1.z * vec2.y, vec1.z * vec2.x - vec1.x * vec2.z, vec1.x * vec2.y - vec1.y * vec2.x); + } + + public static AMVector3 xCrossProduct(AMVector3 vec) + { + return new AMVector3(0.0D, vec.z, -vec.y); + } + + public static AMVector3 zCrossProduct(AMVector3 vec) + { + return new AMVector3(-vec.y, vec.x, 0.0D); + } + + public static float dotProduct(AMVector3 vec1, AMVector3 vec2) + { + return (vec1.x * vec2.x) + (vec1.y * vec2.y) + (vec1.z * vec2.z); + } + + public static float angle(AMVector3 vec1, AMVector3 vec2) + { + return anglePreNorm(vec1.copy().normalize(), vec2.copy().normalize()); + } + + public static float anglePreNorm(AMVector3 vec1, AMVector3 vec2) + { + return (float)Math.acos(dotProduct(vec1, vec2)); + } + + public static AMVector3 zero(){ + return new AMVector3(0,0,0); + } + + public AMVector3 rotate(float angle, AMVector3 axis) + { + return AMMatrix4.rotationMat(angle, axis).translate(this); + } + + @Override + public String toString() + { + return "[" + this.x + "," + this.y + "," + this.z + "]"; + } + + public Vec3 toVec3D() + { + return Vec3.createVectorHelper(this.x, this.y, this.z); + } + + public static AMVector3 getPerpendicular(AMVector3 vec) + { + if (vec.z == 0.0F) { + return zCrossProduct(vec); + } + return xCrossProduct(vec); + } + + public boolean isZero() + { + return (this.x == 0.0F) && (this.y == 0.0F) && (this.z == 0.0F); + } + + public boolean isWithinRange(float min, float max) + { + return (this.x >= min && x <= max) && (this.y >= min && this.y <= max) && (this.z >= min && this.z <= max); + } + + public double distanceTo(AMVector3 target){ + double var2 = target.x - this.x; + double var4 = target.y - this.y; + double var6 = target.z - this.z; + return MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6); + } + + public double distanceSqTo(AMVector3 target){ + double var2 = target.x - this.x; + double var4 = target.y - this.y; + double var6 = target.z - this.z; + return var2 * var2 + var4 * var4 + var6 * var6; + } + + + /** + * Rounds all values in this Vector to their integral floors + */ + public void floorToI(){ + this.x = (float) Math.floor(this.x); + this.y = (float) Math.floor(this.y); + this.z = (float) Math.floor(this.z); + } + + /** + * Rounds all values in this Vector to their integral logical roundings + */ + public void roundToI(){ + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + } + + /** + * Rounds all values in this Vector to their integral ceilings + */ + public void ceilToI(){ + this.x = (float) Math.ceil(this.x); + this.y = (float) Math.ceil(this.y); + this.z = (float) Math.ceil(this.z); + } + + /** + * Writes the vector3 to the specified compound - note that the way this function works, only one vector3 can be written to a compound at a time. + * Use sub-compounds if you need more! + */ + public void writeToNBT(NBTTagCompound compound){ + compound.setFloat("Vec3_x", x); + compound.setFloat("Vec3_y", y); + compound.setFloat("Vec3_z", z); + } + + public static AMVector3 readFromNBT(NBTTagCompound compound){ + return new AMVector3(compound.getFloat("Vec3_x"), compound.getFloat("Vec3_y"), compound.getFloat("Vec3_z")); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AMVector3){ + AMVector3 comp = (AMVector3) obj; + return (comp.x == this.x && comp.y == this.y && comp.z == this.z); + } + return false; + } + + @Override + public int hashCode() { + return (int) (x + y + z); + } +} diff --git a/src/api/java/am2/api/particles/IBeamParticle.java b/src/api/java/am2/api/particles/IBeamParticle.java new file mode 100644 index 0000000..a821cec --- /dev/null +++ b/src/api/java/am2/api/particles/IBeamParticle.java @@ -0,0 +1,26 @@ +package am2.api.particles; + +public interface IBeamParticle { + /** + * Sets the beam type. Determines the texture of the beam. Valid types are 0-2. + */ + public void setType(int type); + /** + * Sets the color from a single integer. Good for hex colors. + */ + public void setRGBColor(int color); + /** + * Sets the beam color from 3 int values (0-255). + */ + public void setRGBColorI(int r, int g, int b); + /** + * Sets the beam color from 3 floating point values (0.0f - 1.0f) + */ + public void setRGBColorF(float r, float g, float b); + /** + * Indicates that this beam is being cast by a player that is in first person. Should only be called when creating a beam from the local player, if the player is in first person. + *
+ * This will offset the beam to make it look like it is coming from the player's active item and not their face. + */ + public void setFirstPersonPlayerCast(); +} diff --git a/src/api/java/am2/api/power/IObeliskFuelHelper.java b/src/api/java/am2/api/power/IObeliskFuelHelper.java new file mode 100644 index 0000000..01d3760 --- /dev/null +++ b/src/api/java/am2/api/power/IObeliskFuelHelper.java @@ -0,0 +1,16 @@ +package am2.api.power; + +import net.minecraft.item.ItemStack; + +public interface IObeliskFuelHelper { + /** + * Registers a new fuel type for the obelisk to burn + * @param stack The stack to use as a comparator (stackSize is ignored, just use 1) + * @param burnTime How long the obelisk should burn for when given one of these items + */ + public void registerFuelType(ItemStack stack, int burnTime); + /** + * Retrieves the burn time for the specified stack. Returns 0 if it is not a valid fuel. + */ + public int getFuelBurnTime(ItemStack stack); +} diff --git a/src/api/java/am2/api/power/IPowerNode.java b/src/api/java/am2/api/power/IPowerNode.java new file mode 100644 index 0000000..985564d --- /dev/null +++ b/src/api/java/am2/api/power/IPowerNode.java @@ -0,0 +1,54 @@ +package am2.api.power; +import net.minecraft.tileentity.TileEntity; + +/** + * + * @author Mithion + * This will eventually allow you to interface with the AM power network - currently it is not fully working. + */ +public interface IPowerNode { + + /** + * Gets the current capacity in the power block + */ + public float getCapacity(); + + /** + * Can this block provide power? + * @param type The power type we are checking for + */ + public boolean canProvidePower(PowerTypes type); + + /** + * Can this block relay power? + * @param type The type of power we are looking for + */ + public boolean canRelayPower(PowerTypes type); + + /** + * Can this block request power? + */ + public boolean canRequestPower(); + + /** + * Is this block a nexus? + */ + public boolean isSource(); + + /** + * How fast does this block charge? + */ + public int getChargeRate(); + + /** + * Gets the current power type of the block. + */ + public PowerTypes[] getValidPowerTypes(); + + /** + * Offset of any particle effects to the origin of the block + * @param axis The axis in question. 0=x, 1=y, 2=z + */ + public float particleOffset(int axis); + +} diff --git a/src/api/java/am2/api/power/PowerTypes.java b/src/api/java/am2/api/power/PowerTypes.java new file mode 100644 index 0000000..62dd4d5 --- /dev/null +++ b/src/api/java/am2/api/power/PowerTypes.java @@ -0,0 +1,69 @@ +package am2.api.power; + +import java.security.InvalidParameterException; +import java.util.ArrayList; + +import am2.api.ArsMagicaApi; +import cpw.mods.fml.common.FMLLog; + +public final class PowerTypes{ + + public static final PowerTypes NONE = new PowerTypes(0, "None", "\u00A7f"); + public static final PowerTypes LIGHT = new PowerTypes(1, "Light", "\u00A7b"); + public static final PowerTypes NEUTRAL = new PowerTypes(2, "Neutral", "\u00A71"); + public static final PowerTypes DARK = new PowerTypes(4, "Dark", "\u00A74"); + + private static final ArrayList allPowerTypes = new ArrayList() {{ + add(LIGHT); + add(NEUTRAL); + add(DARK); + }}; + + private int _id; + private String _name; + private String _chatColor; + + private PowerTypes(int ID, String name, String chatColor){ + if ((ID & -ID) != ID){ + throw new InvalidParameterException(String.format("ID must be a bitflag that is a power of 2! (You used %d)", ID)); + } + _id = ID; + _name = name; + _chatColor = chatColor; + } + + public static void RegisterPowerType(int id, String name, String chatColor){ + if (getByID(id) == NONE){ + FMLLog.info("Ars Magica 2 >> Attempted to register power type %s with ID of %d, but that ID is already taken! The type was NOT registered!"); + }else{ + allPowerTypes.add(new PowerTypes(id, name, chatColor)); + FMLLog.info("Ars Magica 2 >> Registered new power type %s with ID %d", name, id); + } + } + + public int ID(){ + return _id; + } + + public String name(){ + return _name; + } + + public String chatColor(){ + if (ArsMagicaApi.instance.getColourblindMode()){ + return ""; + } + return _chatColor; + } + + public static PowerTypes[] all(){ + return allPowerTypes.toArray(new PowerTypes[allPowerTypes.size()]); + } + + public static PowerTypes getByID(int id){ + for (PowerTypes type : all()) + if (type.ID() == id) + return type; + return NONE; + } +} diff --git a/src/api/java/am2/api/spell/ISkillTreeManager.java b/src/api/java/am2/api/spell/ISkillTreeManager.java new file mode 100644 index 0000000..00ed0c6 --- /dev/null +++ b/src/api/java/am2/api/spell/ISkillTreeManager.java @@ -0,0 +1,19 @@ +package am2.api.spell; + +import am2.api.spell.component.interfaces.ISkillTreeEntry; +import am2.api.spell.enums.SkillPointTypes; +import am2.api.spell.enums.SkillTrees; + +public interface ISkillTreeManager { + /** + * Registers a spell part into the skill tree (where it can be unlocked). + * Pass a null prerequisite for no prerequisite. + * Throws an exception if the prerequisite passed in is not a registered entry in the skill tree, or if it is in a different tree. + * @param shape The shape to register + * @param x The x-coordinate in the skill tree to display the shape IIcon + * @param y The y-coordinate in the skill tree to display the shape IIcon + * @param tree The skill tree to register the shape into + * @param prerequisites The prerequisite skills needed for the shape. + */ + public void RegisterPart(ISkillTreeEntry part, int x, int y, SkillTrees tree, SkillPointTypes requiredPoint, ISkillTreeEntry ... prerequisites); +} diff --git a/src/api/java/am2/api/spell/ISpellIconManager.java b/src/api/java/am2/api/spell/ISpellIconManager.java new file mode 100644 index 0000000..b0c86b7 --- /dev/null +++ b/src/api/java/am2/api/spell/ISpellIconManager.java @@ -0,0 +1,20 @@ +package am2.api.spell; + +import net.minecraft.util.IIcon; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public interface ISpellIconManager { + /** + * Returns the IIcon registered to the specified spell name. Returns the missing IIcon if one doesn't exist. + */ + public IIcon getIcon(String spellName); + + /** + * Registers an IIcon to be associated with a spell component + * @param spellName The unlocalized name of the spell used when it was registered + * @param IIcon The IIcon of the spell + */ + public void registerIcon(String spellName, IIcon IIcon); +} diff --git a/src/api/java/am2/api/spell/ISpellModifierManager.java b/src/api/java/am2/api/spell/ISpellModifierManager.java new file mode 100644 index 0000000..137a2e8 --- /dev/null +++ b/src/api/java/am2/api/spell/ISpellModifierManager.java @@ -0,0 +1,8 @@ +package am2.api.spell; + +import am2.api.spell.component.interfaces.ISpellModifier; + +public interface ISpellModifierManager { + public int registerSpellModifier(ISpellModifier modifier, String modifierName); + public ISpellModifier getSpellModifier(int modifierID); +} diff --git a/src/api/java/am2/api/spell/ISpellPartManager.java b/src/api/java/am2/api/spell/ISpellPartManager.java new file mode 100644 index 0000000..3b7acdb --- /dev/null +++ b/src/api/java/am2/api/spell/ISpellPartManager.java @@ -0,0 +1,27 @@ +package am2.api.spell; + +import am2.api.spell.component.interfaces.ISkillTreeEntry; + +public interface ISpellPartManager { + /** + * Registers the skill tree entry into the skill manager. + * @param component The skill tree entry to register + * @param name The unlocalized name you want to register it to. Local translations are am2.spell.unlocalized_name, so register this into the language registry for localization. + * @return The shifted numeric ID that is used, this should be stored somewhere + */ + public int registerSkillTreeEntry(ISkillTreeEntry component, String name); + + /** + * + * @param ID The shifted ID of the skill. + * @return The skill tree entry or null if not found. + */ + public ISkillTreeEntry getSkill(int ID); + + /** + * + * @param name The unlocalized name of the skill + * @return The skill tree entry or null if not found. + */ + public ISkillTreeEntry getSkill(String name); +} diff --git a/src/api/java/am2/api/spell/ISpellShapeManager.java b/src/api/java/am2/api/spell/ISpellShapeManager.java new file mode 100644 index 0000000..86c1108 --- /dev/null +++ b/src/api/java/am2/api/spell/ISpellShapeManager.java @@ -0,0 +1,8 @@ +package am2.api.spell; + +import am2.api.spell.component.interfaces.ISpellShape; + +public interface ISpellShapeManager { + public int registerSpellShape(ISpellShape shape, String shapeName); + public ISpellShape getSpellShape(int shapeID); +} diff --git a/src/api/java/am2/api/spell/ItemSpellBase.java b/src/api/java/am2/api/spell/ItemSpellBase.java new file mode 100644 index 0000000..09b7b5a --- /dev/null +++ b/src/api/java/am2/api/spell/ItemSpellBase.java @@ -0,0 +1,28 @@ +package am2.api.spell; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.Item; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; + +/** + * This is just here for reference - you shouldn't have any need to inherit from this item. To add new parts to spells, inherit from ISpellShape, ISpellModifier, or ISpellComponent. + * @author Mithion + * + */ +public abstract class ItemSpellBase extends Item{ + public ItemSpellBase() { + super(); + } + + /** + * Specific version of getMovingObjectPosition that takes into account the targeting types that I need + * @param caster The caster of the spell + * @param world The world the spell is being cast in + * @param range The range to raycast + * @param targetEntities Stop at collision with entities + * @param targetWater Stop at collision with any non-solid block + * @return A MovingObjectPosition instance if a collision was found, null otherwise + */ + public abstract MovingObjectPosition getMovingObjectPosition(EntityLivingBase caster, World world, double range, boolean targetEntities, boolean targetWater); +} diff --git a/src/api/java/am2/api/spell/component/interfaces/IRitualInteraction.java b/src/api/java/am2/api/spell/component/interfaces/IRitualInteraction.java new file mode 100644 index 0000000..096c25b --- /dev/null +++ b/src/api/java/am2/api/spell/component/interfaces/IRitualInteraction.java @@ -0,0 +1,23 @@ +package am2.api.spell.component.interfaces; + +import net.minecraft.item.ItemStack; +import am2.api.blocks.MultiblockStructureDefinition; + +public interface IRitualInteraction { + /** + * Gets a MultiblockStructureDefinition outlining the ritual blocks needed and where they should be relative to a given location. + * This should be instantiated on mod load and cached somewhere, and NOT instantiated upon request. + */ + public MultiblockStructureDefinition getRitualShape(); + + /** + * Gets a list of items that need to be present in {@link #getReagentSearchRadius() getReagentSearchRadius()} for the ritual to match. + * Items on the ground as well as items attached to Wizard's Chalk are included. + */ + public ItemStack[] getReagents(); + + /** + * Gets the radius to search for reagents when checking the ritual. + */ + public int getReagentSearchRadius(); +} diff --git a/src/api/java/am2/api/spell/component/interfaces/ISkillTreeEntry.java b/src/api/java/am2/api/spell/component/interfaces/ISkillTreeEntry.java new file mode 100644 index 0000000..36dcb55 --- /dev/null +++ b/src/api/java/am2/api/spell/component/interfaces/ISkillTreeEntry.java @@ -0,0 +1,9 @@ +package am2.api.spell.component.interfaces; + +public interface ISkillTreeEntry { + /** + * Gets the ID of the skill. Must be unique among all other skills. + * @return The ID of the part. + */ + public int getID(); +} diff --git a/src/api/java/am2/api/spell/component/interfaces/ISpellComponent.java b/src/api/java/am2/api/spell/component/interfaces/ISpellComponent.java new file mode 100644 index 0000000..b35d577 --- /dev/null +++ b/src/api/java/am2/api/spell/component/interfaces/ISpellComponent.java @@ -0,0 +1,72 @@ +package am2.api.spell.component.interfaces; + +import java.util.EnumSet; +import java.util.Random; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import am2.api.spell.enums.Affinity; + +public interface ISpellComponent extends ISpellPart{ + /** + * Apply the effect to a single block + * @param stack The item stack that contains the effect data + * @param world The world the effect is in + * @param blockx The x coordinate of the block + * @param blocky The y coordinate of the block + * @param blockz The z coordinate of the block + * @param blockFace The face of the block that was targeted + * @param impactX The x coordinate of the impact + * @param impactY The y coordinate of the impact + * @param impactZ The z coordinate of the impact + * @param caster The caster of the spell + * @return True if the effect was successfully applied to the block + */ + public boolean applyEffectBlock(ItemStack stack, World world, int blockx, int blocky, int blockz, int blockFace, double impactX, double impactY, double impactZ, EntityLivingBase caster); + + /** + * Apply the effect to a single entity + * @param stack The stack representing the spell + * @param world The world the spell was cast in + * @param caster The caster of the spell + * @param target The current target of the spell + * @return True if the effect was applied successfully to the entity + */ + public boolean applyEffectEntity(ItemStack stack, World world, EntityLivingBase caster, Entity target); + + /** + * Gets the mana cost of the spell + */ + public float manaCost(EntityLivingBase caster); + + /** + * Gets the burnout of the spell + */ + public float burnout(EntityLivingBase caster); + + /** + * Gets any reagents that must be present in the caster's inventory in order + * to cast the spell. + */ + public ItemStack[] reagents(EntityLivingBase caster); + + /** + * Spawn visual effects for the component + * @param colorModifier The color from the color modifier. -1 if missing. + */ + public void spawnParticles(World world, double x, double y, double z, EntityLivingBase caster, Entity target, Random rand, int colorModifier); + + /** + * Gets the affinity of the spell + */ + public EnumSet getAffinity(); + + /** + * Gets the amount (before diminishing returns) that this component, when successfully applied, + * shifts the caster's affinity + * @param affinity The affinity being shifted + */ + public float getAffinityShift(Affinity affinity); +} diff --git a/src/api/java/am2/api/spell/component/interfaces/ISpellModifier.java b/src/api/java/am2/api/spell/component/interfaces/ISpellModifier.java new file mode 100644 index 0000000..0aa0e90 --- /dev/null +++ b/src/api/java/am2/api/spell/component/interfaces/ISpellModifier.java @@ -0,0 +1,43 @@ +package am2.api.spell.component.interfaces; + +import java.util.EnumSet; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import am2.api.spell.enums.SpellModifiers; + +public interface ISpellModifier extends ISpellPart{ + /** + * Returns a list of the aspects of a spell that this modifier can change. + * @return + */ + public EnumSet getAspectsModified(); + + /** + * Returns the modified value for the specified type. + * @param type The type of value we are modifying + * @param caster The caster + * @param target The target (can be the same as the caster) + * @param world The world in which the spell is being cast. + * @param metadata Any metadata written to the spell for this modifier (obtained from getModifierMetadata) + * @return A factor to multiply the default value by (or add, depending on the component's programming) + */ + public float getModifier(SpellModifiers type, EntityLivingBase caster, Entity target, World world, byte[] metadata); + + /** + * Gets the amount that adding this modifier to the spell alters the mana cost. + * @param spellStack The itemstack comprising the spell (in case you want to base it on other modifiers added) + * @param stage The stage in which this modifier has been added (if the modifier is added to multiple stages, this will be called multiple times, once per stage) + * @param quantity The quantity of this multiplier in the specified stage. + */ + public float getManaCostMultiplier(ItemStack spellStack, int stage, int quantity); + + /** + * Gets any metadata needed by this modifier for the current spell. Used, for example, in the color modifier to determine what color was specified. + * @param stage The stage this modifier is at + * @param matchedRecipe The items that were added to the crafting altar which resulted in the matching of the recipe. + */ + public byte[] getModifierMetadata(int stage, ItemStack[] matchedRecipe); +} diff --git a/src/api/java/am2/api/spell/component/interfaces/ISpellPart.java b/src/api/java/am2/api/spell/component/interfaces/ISpellPart.java new file mode 100644 index 0000000..b276755 --- /dev/null +++ b/src/api/java/am2/api/spell/component/interfaces/ISpellPart.java @@ -0,0 +1,28 @@ +package am2.api.spell.component.interfaces; + +/** + * Identifies that this object is either a spell component, a spell modifier, or a spell shape. + * Do not inherit this directly unless you are adding talents and such, rather inherit ISpellComponent, ISpellModifier, or ISpellShape for spell parts. + * @author Mithion + * + */ +public interface ISpellPart extends ISkillTreeEntry { + + /** + * recipe items, in order, that need to be thrown into the crafting altar in order to create the item. + *
+ * Use Items for items, Blocks for blocks, Strings for OreDictionary items, and E:[type flag] followed by an integer for essence amounts. + *
+ * Use itemstacks for items/blocks/oredict when meta is required. By default it is meta 0. Quantity (stack size) is ignored. + *
+ * Integer pairs represent the type (*=any, 1=neutral, 2=light, 4=dark, etc.), and the quantity of essence required. The type can be used as flags, + *
+ * For example: + *
+	 *     new Object[]{ "E:1|2", 1500 } //require 1500 of neutral or 1500 of light power.
+	 *     new Object[]{ "E:*", 1500 } //require 1500 of any kind of power
+	 *     etc.
+	 *
+ */ + public Object[] getRecipeItems(); +} diff --git a/src/api/java/am2/api/spell/component/interfaces/ISpellShape.java b/src/api/java/am2/api/spell/component/interfaces/ISpellShape.java new file mode 100644 index 0000000..9ad24ec --- /dev/null +++ b/src/api/java/am2/api/spell/component/interfaces/ISpellShape.java @@ -0,0 +1,54 @@ +package am2.api.spell.component.interfaces; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import am2.api.spell.ItemSpellBase; +import am2.api.spell.enums.Affinity; +import am2.api.spell.enums.SpellCastResult; + +public interface ISpellShape extends ISpellPart { + /** + * Creates the target area/entity list and applies the effects to ground/mobs + * @param item The spell being cast + * @param stack The itemstack representing the spell + * @param caster The caster of the spell + * @param target The specified target of the spell. If this is not NULL, this is a forced target, and should be included with any other targets of the shape. Otherwise the default spell shape logic should apply. + * @param world The world the spell is being cast in + * @param x The x-coordinate of the spell's effect + * @param y The y-coordinate of the spell's effect + * @param z The z-coordinate of the spell's effect + * @param side The side the spell is applied on + * @param giveXP This is passed along to be given back to the SpellHelper where needed. + * @param useCount The number of ticks the spell item has been in use for + * @return The result of the spell cast. + */ + public SpellCastResult beginStackStage(ItemSpellBase item, ItemStack stack, EntityLivingBase caster, EntityLivingBase target, World world, double x, double y, double z, int side, boolean giveXP, int useCount); + + /** + * Is this shape a valid shape for a channeled/maintained spell? + */ + public boolean isChanneled(); + + /** + * Allows different shapes to vary the mana cost of a spell + * @param spellStack the itemstack representing the spell (useful if you want to vary based on added modifiers as well, for example) + * @return + */ + public float manaCostMultiplier(ItemStack spellStack); + + /** + * Is the spell a terminus shape? Return true if this component does not continue the spell chain when proccing. + */ + public boolean isTerminusShape(); + + /** + * Is the shape a principal shape? Return true if this spell requires another shape to proc (like runes and zones) + */ + public boolean isPrincipumShape(); + + /** + * Play the sound for the specified affinity + */ + public String getSoundForAffinity(Affinity affinity, ItemStack stack, World world); +} diff --git a/src/api/java/am2/api/spell/enums/Affinity.java b/src/api/java/am2/api/spell/enums/Affinity.java new file mode 100644 index 0000000..0acef4d --- /dev/null +++ b/src/api/java/am2/api/spell/enums/Affinity.java @@ -0,0 +1,193 @@ +package am2.api.spell.enums; + +import net.minecraft.item.Item; + +public enum Affinity { + NONE(0, + 0xFFFFFF, + -1, //no direct opposite + new int[] {}, //no major opposites + new int[] {}, //no minor opposites + new int[] {}), + + ARCANE(1, + 0xb935cd, + 9, //nature is direct opposite + new int[] { 9, 4, 2, 7 }, //Major Opposites: life, earth, water, ice + new int[] { 5, 10 }, //Minor Opposites: Air, Ender + new int[] { 6, 3 }), //Adjacent Affinities: Lightning, Fire + + WATER(2, + 0x0b5cef, + 3, //fire is direct opposite + new int[] { 7, 4, 1, 10 }, //Major Opposites: lightning, earth, arcane, ender + new int[] { 5, 7 }, //Minor Opposites: Air, Ice + new int[] { 9, 8 }), //Adjacent Affinities: Life, Nature + + FIRE(3, + 0xef260b, + 2, //water is direct opposite + new int[] { 5, 7, 8, 9 }, //Major Opposites: air, ice, nature, life + new int[] { 4, 6 }, //Minor Opposites: Earth, Lightning + new int[] { 10, 1 }), //Adjacent Affinities: Ender, Arcane + + EARTH(4, + 0x61330b, + 5, //air is direct opposite + new int[] { 2, 1, 9, 6 }, //Major Opposites: water, arcane, life, lightning + new int[] { 8, 3 }, //Minor Opposites: Nature, Fire + new int[] { 7, 10 }), //Adjacent Affinities: Ice, Ender + + AIR(5, + 0x777777, + 4, //earth is direct opposite + new int[] { 8, 3, 7, 10 }, //Major Opposites: nature, fire, ice, ender + new int[] { 2, 1 }, //Minor Opposites: Water, Arcane + new int[] { 9, 6 }), //Adjacent Affinities: Life, Lightning + + LIGHTNING(6, + 0xdece19, + 7, //ice is direct opposite + new int[] { 2, 10, 8, 4 }, //Major Opposites: water, ender, nature, earth + new int[] { 9, 3 }, //Minor Opposites: Life, Fire + new int[] { 5, 1 }), //Adjacent Affinities: Air, Arcane + + ICE(7, + 0xd3e8fc, + 6, //lightning is direct opposite + new int[] { 9, 3, 5, 1 }, //Major Opposites: life, fire, air, arcane + new int[] { 2, 10 }, //Minor Opposites: Water, Ender + new int[] { 8, 4 }), //Adjacent Affinities: Nature, Earth + + NATURE(8, + 0x228718, + 6, //arcane is direct opposite + new int[] { 5, 10, 6, 3 }, //Major Opposites: air, ender, lightning, fire + new int[] { 9, 4 }, //Minor Opposites: Life, Earth + new int[] { 2, 7 }), //Adjacent Affinities: Water, Ice + + LIFE(9, + 0x34e122, + 10, //ender is direct opposite + new int[] { 1, 7, 3, 4 }, //Major Opposites: arcane, ice, fire, earth + new int[] { 8, 6 }, //Minor Opposites: Nature, Lightning + new int[] { 2, 5 }), //Adjacent Affinities: Water, Air + + ENDER(10, + 0x3f043d, + 9, //life is direct opposite + new int[] { 8, 6, 2, 5 }, //Major Opposites: nature, lightning, water, air + new int[] { 1, 7 }, //Minor Opposites: Arcane, Ice + new int[] { 4, 3 }); //Adjacent Affinities: Earth, Fire + + + public int ID; + private int directOpposingAffinity; + private int[] majorOppositions; + private int[] minorOppositions; + private int[] adjacentAffinities; + public Item representItem; + public int representMeta; + public final int color; + + private Affinity(int ID, int color, int directOppositeAffinity, int[] majorOppositions, int[] minorOppositions, int[] adjacentAffinities){ + this.ID = ID; + this.directOpposingAffinity = directOppositeAffinity; + this.majorOppositions = majorOppositions; + this.minorOppositions = minorOppositions; + this.adjacentAffinities = adjacentAffinities; + this.color = color; + } + + public Affinity getOpposingAffinity(){ + if (this.directOpposingAffinity > -1) + return Affinity.values()[this.directOpposingAffinity]; + return Affinity.NONE; + } + + public Affinity[] getMajorOpposingAffinities(){ + Affinity[] opposing = new Affinity[this.majorOppositions.length]; + int count = 0; + for (int i : this.majorOppositions){ + opposing[count++] = Affinity.values()[i]; + } + return opposing; + } + + public Affinity[] getMinorOpposingAffinities(){ + Affinity[] opposing = new Affinity[this.minorOppositions.length]; + int count = 0; + for (int i : this.minorOppositions){ + opposing[count++] = Affinity.values()[i]; + } + return opposing; + } + + public Affinity[] getAdjacentAffinities(){ + Affinity[] adjacent = new Affinity[this.adjacentAffinities.length]; + int count = 0; + for (int i : this.adjacentAffinities){ + adjacent[count++] = Affinity.values()[i]; + } + return adjacent; + } + + public void setRepresentItem(Item representItem, int meta){ + if (this.representItem == null){ + this.representItem = representItem; + this.representMeta = meta; + } + } + + public static Affinity getByID(int ID){ + for (Affinity affinity : Affinity.values()){ + if (affinity.ID == ID){ + return affinity; + } + } + return Affinity.NONE; + } + + public static Affinity[] getOrderedAffinities(){ + return new Affinity[]{ + AIR, + LIGHTNING, + ARCANE, + FIRE, + ENDER, + EARTH, + ICE, + NATURE, + WATER, + LIFE + }; + } + + public int getAffinityMask(){ + switch (this){ + case AIR: + return 0x1; + case ARCANE: + return 0x2; + case EARTH: + return 0x4; + case ENDER: + return 0x8; + case FIRE: + return 0x10; + case ICE: + return 0x20; + case LIFE: + return 0x40; + case LIGHTNING: + return 0x80; + case NATURE: + return 0x100; + case WATER: + return 0x200; + case NONE: + default: + return 0; + } + } +} diff --git a/src/api/java/am2/api/spell/enums/BuffPowerLevel.java b/src/api/java/am2/api/spell/enums/BuffPowerLevel.java new file mode 100644 index 0000000..71f098b --- /dev/null +++ b/src/api/java/am2/api/spell/enums/BuffPowerLevel.java @@ -0,0 +1,7 @@ +package am2.api.spell.enums; + +public class BuffPowerLevel { + public static final int Low = 0; + public static final int Medium = 1; + public static final int High = 2; +} diff --git a/src/api/java/am2/api/spell/enums/ContingencyTypes.java b/src/api/java/am2/api/spell/enums/ContingencyTypes.java new file mode 100644 index 0000000..60bdc67 --- /dev/null +++ b/src/api/java/am2/api/spell/enums/ContingencyTypes.java @@ -0,0 +1,10 @@ +package am2.api.spell.enums; + +public enum ContingencyTypes { + NONE, + FALL, + DAMAGE_TAKEN, + ON_FIRE, + HEALTH_LOW, + DEATH +} diff --git a/src/api/java/am2/api/spell/enums/LearnStates.java b/src/api/java/am2/api/spell/enums/LearnStates.java new file mode 100644 index 0000000..2685501 --- /dev/null +++ b/src/api/java/am2/api/spell/enums/LearnStates.java @@ -0,0 +1,9 @@ +package am2.api.spell.enums; + +public enum LearnStates{ + LEARNED, + CAN_LEARN, + CANNOT_LEARN, + LOCKED, + DISABLED +}; \ No newline at end of file diff --git a/src/api/java/am2/api/spell/enums/SkillPointTypes.java b/src/api/java/am2/api/spell/enums/SkillPointTypes.java new file mode 100644 index 0000000..6174c0d --- /dev/null +++ b/src/api/java/am2/api/spell/enums/SkillPointTypes.java @@ -0,0 +1,8 @@ +package am2.api.spell.enums; + +public enum SkillPointTypes{ + BLUE, + GREEN, + RED, + SILVER +} diff --git a/src/api/java/am2/api/spell/enums/SkillTrees.java b/src/api/java/am2/api/spell/enums/SkillTrees.java new file mode 100644 index 0000000..1dbbcfa --- /dev/null +++ b/src/api/java/am2/api/spell/enums/SkillTrees.java @@ -0,0 +1,11 @@ +package am2.api.spell.enums; + +public enum SkillTrees { + None, + Offense, + Defense, + Utility, + Talents, + Familiar, + Affinity +} diff --git a/src/api/java/am2/api/spell/enums/SpellCastResult.java b/src/api/java/am2/api/spell/enums/SpellCastResult.java new file mode 100644 index 0000000..cbfe3a5 --- /dev/null +++ b/src/api/java/am2/api/spell/enums/SpellCastResult.java @@ -0,0 +1,11 @@ +package am2.api.spell.enums; + +public enum SpellCastResult { + SUCCESS, + NOT_ENOUGH_MANA, + REAGENTS_MISSING, + MALFORMED_SPELL_STACK, + EFFECT_FAILED, + SUCCESS_REDUCE_MANA, + SILENCED +} diff --git a/src/api/java/am2/api/spell/enums/SpellModifiers.java b/src/api/java/am2/api/spell/enums/SpellModifiers.java new file mode 100644 index 0000000..ac6b34c --- /dev/null +++ b/src/api/java/am2/api/spell/enums/SpellModifiers.java @@ -0,0 +1,30 @@ +package am2.api.spell.enums; + +public enum SpellModifiers { + SPEED(1.0D), + GRAVITY(0), + BOUNCE(0), + DAMAGE(4.0D), + HEALING(1.0D), + VELOCITY_ADDED(0.0D), + RADIUS(1.0D), + DURATION(1.0D), + PROCS(1), + RANGE(8.0D), + TARGET_NONSOLID_BLOCKS(0), + PIERCING(2), + COLOR(0xFFFFFF), + MINING_POWER(1), + FORTUNE_LEVEL(1), + SILKTOUCH_LEVEL(1), + DISMEMBERING_LEVEL(1), + BUFF_POWER(1); + + public double defaultValue = 0D; + public int defaultValueInt = 0; + + private SpellModifiers(double defaultValue){ + this.defaultValue = defaultValue; + this.defaultValueInt = (int)defaultValue; + } +} 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/ThaumcraftApi.java b/src/api/java/thaumcraft/api/ThaumcraftApi.java index bbd7a43..0d0a672 100644 --- a/src/api/java/thaumcraft/api/ThaumcraftApi.java +++ b/src/api/java/thaumcraft/api/ThaumcraftApi.java @@ -423,7 +423,8 @@ public class ThaumcraftApi { private static HashMap warpMap = new HashMap(); /** - * This method is used to determine how much warp is gained if the item is crafted + * 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 */ @@ -432,7 +433,7 @@ public class ThaumcraftApi { } /** - * This method is used to determine how much warp is gained if the sent item is crafted + * 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 */ diff --git a/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java b/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java index 7f95dc4..8487a20 100644 --- a/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java +++ b/src/api/java/thaumcraft/api/ThaumcraftApiHelper.java @@ -2,6 +2,7 @@ package thaumcraft.api; import java.lang.reflect.Method; import java.util.HashMap; +import java.util.Iterator; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; @@ -133,6 +134,29 @@ public class ThaumcraftApiHelper { } 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) { @@ -272,10 +296,8 @@ public class ThaumcraftApiHelper { /** * 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 * @param amount how much warp to add. Negative amounts are only valid for temporary warp * @param temporary add temporary warp instead of permanent - * @param amount how much warp to add */ public static void addWarpToPlayer(EntityPlayer player, int amount, boolean temporary) { boolean ot = false; @@ -290,4 +312,25 @@ public class ThaumcraftApiHelper { FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.Thaumcraft method addWarpToPlayer"); } } + + static Method addStickyWarpToPlayer; + /** + * 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) { + boolean ot = false; + try { + if(addStickyWarpToPlayer == null) { + Class fake = Class.forName("thaumcraft.common.Thaumcraft"); + addStickyWarpToPlayer = fake.getMethod("addStickyWarpToPlayer", + EntityPlayer.class, int.class); + } + addStickyWarpToPlayer.invoke(null, player, amount); + } catch(Exception ex) { + FMLLog.warning("[Thaumcraft API] Could not invoke thaumcraft.common.Thaumcraft method addStickyWarpToPlayer"); + } + } } diff --git a/src/api/java/thaumcraft/api/aspects/AspectList.java b/src/api/java/thaumcraft/api/aspects/AspectList.java index 6b9dfce..6fcfe98 100644 --- a/src/api/java/thaumcraft/api/aspects/AspectList.java +++ b/src/api/java/thaumcraft/api/aspects/AspectList.java @@ -233,6 +233,19 @@ public class AspectList implements Serializable { } } + 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 @@ -251,6 +264,17 @@ public class AspectList implements Serializable { } } - + 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/crafting/CrucibleRecipe.java b/src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java index 5fa968c..595b6e5 100644 --- a/src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java +++ b/src/api/java/thaumcraft/api/crafting/CrucibleRecipe.java @@ -30,7 +30,15 @@ public class CrucibleRecipe { for (Aspect tag:tags.getAspects()) { hc += tag.getTag()+tags.getAmount(tag); } - hc += cat.hashCode(); + if (cat instanceof ItemStack) { + hc += ((ItemStack)cat).toString(); + } else + if (cat instanceof ArrayList && ((ArrayList)catalyst).size()>0) { + for (ItemStack is :(ArrayList)catalyst) { + hc += is.toString(); + } + } + hash = hc.hashCode(); } @@ -69,7 +77,6 @@ public class CrucibleRecipe { for (Aspect tag:aspects.getAspects()) { temptags.remove(tag, aspects.getAmount(tag)); -// if (!temptags.remove(tag, aspects.getAmount(tag))) return null; } itags = temptags; @@ -80,24 +87,5 @@ public class CrucibleRecipe { return recipeOutput; } - -// @Override -// public int hashCode() { -// String hash = ""; -// if (catalyst instanceof ItemStack) { -// hash += ((ItemStack)catalyst).toString(); -// } else if (catalyst instanceof ArrayList && ((ArrayList)catalyst).size()>0) { -// for (ItemStack s:(ArrayList)catalyst) { -// hash += s.toString(); -// } -// } else { -// hash += catalyst.hashCode(); -// } -// hash += getRecipeOutput().toString(); -// for (Aspect a:aspects.getAspectsSorted()) { -// hash += a.getTag() + aspects.getAmount(a); -// } -// return hash.hashCode(); -// } } diff --git a/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java b/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java index 6fb4d63..773da34 100644 --- a/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java +++ b/src/api/java/thaumcraft/api/crafting/InfusionEnchantmentRecipe.java @@ -88,14 +88,14 @@ public class InfusionEnchantmentRecipe return ii.size()==0?true:false; } - private boolean areItemStacksEqual(ItemStack stack0, ItemStack stack1, boolean fuzzy) + 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=false; + boolean t1=ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(stack0, stack1); + if (!t1) return false; if (fuzzy) { - t1=true; int od = OreDictionary.getOreID(stack0); if (od!=-1) { ItemStack[] ores = OreDictionary.getOres(od).toArray(new ItemStack[]{}); @@ -103,9 +103,7 @@ public class InfusionEnchantmentRecipe return true; } } - else - t1=ItemStack.areItemStackTagsEqual(stack0, stack1); - return stack0.getItem() != stack1.getItem() ? false : (stack0.getItemDamage() != stack1.getItemDamage() ? false : (stack0.stackSize > stack0.getMaxStackSize() ? false : t1)); + return stack0.getItem() != stack1.getItem() ? false : (stack0.getItemDamage() != stack1.getItemDamage() ? false : stack0.stackSize <= stack0.getMaxStackSize() ); } diff --git a/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java b/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java index fef0a34..491db3d 100644 --- a/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java +++ b/src/api/java/thaumcraft/api/crafting/InfusionRecipe.java @@ -74,9 +74,9 @@ public class InfusionRecipe if (stack0==null && stack1!=null) return false; if (stack0!=null && stack1==null) return false; if (stack0==null && stack1==null) return true; - boolean t1=false; + boolean t1=ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(stack0, stack1); + if (!t1) return false; if (fuzzy) { - t1=true; int od = OreDictionary.getOreID(stack0); if (od!=-1) { ItemStack[] ores = OreDictionary.getOres(od).toArray(new ItemStack[]{}); @@ -84,12 +84,9 @@ public class InfusionRecipe return true; } } - else - t1=ItemStack.areItemStackTagsEqual(stack0, stack1); - return stack0.getItem() != stack1.getItem() ? false : (stack0.getItemDamage() != stack1.getItemDamage() ? false : (stack0.stackSize > stack0.getMaxStackSize() ? false : t1)); + return stack0.getItem() != stack1.getItem() ? false : (stack0.getItemDamage() != stack1.getItemDamage() ? false : stack0.stackSize <= stack0.getMaxStackSize() ); } - - + public Object getRecipeOutput() { return getRecipeOutput(this.getRecipeInput()); } diff --git a/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java b/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java index 40c7bc2..1490110 100644 --- a/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java +++ b/src/api/java/thaumcraft/api/crafting/ShapedArcaneRecipe.java @@ -224,7 +224,7 @@ public class ShapedArcaneRecipe implements IArcaneRecipe return false; } return (target.getItem() == input.getItem() && - (!target.hasTagCompound() || ItemStack.areItemStackTagsEqual(target, input)) && + (!target.hasTagCompound() || ThaumcraftApiHelper.areItemStackTagsEqualForCrafting(input,target)) && (target.getItemDamage() == OreDictionary.WILDCARD_VALUE|| target.getItemDamage() == input.getItemDamage())); } diff --git a/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java b/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java index 3d4ed50..3b1eaeb 100644 --- a/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java +++ b/src/api/java/thaumcraft/api/crafting/ShapelessArcaneRecipe.java @@ -125,9 +125,13 @@ public class ShapelessArcaneRecipe implements IArcaneRecipe private boolean checkItemEquals(ItemStack target, ItemStack input) { - return (target.getItem() == input.getItem() && - (!target.hasTagCompound() || ItemStack.areItemStackTagsEqual(target, input)) && - (target.getItemDamage() == OreDictionary.WILDCARD_VALUE || target.getItemDamage() == input.getItemDamage())); + 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())); } /** diff --git a/src/api/java/vazkii/botania/api/BotaniaAPI.java b/src/api/java/vazkii/botania/api/BotaniaAPI.java index 5a7b141..b858795 100644 --- a/src/api/java/vazkii/botania/api/BotaniaAPI.java +++ b/src/api/java/vazkii/botania/api/BotaniaAPI.java @@ -40,6 +40,11 @@ import vazkii.botania.api.recipe.RecipeManaInfusion; import vazkii.botania.api.recipe.RecipePetals; import vazkii.botania.api.recipe.RecipeRuneAltar; import vazkii.botania.api.subtile.SubTileEntity; +import vazkii.botania.api.subtile.signature.BasicSignature; +import vazkii.botania.api.subtile.signature.SubTileSignature; +import vazkii.botania.api.wiki.IWikiProvider; +import vazkii.botania.api.wiki.SimpleWikiProvider; +import vazkii.botania.api.wiki.WikiHooks; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; @@ -57,6 +62,7 @@ public final class BotaniaAPI { public static List elvenTradeRecipes = new ArrayList(); private static BiMap> subTiles = HashBiMap.> create(); + private static Map, SubTileSignature> subTileSignatures = new HashMap, SubTileSignature>(); public static Set subtilesForCreativeMenu = new LinkedHashSet(); public static Map oreWeights = new HashMap(); @@ -130,6 +136,34 @@ public final class BotaniaAPI { addSeed(Items.nether_wart, Blocks.nether_wart); addSeed(Items.pumpkin_seeds, Blocks.pumpkin_stem); addSeed(Items.melon_seeds, Blocks.melon_stem); + + registerModWiki("Minecraft", new SimpleWikiProvider("Minecraft Wiki", "http://minecraft.gamepedia.com/%s")); + + IWikiProvider technicWiki = new SimpleWikiProvider("Technic Wiki", "http://wiki.technicpack.net/%s"); + IWikiProvider mekanismWiki = new SimpleWikiProvider("Mekanism Wiki", "http://wiki.aidancbrady.com/wiki/%s"); + IWikiProvider buildcraftWiki = new SimpleWikiProvider("BuildCraft Wiki", "http://www.mod-buildcraft.com/wiki/doku.php?id=%s"); + + registerModWiki("Mekanism", mekanismWiki); + registerModWiki("MekanismGenerators", mekanismWiki); + registerModWiki("MekanismTools", mekanismWiki); + registerModWiki("EnderIO", new SimpleWikiProvider("EnderIO Wiki", "http://wiki.enderio.com/%s")); + registerModWiki("TropiCraft", new SimpleWikiProvider("Tropicraft Wiki", "http://wiki.tropicraft.net/wiki/%s")); + registerModWiki("RandomThings", new SimpleWikiProvider("Random Things Wiki", "http://randomthingsminecraftmod.wikispaces.com/%s")); + registerModWiki("Witchery", new SimpleWikiProvider("Witchery Wiki", "https://sites.google.com/site/witcherymod/%s", "-")); + registerModWiki("AppliedEnergistics2", new SimpleWikiProvider("AE2 Wiki", "http://ae-mod.info/%s")); + registerModWiki("BigReactors", technicWiki); + registerModWiki("BuildCraft|Core", buildcraftWiki); + registerModWiki("BuildCraft|Builders", buildcraftWiki); + registerModWiki("BuildCraft|Energy", buildcraftWiki); + registerModWiki("BuildCraft|Factory", buildcraftWiki); + registerModWiki("BuildCraft|Silicon", buildcraftWiki); + registerModWiki("BuildCraft|Transport", buildcraftWiki); + registerModWiki("ArsMagica2", new SimpleWikiProvider("ArsMagica2 Wiki", "http://wiki.arsmagicamod.com/wiki/%s")); + registerModWiki("PneumaticCraft", new SimpleWikiProvider("PneumaticCraft Wiki", "http://www.minemaarten.com/wikis/pneumaticcraft-wiki/pneumaticcraft-wiki-%s")); + registerModWiki("StevesCarts2", new SimpleWikiProvider("Steve's Carts Wiki", "http://stevescarts2.wikispaces.com/%s")); + registerModWiki("GanysSurface", new SimpleWikiProvider("Gany's Surface Wiki", "http://ganys-surface.wikia.com/wiki/%s")); + registerModWiki("GanysNether", new SimpleWikiProvider("Gany's Nether Wiki", "http://ganys-nether.wikia.com/wiki/%s")); + registerModWiki("GanysEnd", new SimpleWikiProvider("Gany's End Wiki", "http://ganys-end.wikia.com/wiki/%s")); } /** @@ -231,6 +265,34 @@ public final class BotaniaAPI { subTiles.put(key, subtileClass); } + /** + * Registers a SubTileEntity's signature. + * @see SubTileSignature + */ + public static void registerSubTileSignature(Class subtileClass, SubTileSignature signature) { + subTileSignatures.put(subtileClass, signature); + } + + /** + * Gets the singleton signature for a SubTileEntity class. Registers a fallback if one wasn't registered + * before the call. + */ + public static SubTileSignature getSignatureForClass(Class subtileClass) { + if(!subTileSignatures.containsKey(subtileClass)) + registerSubTileSignature(subtileClass, new BasicSignature(subTiles.inverse().get(subtileClass))); + + return subTileSignatures.get(subtileClass); + } + + /** + * Gets the singleton signature for a SubTileEntity's name. Registers a fallback if one wasn't registered + * before the call. + */ + public static SubTileSignature getSignatureForName(String name) { + Class subtileClass = subTiles.get(name); + return getSignatureForClass(subtileClass); + } + /** * Adds the key for a SubTileEntity into the creative menu. This goes into the * subtilesForCreativeMenu Set. @@ -259,7 +321,7 @@ public final class BotaniaAPI { public static List getAllEntries() { return allEntries; } - + /** * Registers a Lexicon Entry and adds it to the category passed in. */ @@ -311,6 +373,14 @@ public final class BotaniaAPI { return newList; } + /** + * Registers a Wiki provider for a mod so it uses that instead of the fallback + * FTB wiki. Make sure to call this on PostInit only! + */ + public static void registerModWiki(String mod, IWikiProvider provider) { + WikiHooks.registerModWiki(mod, provider); + } + public static Class getSubTileMapping(String key) { if(!subTiles.containsKey(key)) key = ""; diff --git a/src/api/java/vazkii/botania/api/internal/DummyMethodHandler.java b/src/api/java/vazkii/botania/api/internal/DummyMethodHandler.java index 29675d6..22e9da4 100644 --- a/src/api/java/vazkii/botania/api/internal/DummyMethodHandler.java +++ b/src/api/java/vazkii/botania/api/internal/DummyMethodHandler.java @@ -14,6 +14,7 @@ package vazkii.botania.api.internal; import java.util.List; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; @@ -103,6 +104,11 @@ public class DummyMethodHandler implements IInternalMethodHandler { return Blocks.red_flower.getIcon(0, 0); } + @Override + public void registerBasicSignatureIcons(String name, IIconRegister register) { + // NO-OP + } + @Override public IManaNetwork getManaNetworkInstance() { return DummyManaNetwork.instance; @@ -113,6 +119,11 @@ public class DummyMethodHandler implements IInternalMethodHandler { // NO-OP } + @Override + public void renderLexiconText(int x, int y, int width, int height, String unlocalizedText) { + // NO-OP + } + @Override public void sparkleFX(World world, double x, double y, double z, float r, float g, float b, float size, int m) { // NO-OP @@ -127,4 +138,10 @@ public class DummyMethodHandler implements IInternalMethodHandler { public boolean shouldForceCheck() { return true; } + + @Override + public int getPassiveFlowerDecay() { + return 0; + } + } diff --git a/src/api/java/vazkii/botania/api/internal/IInternalMethodHandler.java b/src/api/java/vazkii/botania/api/internal/IInternalMethodHandler.java index fa1934a..f75f208 100644 --- a/src/api/java/vazkii/botania/api/internal/IInternalMethodHandler.java +++ b/src/api/java/vazkii/botania/api/internal/IInternalMethodHandler.java @@ -14,6 +14,7 @@ package vazkii.botania.api.internal; import java.util.List; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; @@ -67,13 +68,20 @@ public interface IInternalMethodHandler { public IIcon getSubTileIconForName(String name); + public void registerBasicSignatureIcons(String name, IIconRegister register); + public boolean shouldForceCheck(); + public int getPassiveFlowerDecay(); + public IInventory getBaublesInventory(EntityPlayer player); @SideOnly(Side.CLIENT) public void drawSimpleManaHUD(int color, int mana, int maxMana, String name, ScaledResolution res); + @SideOnly(Side.CLIENT) + public void renderLexiconText(int x, int y, int width, int height, String unlocalizedText); + public void sparkleFX(World world, double x, double y, double z, float r, float g, float b, float size, int m); } diff --git a/src/api/java/vazkii/botania/api/item/IExoflameHeatable.java b/src/api/java/vazkii/botania/api/item/IExoflameHeatable.java new file mode 100644 index 0000000..eb4815c --- /dev/null +++ b/src/api/java/vazkii/botania/api/item/IExoflameHeatable.java @@ -0,0 +1,44 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Aug 30, 2014, 4:28:29 PM (GMT)] + */ +package vazkii.botania.api.item; + +/** + * A TileEntity that implements this can be heated by an Exoflame flower. + */ +public interface IExoflameHeatable { + + /** + * Can this TileEntity smelt its contents. If true, the Exoflame is allowed + * to fuel it. + */ + public boolean canSmelt(); + + /** + * Gets the amount of ticks left for the fuel. If below 2, the exoflame + * will call boostBurnTime. + */ + public int getBurnTime(); + + /** + * Called to increase the amount of time this furnace should be burning + * the fuel for. Even if it doesn't have any fuel. + */ + public void boostBurnTime(); + + /** + * Called once every two ticks to increase the speed of the furnace. Feel + * free to not do anything if all you want is to allow the exoflame to feed + * it, not make it faster. + */ + public void boostCookTime(); + +} diff --git a/src/api/java/vazkii/botania/api/item/IExtendedPlayerController.java b/src/api/java/vazkii/botania/api/item/IExtendedPlayerController.java index abe815b..67db3e6 100644 --- a/src/api/java/vazkii/botania/api/item/IExtendedPlayerController.java +++ b/src/api/java/vazkii/botania/api/item/IExtendedPlayerController.java @@ -21,7 +21,7 @@ public interface IExtendedPlayerController { * Sets the extra reach the player should have. */ public void setReachDistanceExtension(float f); - + /** * Gets the current reach extension. */ diff --git a/src/api/java/vazkii/botania/api/item/IPetalApothecary.java b/src/api/java/vazkii/botania/api/item/IPetalApothecary.java new file mode 100644 index 0000000..d96f73f --- /dev/null +++ b/src/api/java/vazkii/botania/api/item/IPetalApothecary.java @@ -0,0 +1,30 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Aug 30, 2014, 4:22:15 PM (GMT)] + */ +package vazkii.botania.api.item; + +/** + * Base Interface for the Petal Apothecary block. Can + * be safely casted to TileEntity. + */ +public interface IPetalApothecary { + + /** + * Sets if the the apothecary has water or not. + */ + public void setWater(boolean water); + + /** + * Does the apothecary have water in it? + */ + public boolean hasWater(); + +} diff --git a/src/api/java/vazkii/botania/api/lexicon/LexiconEntry.java b/src/api/java/vazkii/botania/api/lexicon/LexiconEntry.java index df60cd2..bbc475c 100644 --- a/src/api/java/vazkii/botania/api/lexicon/LexiconEntry.java +++ b/src/api/java/vazkii/botania/api/lexicon/LexiconEntry.java @@ -70,8 +70,11 @@ public class LexiconEntry implements Comparable { public LexiconEntry setLexiconPages(LexiconPage... pages) { this.pages.addAll(Arrays.asList(pages)); - for(int i = 0; i < this.pages.size(); i++) - this.pages.get(i).onPageAdded(this, i); + for(int i = 0; i < this.pages.size(); i++) { + LexiconPage page = this.pages.get(i); + if(!page.skipRegistry) + page.onPageAdded(this, i); + } return this; } diff --git a/src/api/java/vazkii/botania/api/lexicon/LexiconPage.java b/src/api/java/vazkii/botania/api/lexicon/LexiconPage.java index 4ab7bd7..f17f0c5 100644 --- a/src/api/java/vazkii/botania/api/lexicon/LexiconPage.java +++ b/src/api/java/vazkii/botania/api/lexicon/LexiconPage.java @@ -18,6 +18,7 @@ import cpw.mods.fml.relauncher.SideOnly; public abstract class LexiconPage { public String unlocalizedName; + public boolean skipRegistry; public LexiconPage(String unlocalizedName) { this.unlocalizedName = unlocalizedName; @@ -40,6 +41,14 @@ public abstract class LexiconPage { // NO-OP } + /** + * Called when a key is pressed. + */ + @SideOnly(Side.CLIENT) + public void onKeyPressed(char c, int key) { + // NO-OP + } + /** * Called when {@link LexiconEntry#setLexiconPages(LexiconPage...)} is called. */ @@ -50,4 +59,9 @@ public abstract class LexiconPage { public String getUnlocalizedName() { return unlocalizedName; } + + public LexiconPage setSkipRegistry() { + skipRegistry = true; + return this; + } } diff --git a/src/api/java/vazkii/botania/api/mana/IManaItem.java b/src/api/java/vazkii/botania/api/mana/IManaItem.java index 6fdcc22..42dfef1 100644 --- a/src/api/java/vazkii/botania/api/mana/IManaItem.java +++ b/src/api/java/vazkii/botania/api/mana/IManaItem.java @@ -60,7 +60,9 @@ public interface IManaItem { public boolean canExportManaToItem(ItemStack stack, ItemStack otherStack); /** - * If this item simply does not export mana in any have, set this to true. + * If this item simply does not export mana at all, set this to true. This is + * used to skip items that contain mana but can't export it when drawing the + * mana bar above the XP bar. */ public boolean isNoExport(ItemStack stack); diff --git a/src/api/java/vazkii/botania/api/mana/spark/ISparkAttachable.java b/src/api/java/vazkii/botania/api/mana/spark/ISparkAttachable.java new file mode 100644 index 0000000..4353f01 --- /dev/null +++ b/src/api/java/vazkii/botania/api/mana/spark/ISparkAttachable.java @@ -0,0 +1,54 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Aug 21, 2014, 5:44:13 PM (GMT)] + */ +package vazkii.botania.api.mana.spark; + +import net.minecraft.item.ItemStack; +import vazkii.botania.api.mana.IManaReceiver; + +/** + * A TileEntity that implements this can have a Spark attached to it. + * For the Spark to be allowed to have upgrades, it needs to be an IManaPool. + */ +public interface ISparkAttachable extends IManaReceiver { + + /** + * Can this block have a Spark attached to it. Note that this will not + * unattach the Spark if it's changed later. + */ + public boolean canAttachSpark(ItemStack stack); + + /** + * Called when the Spark is attached. + */ + public void attachSpark(ISparkEntity entity); + + /** + * Gets the Spark that is attached to this block. A common implementation is + * to check for Spark entities above: + * + List sparks = worldObj.getEntitiesWithinAABB(ISparkEntity.class, AxisAlignedBB.getBoundingBox(xCoord, yCoord + 1, zCoord, xCoord + 1, yCoord + 2, zCoord + 1)); + if(sparks.size() == 1) { + Entity e = (Entity) sparks.get(0); + return (ISparkEntity) e; + } + + return null; + */ + public ISparkEntity getAttachedSpark(); + + /** + * Return true if this Tile no longer requires mana and all Sparks + * transferring mana to it should cancel their transfer. + */ + public boolean areIncomingTranfersDone(); + +} diff --git a/src/api/java/vazkii/botania/api/mana/spark/ISparkEntity.java b/src/api/java/vazkii/botania/api/mana/spark/ISparkEntity.java new file mode 100644 index 0000000..084b827 --- /dev/null +++ b/src/api/java/vazkii/botania/api/mana/spark/ISparkEntity.java @@ -0,0 +1,65 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Aug 21, 2014, 5:44:07 PM (GMT)] + */ +package vazkii.botania.api.mana.spark; + +import java.util.Collection; + +/** + * An Entity that implements this is considered a Spark. + */ +public interface ISparkEntity { + + /** + * Which TileEntity is this Spark attached to? A common implementation is checking the block below. + * + int x = MathHelper.floor_double(posX); + int y = MathHelper.floor_double(posY) - 1; + int z = MathHelper.floor_double(posZ); + TileEntity tile = worldObj.getTileEntity(x, y, z); + if(tile != null && tile instanceof ISparkAttachable) + return (ISparkAttachable) tile; + + return null; + */ + public ISparkAttachable getAttachedTile(); + + /** + * Gets a collection of all Sparks this is tranfering to. + */ + public Collection getTransfers(); + + /** + * Registers the Spark passed in as a Spark meant for mana to be transfered towards. + */ + public void registerTransfer(ISparkEntity entity); + + /** + * Gets which upgrade is in this Spark.
+ * 0: None
+ * 1: Dispersive
+ * 2: Dominant
+ * 3: Recessive
+ * 4: Isolated + */ + public int getUpgrade(); + + /** + * Sets the upgrade on this Spark. See {@link ISparkEntity#getUpgrade} + */ + public void setUpgrade(int upgrade); + + /** + * See {@link ISparkAttachable#areIncomingTranfersDone()} + */ + public boolean areIncomingTransfersDone(); + +} diff --git a/src/api/java/vazkii/botania/api/mana/spark/SparkHelper.java b/src/api/java/vazkii/botania/api/mana/spark/SparkHelper.java new file mode 100644 index 0000000..6bb3196 --- /dev/null +++ b/src/api/java/vazkii/botania/api/mana/spark/SparkHelper.java @@ -0,0 +1,33 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Aug 21, 2014, 7:16:11 PM (GMT)] + */ +package vazkii.botania.api.mana.spark; + +import java.util.List; + +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; + +public final class SparkHelper { + + public static final int SPARK_SCAN_RANGE = 12; + + public static List getSparksAround(World world, double x, double y, double z) { + return SparkHelper.getEntitiesAround(ISparkEntity.class, world, x, y, z); + } + + public static List getEntitiesAround(Class clazz, World world, double x, double y, double z) { + int r = SPARK_SCAN_RANGE; + List entities = world.getEntitiesWithinAABB(clazz, AxisAlignedBB.getBoundingBox(x - r, y - r, z - r, x + r, y + r, z + r)); + return entities; + } + +} diff --git a/src/api/java/vazkii/botania/api/package-info.java b/src/api/java/vazkii/botania/api/package-info.java index e5a7b19..82da263 100644 --- a/src/api/java/vazkii/botania/api/package-info.java +++ b/src/api/java/vazkii/botania/api/package-info.java @@ -1,4 +1,4 @@ -@API(owner = "Botania", apiVersion = "7", provides = "BotaniaAPI") +@API(owner = "Botania", apiVersion = "18", provides = "BotaniaAPI") package vazkii.botania.api; import cpw.mods.fml.common.API; diff --git a/src/api/java/vazkii/botania/api/subtile/ISubTileContainer.java b/src/api/java/vazkii/botania/api/subtile/ISubTileContainer.java new file mode 100644 index 0000000..ddfaee7 --- /dev/null +++ b/src/api/java/vazkii/botania/api/subtile/ISubTileContainer.java @@ -0,0 +1,30 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Aug 26, 2014, 5:42:16 PM (GMT)] + */ +package vazkii.botania.api.subtile; + +/** + * A TileEntity that implements this contains a SubTileEntity. + */ +public interface ISubTileContainer { + + /** + * Gets the SubTile in this block. Generally shouldn't return null, but in that + * case use the fallback DummySubTile. + */ + public SubTileEntity getSubTile(); + + /** + * Sets the SubTile on this block from it's name. + */ + public void setSubTile(String name); + +} diff --git a/src/api/java/vazkii/botania/api/subtile/SubTileEntity.java b/src/api/java/vazkii/botania/api/subtile/SubTileEntity.java index 499e385..366614a 100644 --- a/src/api/java/vazkii/botania/api/subtile/SubTileEntity.java +++ b/src/api/java/vazkii/botania/api/subtile/SubTileEntity.java @@ -21,6 +21,7 @@ import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.IIcon; import vazkii.botania.api.BotaniaAPI; import vazkii.botania.api.lexicon.LexiconEntry; +import vazkii.botania.api.wand.IWandBindable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -100,6 +101,20 @@ public class SubTileEntity { return null; } + /** + * @see IWandBindable#canSelect(EntityPlayer, ItemStack, int, int, int, int) + */ + public boolean canSelect(EntityPlayer player, ItemStack wand, int x, int y, int z, int side) { + return false; + } + + /** + * @see IWandBindable#bindTo(EntityPlayer, ItemStack, int, int, int, int) + */ + public boolean bindTo(EntityPlayer player, ItemStack wand, int x, int y, int z, int side) { + return false; + } + /** * Called on the client when the block being pointed at is the one with this sub tile. * Used to render a HUD portraying some data from this sub tile. diff --git a/src/api/java/vazkii/botania/api/subtile/SubTileFunctional.java b/src/api/java/vazkii/botania/api/subtile/SubTileFunctional.java index a927946..7d95afe 100644 --- a/src/api/java/vazkii/botania/api/subtile/SubTileFunctional.java +++ b/src/api/java/vazkii/botania/api/subtile/SubTileFunctional.java @@ -180,6 +180,28 @@ public class SubTileFunctional extends SubTileEntity { return new ChunkCoordinates(linkedPool.xCoord, linkedPool.yCoord, linkedPool.zCoord); } + @Override + public boolean canSelect(EntityPlayer player, ItemStack wand, int x, int y, int z, int side) { + return true; + } + + @Override + public boolean bindTo(EntityPlayer player, ItemStack wand, int x, int y, int z, int side) { + int range = 10; + range *= range; + + double dist = (x - supertile.xCoord) * (x - supertile.xCoord) + (y - supertile.yCoord) * (y - supertile.yCoord) + (z - supertile.zCoord) * (z - supertile.zCoord); + if(range >= dist) { + TileEntity tile = player.worldObj.getTileEntity(x, y, z); + if(tile instanceof IManaPool) { + linkedPool = tile; + return true; + } + } + + return false; + } + @Override public void renderHUD(Minecraft mc, ScaledResolution res) { String name = StatCollector.translateToLocal("tile.botania:flower." + getUnlocalizedName() + ".name"); diff --git a/src/api/java/vazkii/botania/api/subtile/SubTileGenerating.java b/src/api/java/vazkii/botania/api/subtile/SubTileGenerating.java index 4d86776..edfeabe 100644 --- a/src/api/java/vazkii/botania/api/subtile/SubTileGenerating.java +++ b/src/api/java/vazkii/botania/api/subtile/SubTileGenerating.java @@ -13,6 +13,7 @@ package vazkii.botania.api.subtile; import java.awt.Color; +import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.entity.player.EntityPlayer; @@ -31,6 +32,7 @@ import vazkii.botania.api.mana.IManaCollector; public class SubTileGenerating extends SubTileEntity { private static final String TAG_MANA = "mana"; + private static final String TAG_TICKS_EXISTED = "ticksExisted"; private static final String TAG_COLLECTOR_X = "collectorX"; private static final String TAG_COLLECTOR_Y = "collectorY"; @@ -38,6 +40,7 @@ public class SubTileGenerating extends SubTileEntity { protected int mana; + int ticksExisted = 0; int sizeLastCheck = -1; protected TileEntity linkedCollector = null; public int knownMana = -1; @@ -71,6 +74,16 @@ public class SubTileGenerating extends SubTileEntity { if(Math.random() > particleChance) BotaniaAPI.internalHandler.sparkleFX(supertile.getWorldObj(), supertile.xCoord + 0.3 + Math.random() * 0.5, supertile.yCoord + 0.5 + Math.random() * 0.5, supertile.zCoord + 0.3 + Math.random() * 0.5, color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, (float) Math.random(), 5); } + + if(!supertile.getWorldObj().isRemote) { + ++ticksExisted; + int muhBalance = BotaniaAPI.internalHandler.getPassiveFlowerDecay(); + + if(isPassiveFlower() && muhBalance > 0 && ticksExisted > muhBalance) { + supertile.getWorldObj().playAuxSFX(2001, supertile.xCoord, supertile.yCoord, supertile.zCoord, Block.getIdFromBlock(supertile.getBlockType())); + supertile.getWorldObj().setBlockToAir(supertile.xCoord, supertile.yCoord, supertile.zCoord); + } + } } public void linkCollector() { @@ -120,11 +133,14 @@ public class SubTileGenerating extends SubTileEntity { int manaval = Math.min(mana, collector.getMaxMana() - collector.getCurrentMana()); mana -= manaval; collector.recieveMana(manaval); - sync(); } } } + public boolean isPassiveFlower() { + return false; + } + public boolean shouldSyncPassiveGeneration() { return false; } @@ -166,6 +182,8 @@ public class SubTileGenerating extends SubTileEntity { @Override public void readFromPacketNBT(NBTTagCompound cmp) { mana = cmp.getInteger(TAG_MANA); + if(!cmp.hasKey(TAG_TICKS_EXISTED)) + ticksExisted = cmp.getInteger(TAG_TICKS_EXISTED); int x = cmp.getInteger(TAG_COLLECTOR_X); int y = cmp.getInteger(TAG_COLLECTOR_Y); @@ -177,6 +195,7 @@ public class SubTileGenerating extends SubTileEntity { @Override public void writeToPacketNBT(NBTTagCompound cmp) { cmp.setInteger(TAG_MANA, mana); + cmp.setInteger(TAG_TICKS_EXISTED, ticksExisted); int x = linkedCollector == null ? 0 : linkedCollector.xCoord; int y = linkedCollector == null ? -1 : linkedCollector.yCoord; @@ -194,6 +213,28 @@ public class SubTileGenerating extends SubTileEntity { return new ChunkCoordinates(linkedCollector.xCoord, linkedCollector.yCoord, linkedCollector.zCoord); } + @Override + public boolean canSelect(EntityPlayer player, ItemStack wand, int x, int y, int z, int side) { + return true; + } + + @Override + public boolean bindTo(EntityPlayer player, ItemStack wand, int x, int y, int z, int side) { + int range = 6; + range *= range; + + double dist = (x - supertile.xCoord) * (x - supertile.xCoord) + (y - supertile.yCoord) * (y - supertile.yCoord) + (z - supertile.zCoord) * (z - supertile.zCoord); + if(range >= dist) { + TileEntity tile = player.worldObj.getTileEntity(x, y, z); + if(tile instanceof IManaCollector) { + linkedCollector = tile; + return true; + } + } + + return false; + } + @Override public void renderHUD(Minecraft mc, ScaledResolution res) { String name = StatCollector.translateToLocal("tile.botania:flower." + getUnlocalizedName() + ".name"); diff --git a/src/api/java/vazkii/botania/api/subtile/signature/BasicSignature.java b/src/api/java/vazkii/botania/api/subtile/signature/BasicSignature.java new file mode 100644 index 0000000..f72cb09 --- /dev/null +++ b/src/api/java/vazkii/botania/api/subtile/signature/BasicSignature.java @@ -0,0 +1,58 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Oct 17, 2014, 5:34:35 PM (GMT)] + */ +package vazkii.botania.api.subtile.signature; + +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +import vazkii.botania.api.BotaniaAPI; + +/** + * A basic (and fallback) implementation of SubTileSignature. + */ +public class BasicSignature extends SubTileSignature { + + final String name; + + public BasicSignature(String name) { + this.name = name; + } + + @Override + public void registerIcons(IIconRegister register) { + BotaniaAPI.internalHandler.registerBasicSignatureIcons(name, register); + } + + @Override + public IIcon getIconForStack(ItemStack stack) { + return BotaniaAPI.internalHandler.getSubTileIconForName(name); + } + + @Override + public String getUnlocalizedNameForStack(ItemStack stack) { + return unlocalizedName(""); + } + + @Override + public String getUnlocalizedLoreTextForStack(ItemStack stack) { + return unlocalizedName(".reference"); + } + + public String getName() { + return name; + } + + private String unlocalizedName(String end) { + return "tile." + SubTileSignature.SPECIAL_FLOWER_PREFIX + name + end; + } + +} diff --git a/src/api/java/vazkii/botania/api/subtile/signature/SubTileSignature.java b/src/api/java/vazkii/botania/api/subtile/signature/SubTileSignature.java new file mode 100644 index 0000000..dcd280e --- /dev/null +++ b/src/api/java/vazkii/botania/api/subtile/signature/SubTileSignature.java @@ -0,0 +1,47 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Oct 17, 2014, 5:29:26 PM (GMT)] + */ +package vazkii.botania.api.subtile.signature; + +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; + +/** + * A singleton instance for a SubTileEntity, this is called for a few methods. + */ +public abstract class SubTileSignature { + + public static final String SPECIAL_FLOWER_PREFIX = "flower."; + + /** + * Equivalent to Block.registerBlockIcons. + */ + public abstract void registerIcons(IIconRegister register); + + /** + * Gets the icon to display for the flower item. + */ + public abstract IIcon getIconForStack(ItemStack stack); + + /** + * Gets the display name for the flower item. + */ + public abstract String getUnlocalizedNameForStack(ItemStack stack); + + /** + * Gets the lore text for the flower item, displayed in the item's tooltip. + * If you do not want a reference return a key that does not have localization such + * as "botaniamisc.noloc". + */ + public abstract String getUnlocalizedLoreTextForStack(ItemStack stack); + +} diff --git a/src/api/java/vazkii/botania/api/wand/IWandBindable.java b/src/api/java/vazkii/botania/api/wand/IWandBindable.java new file mode 100644 index 0000000..d1737a9 --- /dev/null +++ b/src/api/java/vazkii/botania/api/wand/IWandBindable.java @@ -0,0 +1,35 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Oct 9, 2014, 3:01:58 PM (GMT)] + */ +package vazkii.botania.api.wand; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +/** + * A TileEntity that implements this can be bound to another block + * via the Wand of the Forest. Also see IWireframeAABBProvider to change + * the displayed bounding box. + */ +public interface IWandBindable extends ITileBound { + + /** + * Return true if the Wand can select this tile. + */ + public boolean canSelect(EntityPlayer player, ItemStack wand, int x, int y, int z, int side); + + /** + * Call to bind the TileEntity to where the player clicked. Return true to deselect + * the TileEntity for another bind or false case the TileEntity should stay selected. + */ + public boolean bindTo(EntityPlayer player, ItemStack wand, int x, int y, int z, int side); + +} diff --git a/src/api/java/vazkii/botania/api/wand/IWandable.java b/src/api/java/vazkii/botania/api/wand/IWandable.java index 519745d..0cdcf1f 100644 --- a/src/api/java/vazkii/botania/api/wand/IWandable.java +++ b/src/api/java/vazkii/botania/api/wand/IWandable.java @@ -21,7 +21,7 @@ import net.minecraft.world.World; public interface IWandable { /** - * Called when the item is used by a wand. Note that the player parameter can be null + * Called when the block is used by a wand. Note that the player parameter can be null * if this function is called from a dispenser. */ public boolean onUsedByWand(EntityPlayer player, ItemStack stack, World world, int x, int y, int z, int side); diff --git a/src/api/java/vazkii/botania/api/wiki/IWikiProvider.java b/src/api/java/vazkii/botania/api/wiki/IWikiProvider.java new file mode 100644 index 0000000..42e6114 --- /dev/null +++ b/src/api/java/vazkii/botania/api/wiki/IWikiProvider.java @@ -0,0 +1,39 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Sep 2, 2014, 5:57:35 PM (GMT)] + */ +package vazkii.botania.api.wiki; + +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; + +/** + * An interface for a Wiki Provider, these are registered to allow a mod to provide a wiki + * for all the blocks in them, used for the world interaction with the Lexica Botania. + * A simple, mostly all-inclusive implementation can be found on SimpleWikiProvider. + */ +public interface IWikiProvider { + + /** + * Gets the name of the block being looked at for display. + */ + public String getBlockName(World world, MovingObjectPosition pos); + + /** + * Gets the URL to open when the block is clicked. + */ + public String getWikiURL(World world, MovingObjectPosition pos); + + /** + * Gets the name of the wiki for display. + */ + public String getWikiName(World world, MovingObjectPosition pos); + +} diff --git a/src/api/java/vazkii/botania/api/wiki/SimpleWikiProvider.java b/src/api/java/vazkii/botania/api/wiki/SimpleWikiProvider.java new file mode 100644 index 0000000..6eb949b --- /dev/null +++ b/src/api/java/vazkii/botania/api/wiki/SimpleWikiProvider.java @@ -0,0 +1,73 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Sep 2, 2014, 5:58:39 PM (GMT)] + */ +package vazkii.botania.api.wiki; + +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; + +import org.apache.commons.lang3.text.WordUtils; + +public class SimpleWikiProvider implements IWikiProvider { + + final String name, urlBase, replacement; + + public SimpleWikiProvider(String name, String urlBase) { + this(name, urlBase, "%20"); + } + + public SimpleWikiProvider(String name, String urlBase, String replacement) { + this.name = name; + this.urlBase = urlBase; + this.replacement = replacement; + } + + @Override + public String getBlockName(World world, MovingObjectPosition pos) { + int x = pos.blockX; + int y = pos.blockY; + int z = pos.blockZ; + + Block block = world.getBlock(x, y, z); + if(block == null) + return null; + + ItemStack stack = block.getPickBlock(pos, world, x, y, z); + + if(stack == null || stack.getItem() == null) + stack = new ItemStack(block, 1, world.getBlockMetadata(x, y, z)); + + if(stack.getItem() == null) + return null; + + String name = stack.getDisplayName(); + if(name == null || name.isEmpty()) + return null; + + return name; + } + + @Override + public String getWikiURL(World world, MovingObjectPosition pos) { + String name = getBlockName(world, pos); + if(name == null) + return null; + return String.format(urlBase, WordUtils.capitalizeFully(name).replaceAll(" ", replacement)); + } + + @Override + public String getWikiName(World world, MovingObjectPosition pos) { + return name; + } + +} diff --git a/src/api/java/vazkii/botania/api/wiki/WikiHooks.java b/src/api/java/vazkii/botania/api/wiki/WikiHooks.java new file mode 100644 index 0000000..40f586e --- /dev/null +++ b/src/api/java/vazkii/botania/api/wiki/WikiHooks.java @@ -0,0 +1,43 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Sep 2, 2014, 6:05:03 PM (GMT)] + */ +package vazkii.botania.api.wiki; + +import java.util.HashMap; +import java.util.Map; + +import net.minecraft.block.Block; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier; + +public class WikiHooks { + + private static final IWikiProvider FALLBACK_PROVIDER = new SimpleWikiProvider("FTB Wiki", "http://wiki.feed-the-beast.com/%s"); + + private static final Map modWikis = new HashMap(); + + public static IWikiProvider getWikiFor(Block block) { + UniqueIdentifier mod = GameRegistry.findUniqueIdentifierFor(block); + return getWikiFor(mod.modId.toLowerCase()); + } + + public static IWikiProvider getWikiFor(String mod) { + if(!modWikis.containsKey(mod)) + modWikis.put(mod, FALLBACK_PROVIDER); + + return modWikis.get(mod); + } + + public static void registerModWiki(String mod, IWikiProvider provider) { + modWikis.put(mod.toLowerCase(), provider); + } + +}