From 5c01df44c1bef58e98ddd8a84641e5173fa0da71 Mon Sep 17 00:00:00 2001 From: WayofTime Date: Mon, 25 May 2015 14:58:23 -0400 Subject: [PATCH] Delivering packages in style! --- build.properties | 4 +- .../api/IHeatExchangerLogic.java | 77 ++++++ .../pneumaticCraft/api/PneumaticRegistry.java | 158 ++++++++++++ .../api/actuator/IActuator.java | 32 +++ .../api/block/BlockSupplier.java | 77 ++++++ .../api/block/IPneumaticWrenchable.java | 14 ++ .../api/client/GuiAnimatedStatSupplier.java | 49 ++++ .../api/client/GuiElementRenderer.java | 32 +++ .../api/client/IGuiAnimatedStat.java | 179 ++++++++++++++ .../AssemblyRenderOverriding.java | 55 +++++ .../pneumaticHelmet/IBlockTrackEntry.java | 80 +++++++ .../pneumaticHelmet/IEntityTrackEntry.java | 49 ++++ .../client/pneumaticHelmet/IGuiScreen.java | 15 ++ .../pneumaticHelmet/IHackableBlock.java | 69 ++++++ .../pneumaticHelmet/IHackableEntity.java | 59 +++++ .../client/pneumaticHelmet/IOptionPage.java | 46 ++++ .../IUpgradeRenderHandler.java | 92 +++++++ .../RenderHandlerRegistry.java | 10 + .../api/drone/DroneConstructingEvent.java | 11 + .../api/drone/IBlockInteractHandler.java | 26 ++ .../api/drone/ICustomBlockInteract.java | 45 ++++ .../java/pneumaticCraft/api/drone/IDrone.java | 61 +++++ .../api/drone/IPathNavigator.java | 11 + .../api/drone/IPathfindHandler.java | 26 ++ .../drone/SpecialVariableRetrievalEvent.java | 60 +++++ .../api/item/IInventoryItem.java | 20 ++ .../api/item/IPressurizable.java | 35 +++ .../api/item/IProgrammable.java | 34 +++ .../pneumaticCraft/api/item/ItemSupplier.java | 47 ++++ .../java/pneumaticCraft/api/package-info.java | 5 + .../api/recipe/AssemblyRecipe.java | 49 ++++ .../api/recipe/IPressureChamberRecipe.java | 34 +++ .../api/recipe/PressureChamberRecipe.java | 24 ++ .../api/tileentity/AirHandlerSupplier.java | 51 ++++ .../api/tileentity/IAirHandler.java | 114 +++++++++ .../api/tileentity/IHeatExchanger.java | 24 ++ .../api/tileentity/IManoMeasurable.java | 14 ++ .../api/tileentity/IPneumaticMachine.java | 30 +++ .../api/universalSensor/EntityPollSensor.java | 31 +++ .../IBlockAndCoordinateEventSensor.java | 59 +++++ .../IBlockAndCoordinatePollSensor.java | 63 +++++ .../universalSensor/IEventSensorSetting.java | 23 ++ .../universalSensor/IPollSensorSetting.java | 27 +++ .../api/universalSensor/ISensorSetting.java | 59 +++++ .../universalSensor/PlayerEventSensor.java | 33 +++ .../universalSensor/SensorRegistrator.java | 33 +++ .../AlchemicalWizardry.java | 5 +- .../api/guide/PageRitualMultiBlock.java | 4 +- .../common/book/BloodMagicGuide.java | 225 +++++++++++++++++- .../entity/mob/MailOrderEntityItem.java | 31 ++- .../common/guide/RecipeHolder.java | 4 + .../alchemicalwizardryBooks/lang/en_US.lang | 90 +++---- 52 files changed, 2444 insertions(+), 61 deletions(-) create mode 100644 src/api/java/pneumaticCraft/api/IHeatExchangerLogic.java create mode 100644 src/api/java/pneumaticCraft/api/PneumaticRegistry.java create mode 100644 src/api/java/pneumaticCraft/api/actuator/IActuator.java create mode 100644 src/api/java/pneumaticCraft/api/block/BlockSupplier.java create mode 100644 src/api/java/pneumaticCraft/api/block/IPneumaticWrenchable.java create mode 100644 src/api/java/pneumaticCraft/api/client/GuiAnimatedStatSupplier.java create mode 100644 src/api/java/pneumaticCraft/api/client/GuiElementRenderer.java create mode 100644 src/api/java/pneumaticCraft/api/client/IGuiAnimatedStat.java create mode 100644 src/api/java/pneumaticCraft/api/client/assemblymachine/AssemblyRenderOverriding.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IBlockTrackEntry.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IEntityTrackEntry.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IGuiScreen.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableBlock.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableEntity.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IOptionPage.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IUpgradeRenderHandler.java create mode 100644 src/api/java/pneumaticCraft/api/client/pneumaticHelmet/RenderHandlerRegistry.java create mode 100644 src/api/java/pneumaticCraft/api/drone/DroneConstructingEvent.java create mode 100644 src/api/java/pneumaticCraft/api/drone/IBlockInteractHandler.java create mode 100644 src/api/java/pneumaticCraft/api/drone/ICustomBlockInteract.java create mode 100644 src/api/java/pneumaticCraft/api/drone/IDrone.java create mode 100644 src/api/java/pneumaticCraft/api/drone/IPathNavigator.java create mode 100644 src/api/java/pneumaticCraft/api/drone/IPathfindHandler.java create mode 100644 src/api/java/pneumaticCraft/api/drone/SpecialVariableRetrievalEvent.java create mode 100644 src/api/java/pneumaticCraft/api/item/IInventoryItem.java create mode 100644 src/api/java/pneumaticCraft/api/item/IPressurizable.java create mode 100644 src/api/java/pneumaticCraft/api/item/IProgrammable.java create mode 100644 src/api/java/pneumaticCraft/api/item/ItemSupplier.java create mode 100644 src/api/java/pneumaticCraft/api/package-info.java create mode 100644 src/api/java/pneumaticCraft/api/recipe/AssemblyRecipe.java create mode 100644 src/api/java/pneumaticCraft/api/recipe/IPressureChamberRecipe.java create mode 100644 src/api/java/pneumaticCraft/api/recipe/PressureChamberRecipe.java create mode 100644 src/api/java/pneumaticCraft/api/tileentity/AirHandlerSupplier.java create mode 100644 src/api/java/pneumaticCraft/api/tileentity/IAirHandler.java create mode 100644 src/api/java/pneumaticCraft/api/tileentity/IHeatExchanger.java create mode 100644 src/api/java/pneumaticCraft/api/tileentity/IManoMeasurable.java create mode 100644 src/api/java/pneumaticCraft/api/tileentity/IPneumaticMachine.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/EntityPollSensor.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinateEventSensor.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinatePollSensor.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/IEventSensorSetting.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/IPollSensorSetting.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/ISensorSetting.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/PlayerEventSensor.java create mode 100644 src/api/java/pneumaticCraft/api/universalSensor/SensorRegistrator.java diff --git a/build.properties b/build.properties index fb217e6c..86c807c4 100644 --- a/build.properties +++ b/build.properties @@ -1,5 +1,5 @@ # -#Sun May 17 08:27:28 EDT 2015 +#Mon May 25 14:32:22 EDT 2015 mod_name=BloodMagic forge_version=10.13.3.1374-1.7.10 ccc_version=1.0.4.29 @@ -9,5 +9,5 @@ guideapi_version=1.0-14 package_group=com.wayoftime.bloodmagic mod_version=1.3.2aBeta minetweaker_version=Dev-1.7.10-3.0.9B +build_number=14 mc_version=1.7.10 -build_number=13 diff --git a/src/api/java/pneumaticCraft/api/IHeatExchangerLogic.java b/src/api/java/pneumaticCraft/api/IHeatExchangerLogic.java new file mode 100644 index 00000000..78f8dbec --- /dev/null +++ b/src/api/java/pneumaticCraft/api/IHeatExchangerLogic.java @@ -0,0 +1,77 @@ +package pneumaticCraft.api; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +/** + * DO NOT IMPLEMENT THIS CLASS YOURSELF! Use PneumaticRegistry.getInstance().getHeatExchangerLogic() ! + * @author MineMaarten + * www.minemaarten.com + */ +public interface IHeatExchangerLogic{ + + /** + * Call this to tick this logic, and make the heat disperse itself. + */ + public void update(); + + /** + * When called (preferably on tile entity load and neighbor block/tile entity change) this will add all IHeatExchanger neighbor TileEntities as connected heat exchangers. + * It will also take care of blocks like Lava. + * + * You don't _have_ to call this method, if this heat exchanger is not connected to the outside world (for example the heat of the liquid + * plastic in the Plastic Mixer). + * @param world + * @param x + * @param y + * @param z + * @param validSides Can be left out as vararg, meaning every side can be connected. When one or more sides are specified this will constrain + * this heat exchanger to only connect to other heat exchangers on these sides. + */ + public void initializeAsHull(World world, int x, int y, int z, ForgeDirection... validSides); + + /** + * When called, this will connect these two heat exchangers. You should only call this on one of the two heat exchangers. + * @param exchanger + */ + public void addConnectedExchanger(IHeatExchangerLogic exchanger); + + public void removeConnectedExchanger(IHeatExchangerLogic exchanger); + + /** + * A heat exchanger starts with 295 degrees Kelvin (20 degrees Celcius) by default. + * @param temperature in degrees Kelvin + */ + public void setTemperature(double temperature); + + public double getTemperature(); + + /** + * The higher the thermal resistance, the slower the heat disperses. + * @param thermalResistance By default it's 1. + */ + public void setThermalResistance(double thermalResistance); + + public double getThermalResistance(); + + /** + * The higher the capacity, the more heat can be 'stored'. This means that an object with a high capacity can heat up an object with a lower + * capacity without losing any significant amount of temperature. + * @param capacity + */ + public void setThermalCapacity(double capacity); + + public double getThermalCapacity(); + + public void writeToNBT(NBTTagCompound tag); + + public void readFromNBT(NBTTagCompound tag); + + /** + * Adds heat (= deltaT * Thermal Capacity) to this exchanger. negative values will remove heat. + * @param amount + */ + public void addHeat(double amount); + +} diff --git a/src/api/java/pneumaticCraft/api/PneumaticRegistry.java b/src/api/java/pneumaticCraft/api/PneumaticRegistry.java new file mode 100644 index 00000000..f3254829 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/PneumaticRegistry.java @@ -0,0 +1,158 @@ +package pneumaticCraft.api; + +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityCreature; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; +import pneumaticCraft.api.client.pneumaticHelmet.IBlockTrackEntry; +import pneumaticCraft.api.client.pneumaticHelmet.IEntityTrackEntry; +import pneumaticCraft.api.client.pneumaticHelmet.IHackableBlock; +import pneumaticCraft.api.client.pneumaticHelmet.IHackableEntity; +import pneumaticCraft.api.drone.ICustomBlockInteract; +import pneumaticCraft.api.drone.IPathfindHandler; +import pneumaticCraft.api.item.IInventoryItem; + +/** + * This class can be used to register and access various things to and from the mod. + */ +public class PneumaticRegistry{ + /** + * This field, which is initialized in PneumaticCraft's preInit, will give you access to various registration and access options. + * @deprecated This field isn't going to be removed, but it'll be marked private. use getInstance(). + */ + @Deprecated + public static IPneumaticCraftInterface instance; + + public static IPneumaticCraftInterface getInstance(){ + return instance; + } + + public static void init(IPneumaticCraftInterface inter){ + if(instance == null) instance = inter;//only allow initialization once; by PneumaticCraft + } + + public static interface IPneumaticCraftInterface{ + + /* + * ------------- Pneumatic Helmet -------------- + */ + + public void registerEntityTrackEntry(Class entry); + + public void registerBlockTrackEntry(IBlockTrackEntry entry); + + public void addHackable(Class entityClazz, Class iHackable); + + public void addHackable(Block block, Class iHackable); + + /** + * Returns a list of all current successful hacks of a given entity. This is used for example in Enderman hacking, so the user + * can only hack an enderman once (more times wouldn't have any effect). This is mostly used for display purposes. + * @param entity + * @return empty list if no hacks. + */ + public List getCurrentEntityHacks(Entity entity); + + /* + * ------------- Drones -------------- + */ + + /** + * Normally drones will pathfind through any block that doesn't have any collisions (Block#getBlocksMovement returns true). + * With this method you can register custom blocks to allow the drone to pathfind through them. If the block requires any special + * handling, like allow pathfinding on certain conditions, you can pass a IPathFindHandler with the registry. + * @param block + * @param handler can be null, to always allow pathfinding through this block. + */ + public void addPathfindableBlock(Block block, IPathfindHandler handler); + + /** + * This will add a puzzle piece that has only a Area white- and blacklist parameter (similar to a GoTo piece). + * It will do the specified behaviour. This can be used to create energy import/export widgets. + * @param interactor + */ + public void registerCustomBlockInteractor(ICustomBlockInteract interactor); + + /** + * Will spawn in a Drone a distance away from the given coordinate. The drone is programmed to travel to go to 5 blocks above the specified + * y level, and drop the deliveredStacks. When there isn't a clear path for the items to fall these 5 blocks the Drone will deliver at a + * y level above the specified y that _is_ clear. If no clear blocks can be found (when there are only solid blocks), the Drone will + * drop the items very high up in the air instead, and drop them there. + * + * When the Drone is tried to be catched by a player (by wrenching it), the drone will only the drop the items that it was delivering (or + * none if it dropped those items already). The Drone itself never will be dropped. + * + * @param x + * @param y + * @param z + * @param deliveredStacks stacks that are delivered by the drone. When no stacks, or more than 65 stacks are given, this will generate a IllegalArgumentException. + * @return the drone. You can use this to set a custom name for example (defaults to "Amazon Delivery Drone"). + */ + public EntityCreature deliverItemsAmazonStyle(World world, int x, int y, int z, ItemStack... deliveredStacks); + + /* + * --------------- Items ------------------- + */ + /** + * See {@link pneumaticCraft.api.item.IInventoryItem} + * @param handler + */ + public void registerInventoryItem(IInventoryItem handler); + + /* + * ----------------- Heat System -------------- + */ + public IHeatExchangerLogic getHeatExchangerLogic(); + + public void registerBlockExchanger(Block block, double temperature, double thermalResistance); + + /* + * ---------------- Power Generation ----------- + */ + + /** + * Adds a burnable liquid to the Liquid Compressor's available burnable fuels. + * @param fluid + * @param mLPerBucket the amount of mL generated for 1000mB of the fuel. As comparison, one piece of coal generates 16000mL in an Air Compressor. + */ + public void registerFuel(Fluid fluid, int mLPerBucket); + + /* + * --------------- Misc ------------------- + */ + + /** + * Returns the amount of Security Stations that disallow interaction with the given coordinate for the given player. + * Usually you'd disallow interaction when this returns > 0. + * @param world + * @param x + * @param y + * @param z + * @param player + * @param showRangeLines When true, any Security Station that prevents interaction will show the line grid (server --> client update is handled internally). + * @return The amount of Security Stations that disallow interaction for the given player. + * This method throws an IllegalArgumentException when tried to be called from the client side! + */ + public int getProtectingSecurityStations(World world, int x, int y, int z, EntityPlayer player, boolean showRangeLines); + + /** + * Use this to register ISimpleBlockRenderHandler render id's of full blocks, those of which should be able to be used for the Pneumatic Door Base camouflage. + * @param id + */ + public void registerConcealableRenderId(int id); + + /** + * Used to register a liquid that represents liquid XP (like MFR mob essence, OpenBlocks liquid XP). + * This is used in the Aerial Interface to pump XP in/out of the player. + * @param fluid + * @param liquidToPointRatio The amount of liquid (in mB) used to get one XP point. In OpenBlocks this is 20 (mB/point). + */ + public void registerXPLiquid(Fluid fluid, int liquidToPointRatio); + + } +} diff --git a/src/api/java/pneumaticCraft/api/actuator/IActuator.java b/src/api/java/pneumaticCraft/api/actuator/IActuator.java new file mode 100644 index 00000000..93ea61a2 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/actuator/IActuator.java @@ -0,0 +1,32 @@ +package pneumaticCraft.api.actuator; + +import java.util.List; + +import net.minecraft.tileentity.TileEntity; + +public interface IActuator{ + /** + * Same as {@link pneumaticCraft.api.universalSensor.ISensorSetting#getSensorPath()} + * @return + */ + public String getSensorPath(); + + /** + * When returned true, the GUI will enable the textbox writing, otherwise not. + * @return + */ + public boolean needsTextBox(); + + /** + * Should return the description of this sensor displayed in the GUI stat. Information should at least include + * when this sensor emits redstone and how (analog (1 through 15), or digital). + * @return + */ + public List getDescription(); + + /** + * + * @param universalActuator + */ + public void actuate(TileEntity universalActuator); +} diff --git a/src/api/java/pneumaticCraft/api/block/BlockSupplier.java b/src/api/java/pneumaticCraft/api/block/BlockSupplier.java new file mode 100644 index 00000000..0e35540d --- /dev/null +++ b/src/api/java/pneumaticCraft/api/block/BlockSupplier.java @@ -0,0 +1,77 @@ +package pneumaticCraft.api.block; + +import net.minecraft.block.Block; +import cpw.mods.fml.common.registry.GameRegistry; + +public class BlockSupplier{ + // private static Class blockClass; + + /** + * @param blockName + * @return + */ + public static Block getBlock(String blockName){ + return GameRegistry.findBlock("PneumaticCraft", blockName); + /*try { + if(blockClass == null) blockClass = Class.forName("pneumaticCraft.common.block.Blockss"); + return (Block)blockClass.getField(blockName).get(null); + } catch(Exception e) { + System.err.println("[PneumaticCraft API] Block supply failed for block: " + blockName); + return null; + }*/ + } + + /* + The following is a list of all the block names that can be passed as argument in getBlock(String) to get a PneumaticCraft block. + + + pressureTube meta = tube type + airCompressor + airCannon + pressureChamberWall meta < 6 ? wall : window + pressureChamberValve + pressureChamberInterface + squidPlant + fireFlower + creeperPlant + slimePlant + rainPlant + enderPlant + lightningPlant + adrenalinePlant + burstPlant + potionPlant + repulsionPlant + heliumPlant + flyingFlower + musicPlant + propulsionPlant + chopperPlant + chargingStation + elevatorBase + elevatorFrame + vacuumPump + pneumaticDoorBase + pneumaticDoor + assemblyPlatform + assemblyIOUnit + assemblyDrill + assemblyLaser + assemblyController + advancedPressureTube meta = tube type (like 'pressureTube') + compressedIron + uvLightBox + etchingAcid + securityStation + universalSensor + pneumaticGenerator + electricCompressor + pneumaticEngine + kineticCompressor + aerialInterface + electrostaticCompressor + aphorismTile + omnidirectionalHopper + + */ +} diff --git a/src/api/java/pneumaticCraft/api/block/IPneumaticWrenchable.java b/src/api/java/pneumaticCraft/api/block/IPneumaticWrenchable.java new file mode 100644 index 00000000..5b666d49 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/block/IPneumaticWrenchable.java @@ -0,0 +1,14 @@ +package pneumaticCraft.api.block; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + +/** + * Should be implemented by any block that allows to be rotated by a Pneumatic Wrench. It uses almost the same + * rotate method as the Vanilla (Forge) method. However it uses energy to rotate (when rotateBlock() return true). + */ +public interface IPneumaticWrenchable{ + + public boolean rotateBlock(World world, EntityPlayer player, int x, int y, int z, ForgeDirection side); +} diff --git a/src/api/java/pneumaticCraft/api/client/GuiAnimatedStatSupplier.java b/src/api/java/pneumaticCraft/api/client/GuiAnimatedStatSupplier.java new file mode 100644 index 00000000..4f88f0f2 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/GuiAnimatedStatSupplier.java @@ -0,0 +1,49 @@ +package pneumaticCraft.api.client; + +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.item.ItemStack; + +/** + * With this class you can retrieve new instances of the PneumaticCraft's IGuiAnimatedStat implementation. You can use these in Gui's as + * well as anywhere you like. When you use these in Gui's you need to pass a valid GuiScreen instance, if you don't you can just pass + * null. + */ +public class GuiAnimatedStatSupplier{ + private static Class animatedStatClass; + + public static IGuiAnimatedStat getAnimatedStat(GuiScreen gui, int backgroundColor){ + return getAnimatedStat(new Class[]{GuiScreen.class, int.class}, gui, backgroundColor); + } + + /** + * Returns a GuiAnimatedStat which uses an itemstack as static icon. + * @param gui + * @param iconStack + * @param backgroundColor + * @return + */ + public static IGuiAnimatedStat getAnimatedStat(GuiScreen gui, ItemStack iconStack, int backgroundColor){ + return getAnimatedStat(new Class[]{GuiScreen.class, int.class, ItemStack.class}, gui, backgroundColor, iconStack); + } + + /** + * Returns a GuiAnimatedStat which uses a texture location as static icon. + * @param gui + * @param iconTexture / text + * @param backgroundColor + * @return + */ + public static IGuiAnimatedStat getAnimatedStat(GuiScreen gui, String iconTexture, int backgroundColor){ + return getAnimatedStat(new Class[]{GuiScreen.class, int.class, String.class}, gui, backgroundColor, iconTexture); + } + + private static IGuiAnimatedStat getAnimatedStat(Class[] constructorClasses, Object... constructorParameters){ + try { + if(animatedStatClass == null) animatedStatClass = Class.forName("pneumaticCraft.client.gui.widget.GuiAnimatedStat"); + return (IGuiAnimatedStat)animatedStatClass.getConstructor(constructorClasses).newInstance(constructorParameters); + } catch(Exception e) { + System.err.println("Failed to retrieve an GuiAnimatedStat instance from PneumaticCraft."); + } + return null; + } +} diff --git a/src/api/java/pneumaticCraft/api/client/GuiElementRenderer.java b/src/api/java/pneumaticCraft/api/client/GuiElementRenderer.java new file mode 100644 index 00000000..ff590de2 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/GuiElementRenderer.java @@ -0,0 +1,32 @@ +package pneumaticCraft.api.client; + +import java.lang.reflect.Method; + +import net.minecraft.client.gui.FontRenderer; + +public class GuiElementRenderer{ + private static Method drawGaugeMethod; + + /** + * Draws a Pressure Gauge, the same which is also used in many PneumaticCraft applications. + * @param fontRenderer fontrenderer used to draw the numbers of the pressure gauge. + * @param minPressure The minimal pressure that needs to be displayed (this is -1 in most applications). + * @param maxPressure The maximal pressure that needs to be rendererd (this is 7 for tier one machines, and 25 for tier two). + * @param dangerPressure The transition pressure from green to red (this is 5 for tier one, and 29 for tier two machines). + * @param minWorkingPressure The transition pressure from yellow to green (variates per machine). + * @param currentPressure The pressure that the needle should point to. + * @param xPos x position of the gauge. + * @param yPos y position of the gauge. + * @param zLevel z position of the gauge (Gui#zLevel, -90, for in normal GUI's). + */ + public static void drawPressureGauge(FontRenderer fontRenderer, float minPressure, float maxPressure, float dangerPressure, float minWorkingPressure, float currentPressure, int xPos, int yPos, float zLevel){ + try { + if(drawGaugeMethod == null) { + drawGaugeMethod = Class.forName("pneumaticCraft.client.gui.GuiUtils").getMethod("drawPressureGauge", FontRenderer.class, float.class, float.class, float.class, float.class, float.class, int.class, int.class, float.class); + } + drawGaugeMethod.invoke(null, fontRenderer, minPressure, maxPressure, dangerPressure, minWorkingPressure, currentPressure, xPos, yPos, zLevel); + } catch(Exception e) { + System.err.println("Failed to render a Pressure Gauge from PneumaticCraft."); + } + } +} diff --git a/src/api/java/pneumaticCraft/api/client/IGuiAnimatedStat.java b/src/api/java/pneumaticCraft/api/client/IGuiAnimatedStat.java new file mode 100644 index 00000000..15d55c71 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/IGuiAnimatedStat.java @@ -0,0 +1,179 @@ +package pneumaticCraft.api.client; + +import java.awt.Rectangle; +import java.util.List; + +/** + * This interface doesn't have to be implemented. In PneumaticCraft there already is one class which implements this interface + * which is used many times in PneumaticCraft (GUI stats, Pneumatic Helmet 2D and 3D stats). You can get an instance of this + * class as well. Information about this you can find in GuiAnimatedStatSupplier.java. Implementing your own version of + * animated stats can be implemented as well via this interface, and they will interact with the PneumaticCraft GuiAnimatedStats + * if you implement it correctly. + */ + +public interface IGuiAnimatedStat{ + + /** + * When you call this method with a set of coordinates representing the button location and dimensions, you'll get + * these parameters back scaled to the GuiAnimatedStat's scale. + * @param origX Button start X. + * @param origY Button start Y. + * @param width Button width. + * @param height Button height. + * @return rectangle containing the new location and dimensions. + */ + public Rectangle getButtonScaledRectangle(int origX, int origY, int width, int height); + + /** + * When passed 0.5F for example, the text of the stat will be half as big (so more text can fit into a certain area). + * @param scale + */ + public void scaleTextSize(float scale); + + /** + * Returns true if the statistic expands to the left. + * @return + */ + public boolean isLeftSided(); + + /** + * Returns true if the statistic is done with expanding (when text will be displayed). + * @return + */ + public boolean isDoneExpanding(); + + /** + * Pass true if the statistic should expand to the left, otherwise false. + * @param leftSided + */ + public void setLeftSided(boolean leftSided); + + /** + * Sets the main text of this stat. Every line should be stored in a seperate list element. Upon rendering, + * EnumChatFormattings will be respected. When you call this method, Too long lines will be divided into multiple shorter ones + * to fit in the GUI. + * @param text + * @return this, so you can chain calls. + */ + public IGuiAnimatedStat setText(List text); + + /** + * Sets the line to a single line. Upon rendering, + * EnumChatFormattings will be respected. When you call this method, Too long lines will be divided into multiple shorter ones + * to fit in the GUI. + * @param text + * @return this, so you can chain calls. + */ + public IGuiAnimatedStat setText(String text); + + /** + * Sets the main text of this stat. Every line should be stored in a seperate list element. Upon rendering, + * EnumChatFormattings will be respected. This version of the text setting doesn't handle too long lines. + * @param text + */ + public void setTextWithoutCuttingString(List text); + + /** + * Sets the title of this stat. It will automatically get the yellow color assigned. + * @param title + */ + public void setTitle(String title); + + /** + * Returns the title of this stat (obviously without color prefix). + * @return + */ + public String getTitle(); + + /** + * Defines what dimensions the stat should have when it is not expanded (default 17x17) and resets the stat to these dimensions. + * Used in PneumaticCraft by the block/entity tracker stats, they are 0x0 when not expanded so it looks like they expand + * (and appear) from nothing. + * @param minWidth + * @param minHeight + */ + public void setMinDimensionsAndReset(int minWidth, int minHeight); + + /** + * When this stat gets a parent stat assigned, the y of this stat will be the same as the parent's plus this stat's + * baseY. This will cause this stat to move up and down when the parent's stat expands/moves. + * @param stat + */ + public void setParentStat(IGuiAnimatedStat stat); + + /** + * Sets the x location of this stat. + * @param x + */ + public void setBaseX(int x); + + /** + * Sets the base Y of this stat. + * @param y + */ + public void setBaseY(int y); + + /** + * Returns the real Y of this stat. This is the same as getBaseY when there is no parent stat, but if there is this method + * returns the value described in setParentStat(IGuiAnimatedStat stat). + * @return + */ + public int getAffectedY(); + + public int getBaseX(); + + public int getBaseY(); + + /** + * Returns the Y size of this stat. + * @return + */ + public int getHeight(); + + /** + * Returns the X size of this stat. + * @return + */ + public int getWidth(); + + public Rectangle getBounds(); + + /** + * This method should be called every game tick to update the logic of the stat (expanding of the stat). + */ + public void update(); + + /** + * Should be called every render tick when and where you want to render the stat. + * @param mouseX + * @param mouseY + * @param partialTicks + */ + public void render(int mouseX, int mouseY, float partialTicks); + + /** + * This method will handle mouse clicks. This will handle open/closing of the stat when the mouse clicks it. + * @param x + * @param y + * @param button + * @return + */ + public void onMouseClicked(int x, int y, int button); + + /** + * Forces the stat to close. + */ + public void closeWindow(); + + /** + * Forces the stat to expand. + */ + public void openWindow(); + + /** + * Returns true if the stat is expanding. + * @return + */ + public boolean isClicked(); + +} diff --git a/src/api/java/pneumaticCraft/api/client/assemblymachine/AssemblyRenderOverriding.java b/src/api/java/pneumaticCraft/api/client/assemblymachine/AssemblyRenderOverriding.java new file mode 100644 index 00000000..1816dc5b --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/assemblymachine/AssemblyRenderOverriding.java @@ -0,0 +1,55 @@ +package pneumaticCraft.api.client.assemblymachine; + +import java.util.HashMap; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class AssemblyRenderOverriding{ + public static final HashMap renderOverrides = new HashMap(); + + public static void addRenderOverride(Block block, IAssemblyRenderOverriding renderOverride){ + renderOverrides.put(Block.getIdFromBlock(block), renderOverride); + } + + public static void addRenderOverride(Item item, IAssemblyRenderOverriding renderOverride){ + renderOverrides.put(Item.getIdFromItem(item), renderOverride); + } + + public static interface IAssemblyRenderOverriding{ + /** + * This method will be called just before the IO Unit's held stack is being rendered. You can insert GL11 calls here to + * rotate the model for example. push and pop matrices are not needed, this is done for you. + * You can also choose to do the whole rendering yourself, you'll need to return false then to indicate that + * PneumaticCraft shouldn't render the item. + * @param renderedStack itemStack that is being rendered + * @return true if PneumaticCraft should render the item (after your changes), or false to cancel rendering. + */ + public boolean applyRenderChangeIOUnit(ItemStack renderedStack); + + /** + * Same deal as with the applyRenderChangeIOUnit(), but now for the Assembly Platform. + * @param renderedStack itemStack that is being rendered + * @return true if PneumaticCraft should render the item (after your changes), or false to cancel rendering. + */ + public boolean applyRenderChangePlatform(ItemStack renderedStack); + + /** + * Should return the distance the claw travels before it is gripped to the stack. + * By default it's 0.0875F for items and 0.00625F for blocks, 0.09375 when the claw is completely closed. + * @param renderedStack + * @return + */ + public float getIOUnitClawShift(ItemStack renderedStack); + + /** + * Should return the distance the claw travels before it is gripped to the stack. + * By default it's 0.0875F for items and 0.00625F for blocks, 0.09375 when the claw is completely closed. + * @param renderedStack + * @return + */ + public float getPlatformClawShift(ItemStack renderedStack); + + } +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IBlockTrackEntry.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IBlockTrackEntry.java new file mode 100644 index 00000000..6d9e1fe0 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IBlockTrackEntry.java @@ -0,0 +1,80 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public interface IBlockTrackEntry{ + /** + * This method should return true if the coordinate checked is one that + * should be tracked. Most entries will just return true when the blockID is + * the one that they track. + * + * @param world + * The world that is examined. + * @param x + * The x coordinate of the block examined. + * @param y + * The y coordinate of the block examined. + * @param z + * The z coordinate of the block examined. + * @param block + * The block of the current coordinate. This will save you a + * call to World.getBlock(). + * @param te The TileEntity at this x,y,z. + * @return true if the coordinate should be tracked by this BlockTrackEntry. + */ + public boolean shouldTrackWithThisEntry(IBlockAccess world, int x, int y, int z, Block block, TileEntity te); + + /** + * This method defines if the block should be updated by the server (each 5 + * seconds). This is specifically aimed at Tile Entities, as the server will + * send an NBT packet. This method returns true at for instance Chests and + * Mob Spawners, to get the inventory at the client side and the time to the + * next spawn respectively. + * @param te The TileEntity at the currently checked location. + * + * @return true if the Tile Entity should be updated, or false when it + * doesn't have to. + */ + public boolean shouldBeUpdatedFromServer(TileEntity te); + + /** + * The return of this method defines at how many tracked blocks of this type + * the HUD should stop displaying text at the tracked blocks of this type. + * + * @return amount of blocks the HUD should stop displaying the block info. + */ + public int spamThreshold(); + + /** + * This method is called each render tick to retrieve the blocks additional + * information. The method behaves the same as the addInformation method in + * the Item class. This method only will be called if + * shouldTrackWithThisEntry() returned true and the player hovers over the + * coordinate. + * + * @param world + * The world the block is in. + * @param x + * The x coordinate the block is at. + * @param y + * The y coordinate the block is at. + * @param z + * The z coordinate the block is at. + * @param te The TileEntity at the x,y,z. + * @param infoList + * The list of lines to display. + */ + public void addInformation(World world, int x, int y, int z, TileEntity te, List infoList); + + /** + * This method is called when displaying the currently tracked blocks. + * Will be tried to be mapped to the localization file first. + * @return the name of the group of this entry. + */ + public String getEntryName(); +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IEntityTrackEntry.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IEntityTrackEntry.java new file mode 100644 index 00000000..65c2b79e --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IEntityTrackEntry.java @@ -0,0 +1,49 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import java.util.List; + +import net.minecraft.entity.Entity; + +/** + * Implement this class and register it by adding it to the entityTrackEntries class. + * There needs to be a parameterless constructor. For every entity that's applicable for this definition, an instance is created. + */ +public interface IEntityTrackEntry{ + /** + * Return true if you want to add a tooltip for the given entity. + * @param entity + * @return + */ + public boolean isApplicable(Entity entity); + + /** + * Add info to the tab. This is only called when isApplicable returned true. + * @param entity + * @param curInfo + */ + public void addInfo(Entity entity, List curInfo); + + /** + * Update is called every (client) tick, and can be used to update something like a timer (used for the Creeper countdown). + * @param entity + */ + public void update(Entity entity); + + /** + * Called every render tick, this method can be used to render additional info. Used for Drone AI visualisation. + * @param entity + * @param partialTicks TODO + */ + public void render(Entity entity, float partialTicks); + + /** + * Just a basic implementation class that can be used if an update and render method isn't needed. + */ + public static abstract class EntityTrackEntry implements IEntityTrackEntry{ + @Override + public void update(Entity entity){} + + @Override + public void render(Entity entity, float partialTicks){} + } +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IGuiScreen.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IGuiScreen.java new file mode 100644 index 00000000..8f98938d --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IGuiScreen.java @@ -0,0 +1,15 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import java.util.List; + +import net.minecraft.client.gui.FontRenderer; + +/** + * Just an interface to give access to GuiSreen#buttonList and GuiScreen#fontRenderer. An instance of this class can + * safely be casted to GuiSreen if needed. + */ +public interface IGuiScreen{ + public List getButtonList(); + + public FontRenderer getFontRenderer(); +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableBlock.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableBlock.java new file mode 100644 index 00000000..9dc7863d --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableBlock.java @@ -0,0 +1,69 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +/** +Use this interface to specify any hackable block. When it's your block, you can simply implement this interface in the +block's class. If you don't have access to the class (vanilla blocks), you can implement this interface in a separate class +and register it using PneumaticRegistry.registry.addHackable(blockClass, IHackableBlockClass). With the former way there will be one instance only per type. In the latter, there will +be an IHackableBlock instance for every block. +*/ +public interface IHackableBlock{ + /** + * Should return a unique id to represent this hackable. Used in NBT saving to be able to trigger the afterHackTime after a server restart. + * Null is a valid return: afterHackTick will not be triggered at all in that case. + * + * CURRENTLY THIS ISN'T IMPLEMENTED. + * @return + */ + public String getId(); + + /** + Returning true will allow the player to hack this block. This can be used to only allow hacking on certain conditions. + */ + public boolean canHack(IBlockAccess world, int x, int y, int z, EntityPlayer player); + + /** + Add info that is displayed on the tracker tooltip here. Text like "Hack to explode" can be added. + This method is only called when canHack(World, int, int, int) returned true. + The added lines automatically will be tried to get localized. + */ + public void addInfo(World world, int x, int y, int z, List curInfo, EntityPlayer player); + + /** + * Add info that is being displayed after hacking, as long as 'afterHackTick' is returning true. + * Things like "Neutralized". + * The added lines automatically will be tried to get localized. + * @param entity + * @param curInfo + * @param player + */ + public void addPostHackInfo(World world, int x, int y, int z, List curInfo, EntityPlayer player); + + /** + Return the time it takes to hack this block in ticks. For more powerful hacks, a longer required hacking time is adviced. + */ + public int getHackTime(IBlockAccess world, int x, int y, int z, EntityPlayer player); + + /** + When the player hacked the block for getHackTime(World, int, int, int) ticks this will be called on both server and client side. + */ + public void onHackFinished(World world, int x, int y, int z, EntityPlayer player); + + /** + * Called every tick after the hacking finished (on both server and client side). Returning true will keep this going (for mob spawners, to keep them neutralized), + * or false to stop ticking (for door/lever hacking). + * + * CURRENTLY THIS METHOD WILL STOP GETTING INVOKED AFTER A SERVER RESTART! + * @param world + * @param x + * @param y + * @param z + * @return + */ + public boolean afterHackTick(World world, int x, int y, int z); +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableEntity.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableEntity.java new file mode 100644 index 00000000..e8aa236c --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IHackableEntity.java @@ -0,0 +1,59 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; + +/** +Use this interface to specify any hackable entity. When it's your entity, you can simply implement this interface in the +entity's class. If you don't have access to the class (vanilla entities), you can implement this interface in a separate class +and register it using PneumaticRegistry.registry.addHackable(entityClass, IHackableEntityClass). In both ways there will be an IHackableEntity instance for every entity. +*/ +public interface IHackableEntity{ + + /** + * Should return a unique id to represent this hackable. Used in NBT saving to be able to trigger the afterHackTime after a server restart. + * Null is a valid return: afterHackTick will not be triggered at all in that case. + * @return + */ + public String getId(); + + /** + Returning true will allow the player to hack this entity. This can be used to only allow hacking on certain conditions. + */ + public boolean canHack(Entity entity, EntityPlayer player); + + /** + Add info that is displayed on the tracker tooltip here. Text like "Hack to explode" can be added. + This method is only called when canHack(Entity) returned true. + The added lines automatically will be tried to get localized. + */ + public void addInfo(Entity entity, List curInfo, EntityPlayer player); + + /** + * Add info that is being displayed after hacking, as long as 'afterHackTick' is returning true. + * Things like "Neutralized". + * The added lines automatically will be tried to get localized. + * @param entity + * @param curInfo + * @param player + */ + public void addPostHackInfo(Entity entity, List curInfo, EntityPlayer player); + + /** + Return the time it takes to hack this entity in ticks. For more powerful hacks, a longer required hacking time is adviced. + */ + public int getHackTime(Entity entity, EntityPlayer player); + + /** + When the player hacked the entity for getHackTime(Entity) ticks this will be called on both client and server side. + */ + public void onHackFinished(Entity entity, EntityPlayer player); + + /** + * Called every tick after the hacking finished. Returning true will keep this going (for mob spawners, to keep them neutralized), + * or false to stop ticking (for door/lever hacking). + */ + public boolean afterHackTick(Entity entity); +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IOptionPage.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IOptionPage.java new file mode 100644 index 00000000..2212749e --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IOptionPage.java @@ -0,0 +1,46 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; + +/** + * The Option Page is the page you see when you press 'F' (by default) with a Pneumatic Helmet equipped. You can register this class + * by returning a new instance of this class at {@link IUpgradeRenderHandler#getGuiOptionsPage()} + */ +public interface IOptionPage{ + + /** + * This string is used in the text of the button of this page. + * @return + */ + public String getPageName(); + + /** + * Here you can initialize your buttons and stuff like with a GuiScreen. For buttons, don't use button id 100 and up, as they + * will be used as selection buttons for other option pages in the main GuiScreen. + * @param gui + */ + public void initGui(IGuiScreen gui); + + /** + * Same as GuiScreen#actionPerformed(GuiButton). + * @param button + */ + public void actionPerformed(GuiButton button); + + /** + * Same as {@link GuiScreen#drawScreen(int, int, float)} + * Here you can render additional things like text. + * @param x + * @param y + * @param partialTicks + */ + public void drawScreen(int x, int y, float partialTicks); + + /** + * Same as GuiScreen#keyTyped(char, int). + * @param ch + * @param key + */ + public void keyTyped(char ch, int key); +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IUpgradeRenderHandler.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IUpgradeRenderHandler.java new file mode 100644 index 00000000..d273baf3 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/IUpgradeRenderHandler.java @@ -0,0 +1,92 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.config.Configuration; +import pneumaticCraft.api.client.IGuiAnimatedStat; + +/** + * To add upgrades for in the Pneumatic Helmet implement this interface. You can add members to this class, however these can only + * be client sided members as this class will be used as singleton. Therefore, only one of these instances exist at the server side + * so any member that is used server side will affect every player. + * + */ +public interface IUpgradeRenderHandler{ + + /** + * Return here the name of the upgrade. This is displayed in the formatting [upgradeName] + " " + "found"/"not found" on + * initialization of the helmet. + * @return + */ + public String getUpgradeName(); + + /** + * Being called from PneumaticCraft's config handler, you can use this method to read settings like stat positions + * @param config PneumaticCraft's config file. + */ + public void initConfig(Configuration config); + + /** + * When called this should save the settings to the config file. Called when changed a setting. When you want to use + * PneumaticCraft's config file, save a reference of it somewhere in this class when the config gets passed in the + * initConfig() method (this always will be called first). + */ + public void saveToConfig(); + + /** + * This method will be called every client tick, and should be used to update logic like the tracking and velocities of stuff. + * @param player + * @param rangeUpgrades amount of range upgrades installed in the helmet. + */ + public void update(EntityPlayer player, int rangeUpgrades); + + /** + * Called in the 3D render stage (renderWorldLastEvent) + * @param partialTicks + */ + public void render3D(float partialTicks); + + /** + * Called in the 2D render stage (Render Tick Handler) + * @param partialTicks + * @param helmetEnabled is true when isEnabled() returned true earlier. Can be used to close AnimatedStats for instance. + * However this is already handled if you return an AnimatedStat in getAnimatedStat(). + */ + public void render2D(float partialTicks, boolean helmetEnabled); + + /** + * You can return a GuiAnimatedStat here, that the HUDHandler will pick up and render. It also automatically opens and closes + * the stat when needed. The GuiMoveStat uses this method to retrieve the to be moved stat. + * @return null if no stat used. + */ + public IGuiAnimatedStat getAnimatedStat(); + + /** + * Should return true if this upgrade handler is enabled for the given stacks placed in the helmet. + * @param upgradeStacks + * @return + */ + public boolean isEnabled(ItemStack[] upgradeStacks); + + /** + * Returns the usage in mL/tick when this upgrade handler is enabled. + * @param rangeUpgrades amount of range upgrades installed in the helmet. + * @param player + * @return usage in mL/tick + */ + public float getEnergyUsage(int rangeUpgrades, EntityPlayer player); + + /** + * Called when (re-)equipped the helmet this method should be used to clear information like current tracked entities. + * So clearing lists and other references as this handler should re-acquire when reinstalled. + */ + public void reset(); + + /** + * When you have some options for your upgrade handler you could return a new instance of an IOptionsPage. + * When you do so, it will automatically get picked up by the options handler, and it will be added to the + * options GUI when this upgrade returns true when calling isEnabled(). Returning null is valid. + * @return + */ + public IOptionPage getGuiOptionsPage(); +} diff --git a/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/RenderHandlerRegistry.java b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/RenderHandlerRegistry.java new file mode 100644 index 00000000..acb1cdc5 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/client/pneumaticHelmet/RenderHandlerRegistry.java @@ -0,0 +1,10 @@ +package pneumaticCraft.api.client.pneumaticHelmet; + +import java.util.List; + +public class RenderHandlerRegistry{ + /** + * With this field you can register your render handlers. This field is initialized in the PreInit phase of PneumaticCraft's loading phase. + */ + public static List renderHandlers; +} diff --git a/src/api/java/pneumaticCraft/api/drone/DroneConstructingEvent.java b/src/api/java/pneumaticCraft/api/drone/DroneConstructingEvent.java new file mode 100644 index 00000000..801c55a4 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/DroneConstructingEvent.java @@ -0,0 +1,11 @@ +package pneumaticCraft.api.drone; + +import cpw.mods.fml.common.eventhandler.Event; + +public class DroneConstructingEvent extends Event{ + public IDrone drone; + + public DroneConstructingEvent(IDrone drone){ + this.drone = drone; + } +} diff --git a/src/api/java/pneumaticCraft/api/drone/IBlockInteractHandler.java b/src/api/java/pneumaticCraft/api/drone/IBlockInteractHandler.java new file mode 100644 index 00000000..5e4eb245 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/IBlockInteractHandler.java @@ -0,0 +1,26 @@ +package pneumaticCraft.api.drone; + +/** + * DON'T IMPLEMENT, just use + */ +public interface IBlockInteractHandler{ + + /** + * Returns a boolean[6] of all sides. when true, this side is accessible + * @return + */ + public boolean[] getSides(); + + public boolean useCount(); + + public void decreaseCount(int count); + + public int getRemainingCount(); + + /** + * When invoked, the drone will abort searching the area. Could be used to abort early when full of RF energy for example, when importing RF. + * (It's useless to search any further) + */ + public void abort(); + +} diff --git a/src/api/java/pneumaticCraft/api/drone/ICustomBlockInteract.java b/src/api/java/pneumaticCraft/api/drone/ICustomBlockInteract.java new file mode 100644 index 00000000..2960425e --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/ICustomBlockInteract.java @@ -0,0 +1,45 @@ +package pneumaticCraft.api.drone; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.ChunkPosition; + +/** + * Implement this and register it to PneumaticRegistry.registerCustomBlockInteractor(). + * This will add a puzzle piece that has only a Area white- and blacklist parameter (similar to a GoTo piece). + * It will do the specified behaviour. This can be used to create energy import/export widgets. + */ +public interface ICustomBlockInteract{ + + /** + * Should return a unique Id, used in NBT saving and localization. + */ + public String getName(); + + /** + * Should return the puzzle piece texture. Should be a multiple of 80x64 (width x height). I'd recommend starting out with copying the Go To widget texture. + * @return + */ + public ResourceLocation getTexture(); + + /** + * The actual interaction. + * + * For every position in the selected area the drone will visit every block (ordered from closest to furthest). It will call this method with 'simulate = true'. If this method returns true, the drone will navigate to this location, and call this method again with 'simulate = false' It will keep doing this until this method returns false. + * + * When interactHandler.useCount() returns true: + * In the interface of the puzzle piece users can specify a 'use count' and fill in the maximum count they want to use. When not simulating, you should only import/export up to interactHandler.getRemainingCount(), and you should notify the removed/added count by doing interactHandler.decreaseCount(int count). + * + * @param pos current visited location + * @param drone + * @param interactHandler object you can use to use to get accessible sides and give feedback about counts. + * @param simulate will be true when trying to figure out whether or not the drone should navigate to this block, false when next to this block. + * @return + */ + public boolean doInteract(ChunkPosition pos, IDrone drone, IBlockInteractHandler interactHandler, boolean simulate); + + /** + * Used for crafting, categorizes the puzzle piece. + * @return + */ + public int getCraftingColorIndex(); +} diff --git a/src/api/java/pneumaticCraft/api/drone/IDrone.java b/src/api/java/pneumaticCraft/api/drone/IDrone.java new file mode 100644 index 00000000..306bc6c0 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/IDrone.java @@ -0,0 +1,61 @@ +package pneumaticCraft.api.drone; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.ai.EntityAITasks; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import net.minecraftforge.common.IExtendedEntityProperties; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.IFluidTank; +import pneumaticCraft.api.item.IPressurizable; + +public interface IDrone extends IPressurizable{ + /** + * + * @param upgradeIndex metadata value of the upgrade item + * @return amount of inserted upgrades in the drone + */ + public int getUpgrades(int upgradeIndex); + + public World getWorld(); + + public IFluidTank getTank(); + + public IInventory getInventory(); + + public Vec3 getPosition(); + + public IPathNavigator getPathNavigator(); + + public void sendWireframeToClient(int x, int y, int z); + + public EntityPlayerMP getFakePlayer(); + + public boolean isBlockValidPathfindBlock(int x, int y, int z); + + public void dropItem(ItemStack stack); + + public void setDugBlock(int x, int y, int z); + + public EntityAITasks getTargetAI(); + + public IExtendedEntityProperties getProperty(String key); + + public void setProperty(String key, IExtendedEntityProperties property); + + public void setEmittingRedstone(ForgeDirection orientation, int emittingRedstone); + + public void setName(String string); + + public void setCarryingEntity(Entity entity); + + public Entity getCarryingEntity(); + + public boolean isAIOverriden(); + + public void onItemPickupEvent(EntityItem curPickingUpEntity, int stackSize); +} diff --git a/src/api/java/pneumaticCraft/api/drone/IPathNavigator.java b/src/api/java/pneumaticCraft/api/drone/IPathNavigator.java new file mode 100644 index 00000000..f089bae5 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/IPathNavigator.java @@ -0,0 +1,11 @@ +package pneumaticCraft.api.drone; + +import net.minecraft.entity.Entity; + +public interface IPathNavigator{ + public boolean moveToXYZ(double x, double y, double z); + + public boolean moveToEntity(Entity entity); + + public boolean hasNoPath(); +} diff --git a/src/api/java/pneumaticCraft/api/drone/IPathfindHandler.java b/src/api/java/pneumaticCraft/api/drone/IPathfindHandler.java new file mode 100644 index 00000000..a5bcfabb --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/IPathfindHandler.java @@ -0,0 +1,26 @@ +package pneumaticCraft.api.drone; + +import net.minecraft.world.World; + +public interface IPathfindHandler{ + /** + * When returned true, the drone can pathfind through this block. When false it can't. + * @param world + * @param x + * @param y + * @param z + * @return + */ + public boolean canPathfindThrough(World world, int x, int y, int z); + + /** + * CURRENTLY NOT IMPLEMENTED! + * Will be called every tick as long as the drone is < 1 block away from the given coordinate. + * can be used to open a door for a drone for example. + * @param world + * @param x + * @param y + * @param z + */ + public void onPathingThrough(World world, int x, int y, int z); +} diff --git a/src/api/java/pneumaticCraft/api/drone/SpecialVariableRetrievalEvent.java b/src/api/java/pneumaticCraft/api/drone/SpecialVariableRetrievalEvent.java new file mode 100644 index 00000000..83581c81 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/drone/SpecialVariableRetrievalEvent.java @@ -0,0 +1,60 @@ +package pneumaticCraft.api.drone; + +import net.minecraft.item.ItemStack; +import net.minecraft.world.ChunkPosition; +import cpw.mods.fml.common.eventhandler.Event; + +/** + * Fired when a Drone is trying to get a special coordinate, by accessing a variable with '$' prefix. + * These event are posted on the MinecraftForge.EVENT_BUS. + */ +public abstract class SpecialVariableRetrievalEvent extends Event{ + + /** + * The special variable name, with the '$' stripped away. + */ + public final String specialVarName; + + /** + * The returning coordinate + */ + + public SpecialVariableRetrievalEvent(String specialVarName){ + + this.specialVarName = specialVarName; + } + + public static abstract class CoordinateVariable extends SpecialVariableRetrievalEvent{ + public ChunkPosition coordinate; + + public CoordinateVariable(String specialVarName){ + super(specialVarName); + } + + public static class Drone extends CoordinateVariable{ + public final IDrone drone; + + public Drone(IDrone drone, String specialVarName){ + super(specialVarName); + this.drone = drone; + } + } + } + + public static abstract class ItemVariable extends SpecialVariableRetrievalEvent{ + public ItemStack item; + + public ItemVariable(String specialVarName){ + super(specialVarName); + } + + public static class Drone extends ItemVariable{ + public final IDrone drone; + + public Drone(IDrone drone, String specialVarName){ + super(specialVarName); + this.drone = drone; + } + } + } +} diff --git a/src/api/java/pneumaticCraft/api/item/IInventoryItem.java b/src/api/java/pneumaticCraft/api/item/IInventoryItem.java new file mode 100644 index 00000000..b153e022 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/item/IInventoryItem.java @@ -0,0 +1,20 @@ +package pneumaticCraft.api.item; + +import java.util.List; + +import net.minecraft.item.ItemStack; + +/** + * Implement this interface for your items that have an inventory. When you don't have access to the item, just create any old class + * that implements this interface and register an instance of it in PneumaticRegistry. + * This will then will be used in the Pneumatic Helmet's item search. + * + */ +public interface IInventoryItem{ + + /** + * @parm stack: Item that potentially has an inventory. + * @parm curStacks: List of all currently added stacks for this item. Add more stacks in here in your implementation when found the right item. + */ + public void getStacksInItem(ItemStack stack, List curStacks); +} diff --git a/src/api/java/pneumaticCraft/api/item/IPressurizable.java b/src/api/java/pneumaticCraft/api/item/IPressurizable.java new file mode 100644 index 00000000..027aaad1 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/item/IPressurizable.java @@ -0,0 +1,35 @@ +package pneumaticCraft.api.item; + +import net.minecraft.item.ItemStack; + +/** + * Any item implementing this interface will be able to (dis)charge in a Charging Station. + */ +public interface IPressurizable{ + /** + * This method should return the current pressure of the ItemStack given. + * + * @param iStack Stack the pressure is asked from. + * @return Pressure in bar. + */ + public float getPressure(ItemStack iStack); + + /** + * this method is used to charge or discharge a pneumatic item. when the + * value is negative the item should be discharging + * + * @param iStack the ItemStack which has to be (dis)charged. + * @param amount amount in mL that the item is (dis)charging. + */ + public void addAir(ItemStack iStack, int amount); + + /** + * This method should return the maximum pressure of a pneumatic item. If it + * has reached this maximum, it won't explode, but it wouldn't (try to) + * charge either. + * + * @param iStack the stack from which the maximum pressure is asked. + * @return maximum pressure in bar. + */ + public float maxPressure(ItemStack iStack); +} diff --git a/src/api/java/pneumaticCraft/api/item/IProgrammable.java b/src/api/java/pneumaticCraft/api/item/IProgrammable.java new file mode 100644 index 00000000..d00d94c3 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/item/IProgrammable.java @@ -0,0 +1,34 @@ +package pneumaticCraft.api.item; + +import net.minecraft.item.ItemStack; + +/** + * Implement this for items that can get programmed in a Programmer. + * For now the only thing you can do with this is make program storages, later more interaction with programming puzzles is planned. + * Puzzle pieces will be written onto the implementer's itemstack NBT, using the "progWidget" tag. + */ +public interface IProgrammable{ + + /** + * When returned true, this stack is allowed to be programmed. + * Used to allow certain damage values to be programmed while others can't. + * @param stack + * @return + */ + public boolean canProgram(ItemStack stack); + + /** + * When returned true, Programming Puzzles are needed to program this item. When returned false, it's free to program. + * Drones and Network API's return true in PneumaticCraft, Network Storages return false. + * @param stack + * @return + */ + public boolean usesPieces(ItemStack stack); + + /** + * When returned true, the implementing item will get a tooltip added of the summary of puzzles used in the stored program. + * @return + */ + public boolean showProgramTooltip(); + +} diff --git a/src/api/java/pneumaticCraft/api/item/ItemSupplier.java b/src/api/java/pneumaticCraft/api/item/ItemSupplier.java new file mode 100644 index 00000000..93c13fb5 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/item/ItemSupplier.java @@ -0,0 +1,47 @@ +package pneumaticCraft.api.item; + +import net.minecraft.item.Item; +import cpw.mods.fml.common.registry.GameRegistry; + +public class ItemSupplier{ + public static Item getItem(String itemName){ + return GameRegistry.findItem("PneumaticCraft", itemName); + } + + /* + The following is a list of all the item names that can be passed as argument in getItem(String) to get a PneumaticCraft item. + + GPSTool Currently tracked coordinated is stored in NBT, with 'x', 'y', 'z' being the tag names for the x,y and z positions respectively. + machineUpgrade damage value = upgrade type. + ingotIronCompressed + pressureGauge + stoneBase + cannonBarrel + turbineBlade + plasticPlant damage value = plant type. Mapped the same as Vanilla dye in terms of color. + plastic damage value = plastic type. Mapped the same as Vanilla dye in terms of color. + airCanister implements IPressurizable + vortexCannon implements IPressurizable + pneumaticCylinder + pneumaticHelmet implements IPressurizable + manometer implements IPressurizable + turbineRotor + assemblyProgram damage value = program type. + emptyPCB + unassembledPCB + PCBBlueprint + bucketEtchingAcid + transistor + capacitor + printedCircuitBoard + failedPCB + networkComponent damage value = network component type. + stopWorm + nukeVirus + compressedIronGear + pneumaticWrench implements IPressurizable + + + + */ +} diff --git a/src/api/java/pneumaticCraft/api/package-info.java b/src/api/java/pneumaticCraft/api/package-info.java new file mode 100644 index 00000000..55919456 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/package-info.java @@ -0,0 +1,5 @@ +@API(apiVersion = "1.0", owner = "PneumaticCraft", provides = "PneumaticCraftApi") +package pneumaticCraft.api; + +import cpw.mods.fml.common.API; + diff --git a/src/api/java/pneumaticCraft/api/recipe/AssemblyRecipe.java b/src/api/java/pneumaticCraft/api/recipe/AssemblyRecipe.java new file mode 100644 index 00000000..8c74b4bb --- /dev/null +++ b/src/api/java/pneumaticCraft/api/recipe/AssemblyRecipe.java @@ -0,0 +1,49 @@ +package pneumaticCraft.api.recipe; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class AssemblyRecipe{ + public static List drillRecipes = new ArrayList(); + public static List laserRecipes = new ArrayList(); + public static List drillLaserRecipes = new ArrayList(); + + private final ItemStack input; + private final ItemStack output; + + public AssemblyRecipe(ItemStack input, ItemStack output){ + this.input = input; + this.output = output; + } + + public ItemStack getInput(){ + return input; + } + + public ItemStack getOutput(){ + return output; + } + + public static void addDrillRecipe(Object input, Object output){ + drillRecipes.add(new AssemblyRecipe(getStackFromObject(input), getStackFromObject(output))); + } + + public static void addLaserRecipe(Object input, Object output){ + laserRecipes.add(new AssemblyRecipe(getStackFromObject(input), getStackFromObject(output))); + } + + private static ItemStack getStackFromObject(Object object){ + if(object instanceof Block) { + return new ItemStack((Block)object); + } else if(object instanceof Item) { + return new ItemStack((Item)object); + } else { + return (ItemStack)object; + } + } + +} diff --git a/src/api/java/pneumaticCraft/api/recipe/IPressureChamberRecipe.java b/src/api/java/pneumaticCraft/api/recipe/IPressureChamberRecipe.java new file mode 100644 index 00000000..93eba67c --- /dev/null +++ b/src/api/java/pneumaticCraft/api/recipe/IPressureChamberRecipe.java @@ -0,0 +1,34 @@ +package pneumaticCraft.api.recipe; + +import net.minecraft.item.ItemStack; + +public interface IPressureChamberRecipe{ + + /** + * Returns the threshold which is minimal to craft the recipe. Negative pressures also work. + * @return threshold pressure + */ + public float getCraftingPressure(); + + /** + * This method should return the used items in the recipe when the right items are provided to craft this recipe. + * @param inputStacks + * @return usedStacks, return null when the inputStacks aren't valid for this recipe. + */ + public ItemStack[] isValidRecipe(ItemStack[] inputStacks); + + /** + * When returned true, only the exact same references of the stacks returned by isValidRecipe() will be removed. This is useful + * to remove stacks with a certain NBT value (like Enchanted Books). Return false for normal behaviour. + * @return true if exact stacks should be removed only. + */ + public boolean shouldRemoveExactStacks(); + + /** + * This method will be called when the recipe should output its items. the stacks the recipe output, may be dependent on the input stacks. + * @param removedStacks same reference to the stacks returned by isValidRecipe. + * @param inputStacks. These stacks can be modified (like adding/removing NBT data eg.) + * @return outputStacks. Stacks that will pop 'out of the chamber' + */ + public ItemStack[] craftRecipe(ItemStack[] inputStacks, ItemStack[] removedStacks); +} diff --git a/src/api/java/pneumaticCraft/api/recipe/PressureChamberRecipe.java b/src/api/java/pneumaticCraft/api/recipe/PressureChamberRecipe.java new file mode 100644 index 00000000..5d6b29e5 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/recipe/PressureChamberRecipe.java @@ -0,0 +1,24 @@ +package pneumaticCraft.api.recipe; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.item.ItemStack; + +public class PressureChamberRecipe{ + public static List chamberRecipes = new ArrayList(); + public static List specialRecipes = new ArrayList(); + + public final ItemStack[] input; + public final ItemStack[] output; + public final float pressure; + public final boolean outputAsBlock; + + public PressureChamberRecipe(ItemStack[] input, float pressureRequired, ItemStack[] output, boolean outputAsBlock){ + this.input = input; + this.output = output; + pressure = pressureRequired; + this.outputAsBlock = outputAsBlock; + } + +} diff --git a/src/api/java/pneumaticCraft/api/tileentity/AirHandlerSupplier.java b/src/api/java/pneumaticCraft/api/tileentity/AirHandlerSupplier.java new file mode 100644 index 00000000..1bf1be74 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/tileentity/AirHandlerSupplier.java @@ -0,0 +1,51 @@ +package pneumaticCraft.api.tileentity; + +import java.lang.reflect.Constructor; + +public class AirHandlerSupplier{ + private static Constructor airHandlerConstructor; + + public static IAirHandler getTierOneAirHandler(int volume){ + return getAirHandler(5F, 7F, volume); + } + + public static IAirHandler getTierTwoAirHandler(int volume){ + return getAirHandler(20F, 25F, volume); + } + + /** + * Returns a new instance of an IAirHandler. This handler handles everything pressurized air related: Air dispersion, + * blowing up when the pressure gets too high, providing a method for releasing air into the atmosphere... + * PROVIDED THAT THE FOLLOWING METHODS ARE FORWARDED TO THIS INSTANCE: + * {@link net.minecraft.tileentity.TileEntity#updateEntity()}, + * {@link net.minecraft.tileentity.TileEntity#writeToNBT(net.minecraft.nbt.NBTTagCompound)} + * {@link net.minecraft.tileentity.TileEntity#readFromNBT(net.minecraft.nbt.NBTTagCompound)} + * {@link net.minecraft.tileentity.TileEntity#validate()} + * @param dangerPressure minimal pressure on which this machine can explode (the yellow to red transition) + * @param criticalPressure the absolute maximum pressure the machine can take 7 bar in tier 1 machines. + * @param maxFlow maximum mL/tick that this machine can disperse. Tier one machines do 50mL/tick while Tier two have 200mL/tick. + * @param volume Volume of the machine's internal storage. These vary from 1000mL for small machines to 10,000mL for the big ones. + * The higher the volume the slower the machine will charge/discharge. + * @return + */ + public static IAirHandler getAirHandler(float dangerPressure, float criticalPressure, int volume){ + IAirHandler airHandler = null; + try { + if(airHandlerConstructor == null) airHandlerConstructor = Class.forName("pneumaticCraft.common.tileentity.TileEntityPneumaticBase").getConstructor(float.class, float.class, int.class); + airHandler = (IAirHandler)airHandlerConstructor.newInstance(dangerPressure, criticalPressure, volume); + } catch(Exception e) { + System.err.println("[PneumaticCraft API] An error has occured whilst trying to get an AirHandler. Here's a stacktrace:"); + e.printStackTrace(); + } + return airHandler; + } + + /** + * Use the version with integer parameters + */ + @Deprecated + public static IAirHandler getAirHandler(float dangerPressure, float criticalPressure, float maxFlow, float volume){ + return getAirHandler(dangerPressure, criticalPressure, (int)volume); + } + +} diff --git a/src/api/java/pneumaticCraft/api/tileentity/IAirHandler.java b/src/api/java/pneumaticCraft/api/tileentity/IAirHandler.java new file mode 100644 index 00000000..72929e90 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/tileentity/IAirHandler.java @@ -0,0 +1,114 @@ +package pneumaticCraft.api.tileentity; + +import java.util.List; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; + +import org.apache.commons.lang3.tuple.Pair; + +/** + * A way for you to access about everything you need from a pneumatic machine. + * DO NOT IMPLEMENT THIS YOURSELF! Use AirHandlerSupplier to get an instance for your TileEntity, and implement IPneumaticMachine instead. + */ + +public interface IAirHandler extends IManoMeasurable{ + + /** + * -----------Needs to be forwarded by the implementing TileEntity's updateEntity() method. + * Updates the pneumatic machine's logic like air dispersion and checking if it needs to explode. + */ + public void updateEntityI(); + + /** + * -----------Needs to be forwarded by the implementing TileEntity. + * @param nbt + */ + public void readFromNBTI(NBTTagCompound nbt); + + /** + * -----------Needs to be forwarded by the implementing TileEntity. + * @param nbt + */ + public void writeToNBTI(NBTTagCompound nbt); + + /** + * -----------Needs to be forwarded by the implementing TileEntity with itself as parameter. + * @param parent TileEntity that is referencing this air handler. + */ + public void validateI(TileEntity parent); + + /** + * Method to release air in the air. It takes air from a specific side, plays a sound effect, and spawns smoke particles. + * It automatically detects if it needs to release air (when under pressure), suck air (when in vacuum) or do nothing. + * @param side + */ + public void airLeak(ForgeDirection side); + + /** + * Returns a list of all the connecting pneumatics. It takes sides in account. + */ + public List> getConnectedPneumatics(); + + /** + * Adds air to the tank of the given side of this TE. It also updates clients where needed (when they have a GUI opened). + * Deprecated: use the version with the integer parameter now. + * @param amount + * @param side + */ + @Deprecated + public void addAir(float amount, ForgeDirection side); + + public void addAir(int amount, ForgeDirection side); + + /** + * Sets the volume of this TE's air tank. When the volume decreases the pressure will remain the same, meaning air will + * be lost. When the volume increases, the air remains the same, meaning the pressure will drop. + * Used in the Volume Upgrade calculations. + * Deprecated: use the version with the integer parameter now. + * @param newVolume + */ + @Deprecated + public void setVolume(float newVolume); + + public void setVolume(int newVolume); + + public int getVolume(); + + /** + * Returns the pressure at which this TE will explode. + * @return + */ + public float getMaxPressure(); + + public float getPressure(ForgeDirection sideRequested); + + /** + * Returns the amount of air (that has a relation to the pressure: air = pressure * volume) + * @param sideRequested + * @return + */ + public int getCurrentAir(ForgeDirection sideRequested); + + /** + * When your TileEntity is implementing IInventory and has slots that accept PneumaticCraft upgrades, register these slots + * to the air handler by calling this method once on initialization of the TileEntity. Then they'll automatically be used to get Volume/Security upgrades. + * @param upgradeSlots all upgrade slots stored in an array. + */ + public void setUpgradeSlots(int... upgradeSlots); + + public int[] getUpgradeSlots(); + + public int getXCoord(); + + public int getYCoord(); + + public int getZCoord(); + + /** + * Needs to be forwarded from the implementing _Block_! Forward the Block's "onNeighborChange" method to this handler. + */ + public void onNeighborChange(); + +} diff --git a/src/api/java/pneumaticCraft/api/tileentity/IHeatExchanger.java b/src/api/java/pneumaticCraft/api/tileentity/IHeatExchanger.java new file mode 100644 index 00000000..60df395c --- /dev/null +++ b/src/api/java/pneumaticCraft/api/tileentity/IHeatExchanger.java @@ -0,0 +1,24 @@ +package pneumaticCraft.api.tileentity; + +import net.minecraftforge.common.util.ForgeDirection; +import pneumaticCraft.api.IHeatExchangerLogic; + +/** + * Implemented by TileEntities or Blocks which transport heat. Keep in mind that when a Block is implementing it you only can give off a constant + * resistance/temperature (like Lava and Ice). + * @author MineMaarten + * www.minemaarten.com + */ +public interface IHeatExchanger{ + + /** + * Get an instance of IHeatExchangerLogic from PneumaticRegistry.getInstance().getHeatExchangerLogic() and keep a global reference. + * Then return it in this method. You can return different exchanger logics for different sides. Keep in mind that when you change + * a returned logic, you need to create a neighbor block change to notify the differences. You can return null to indicate no heat can + * be exchanged on that side. + * @param side + * @return + */ + public IHeatExchangerLogic getHeatExchangerLogic(ForgeDirection side); + +} diff --git a/src/api/java/pneumaticCraft/api/tileentity/IManoMeasurable.java b/src/api/java/pneumaticCraft/api/tileentity/IManoMeasurable.java new file mode 100644 index 00000000..c5178abe --- /dev/null +++ b/src/api/java/pneumaticCraft/api/tileentity/IManoMeasurable.java @@ -0,0 +1,14 @@ +package pneumaticCraft.api.tileentity; + +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; + +public interface IManoMeasurable{ + /** + * This method is invoked by the Manometer when a player right-clicks a TE or Entity with this interface implemented. + * @param player that rightclicks the measurable TE, and therefore needs to get the message + * @param curInfo list you can append info to. If you don't append any info no air will be used. + */ + public void printManometerMessage(EntityPlayer player, List curInfo); +} diff --git a/src/api/java/pneumaticCraft/api/tileentity/IPneumaticMachine.java b/src/api/java/pneumaticCraft/api/tileentity/IPneumaticMachine.java new file mode 100644 index 00000000..0e283115 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/tileentity/IPneumaticMachine.java @@ -0,0 +1,30 @@ +package pneumaticCraft.api.tileentity; + +import net.minecraftforge.common.util.ForgeDirection; + +public interface IPneumaticMachine{ + + /** + * In your TileEntity class which is implementing this interface you should keep a reference of an IAirHandler. + * You can retrieve one by calling {@link AirHandlerSupplier#getAirHandler(net.minecraft.tileentity.TileEntity, float, float, float, float)}. + * Do this when your TileEntity is initialized, i.e. xCoord,yCoord,zCoord and worldObj have a value. + * In this method you need to return this reference. + * + * IMPORTANT: You need to forward the {@link net.minecraft.tileentity.TileEntity#updateEntity()}, + * {@link net.minecraft.tileentity.TileEntity#writeToNBT(net.minecraft.nbt.NBTTagCompound)} , + * {@link net.minecraft.tileentity.TileEntity#readFromNBT(net.minecraft.nbt.NBTTagCompound)} and + * {@link net.minecraft.tileentity.TileEntity#validate()} (with the implementing TileEntity as additional parameter) + * to the IAirHandler. + * Apart from that you'll need to forward {@link net.minecraft.block.Block#onNeighborChange(net.minecraft.world.IBlockAccess, int, int, int, int, int, int)} + * from the implementing block to the IAirHandler. + * @return + */ + public IAirHandler getAirHandler(); + + /** + * Returns true if the pneumatic logic is connected to the given side. + * @param side + * @return + */ + public boolean isConnectedTo(ForgeDirection side); +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/EntityPollSensor.java b/src/api/java/pneumaticCraft/api/universalSensor/EntityPollSensor.java new file mode 100644 index 00000000..0419911f --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/EntityPollSensor.java @@ -0,0 +1,31 @@ +package pneumaticCraft.api.universalSensor; + +import java.util.List; + +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; + +public abstract class EntityPollSensor implements IPollSensorSetting{ + + @Override + public String getSensorPath(){ + return "entityTracker"; + } + + @Override + public int getPollFrequency(){ + return 1; + } + + @Override + public int getRedstoneValue(World world, int x, int y, int z, int sensorRange, String textBoxText){ + AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(x - sensorRange, y - sensorRange, z - sensorRange, x + 1 + sensorRange, y + 1 + sensorRange, z + 1 + sensorRange); + return getRedstoneValue(world.getEntitiesWithinAABB(getEntityTracked(), aabb), textBoxText); + } + + public abstract Class getEntityTracked(); + + public abstract int getRedstoneValue(List entities, String textBoxText); + +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinateEventSensor.java b/src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinateEventSensor.java new file mode 100644 index 00000000..2f225c5a --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinateEventSensor.java @@ -0,0 +1,59 @@ +package pneumaticCraft.api.universalSensor; + +import java.util.List; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.tileentity.TileEntity; + +import org.lwjgl.util.Rectangle; + +import cpw.mods.fml.common.eventhandler.Event; + +public interface IBlockAndCoordinateEventSensor{ + /** + * See {@link ISensorSetting#getSensorPath()} + * @return + */ + public String getSensorPath(); + + /** + * Extended version of the normal emitRedstoneOnEvent. This method will only invoke with a valid GPS tool, and when the coordinate is within range. + * @param event + * @param sensor + * @param range + * @param toolX + * @param toolY + * @param toolZ + * @return + */ + public int emitRedstoneOnEvent(Event event, TileEntity sensor, int range, int toolX, int toolY, int toolZ); + + /** + * See {@link IEventSensorSetting#getRedstonePulseLength()} + * @return + */ + public int getRedstonePulseLength(); + + /** + * See {@link ISensorSetting#needsTextBox()} + * @return + */ + public boolean needsTextBox(); + + /** + * See {@link ISensorSetting#needsSlot()} + */ + public Rectangle needsSlot(); + + /** + * See {@link ISensorSetting#getDescription()} + * @return + */ + public List getDescription(); + + /** + * Called by GuiScreen#drawScreen this method can be used to render additional things like status/info text. + * @param fontRenderer + */ + public void drawAdditionalInfo(FontRenderer fontRenderer); +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinatePollSensor.java b/src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinatePollSensor.java new file mode 100644 index 00000000..e7bc329e --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/IBlockAndCoordinatePollSensor.java @@ -0,0 +1,63 @@ +package pneumaticCraft.api.universalSensor; + +import java.util.List; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.world.World; + +import org.lwjgl.util.Rectangle; + +public interface IBlockAndCoordinatePollSensor{ + /** + * See {@link ISensorSetting#getSensorPath()} + * @return + */ + public String getSensorPath(); + + /** + * See {@link ISensorSetting#needsTextBox()} + * @return + */ + public boolean needsTextBox(); + + /** + * See {@link ISensorSetting#needsSlot()} + * @return + */ + public Rectangle needsSlot(); + + /** + * See {@link ISensorSetting#getDescription()} + * @return + */ + public List getDescription(); + + /** + * See {@link IPollSensorSetting#getRedstoneValue(World, int, int, int, int, String)} , but this has the GPS tracked coordinates + * as extra parameters. This method will only be called when the coordinate is within the Universal Sensor's range. + * @param world + * @param x + * @param y + * @param z + * @param sensorRange + * @param textBoxText + * @param toolX + * @param toolY + * @param toolZ + * @return + */ + public int getRedstoneValue(World world, int x, int y, int z, int sensorRange, String textBoxText, int toolX, int toolY, int toolZ); + + /** + * See {@link IPollSensorSetting#getPollFrequency()} + * @return + */ + public int getPollFrequency(); + + /** + * Called by GuiScreen#drawScreen this method can be used to render additional things like status/info text. + * @param fontRenderer + */ + public void drawAdditionalInfo(FontRenderer fontRenderer); + +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/IEventSensorSetting.java b/src/api/java/pneumaticCraft/api/universalSensor/IEventSensorSetting.java new file mode 100644 index 00000000..bce3017a --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/IEventSensorSetting.java @@ -0,0 +1,23 @@ +package pneumaticCraft.api.universalSensor; + +import net.minecraft.tileentity.TileEntity; +import cpw.mods.fml.common.eventhandler.Event; + +public interface IEventSensorSetting extends ISensorSetting{ + + /** + * This method is only invoked when a subscribed event is triggered. + * @param event + * @param sensor + * @param range + * @param textboxText + * @return Redstone strength for the given event. + */ + public int emitRedstoneOnEvent(Event event, TileEntity sensor, int range, String textboxText); + + /** + * Should return how long a pulse should hold in ticks. By default this is 5 ticks (1/4 second). + * @return + */ + public int getRedstonePulseLength(); +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/IPollSensorSetting.java b/src/api/java/pneumaticCraft/api/universalSensor/IPollSensorSetting.java new file mode 100644 index 00000000..50cf8305 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/IPollSensorSetting.java @@ -0,0 +1,27 @@ +package pneumaticCraft.api.universalSensor; + +import net.minecraft.world.World; + +public interface IPollSensorSetting extends ISensorSetting{ + + /** + * The value returned here is the interval between every check in ticks (the interval of calling getRedstoneValue()). + * Consider increasing the interval when your sensor method is resource intensive. + * @return + */ + public int getPollFrequency(); + + /** + * The base method. This method should return the outputted redstone value 0-15 of this sensor. When this sensor is + * digital, just return 0 or 15. + * @param world + * @param x + * @param y + * @param z + * @param sensorRange Range of the sensor, based on the amount of Range Upgrades inserted in the Universal Sensor. + * @param textBoxText The text typed in the textbox of the Universal Sensor. + * @return + */ + public int getRedstoneValue(World world, int x, int y, int z, int sensorRange, String textBoxText); + +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/ISensorSetting.java b/src/api/java/pneumaticCraft/api/universalSensor/ISensorSetting.java new file mode 100644 index 00000000..bfbf3468 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/ISensorSetting.java @@ -0,0 +1,59 @@ +package pneumaticCraft.api.universalSensor; + +import java.util.List; + +import net.minecraft.client.gui.FontRenderer; + +import org.lwjgl.util.Rectangle; + +public interface ISensorSetting{ + /** + * Should return the button path the player has to follow in which this setting is stored. + * For instance, when the sensor should be located in player and is called speed, you should return "entityTracker/player/speed". + * "entityTracker" indicates that this sensor needs an Entity Tracker upgrade to run. You can choose from the following upgrades: + * + * -entityTracker + * -blockTracker + * -gpsTool (so you can use a certain coordinate (within range) to measure on) + * -volume + * -dispenser + * -speed + * -itemLife + * -itemSearch + * -coordinateTracker + * -range + * -security + * + * You can allow only sensors to work by more than one upgrade, by seperating the upgrades with a '_'. For example, + * "entityTracker_speed" will only let the sensor be chosen when both an Entity Tracker and a Speed Upgrade are inserted. + * @return + */ + public String getSensorPath(); + + /** + * When returned true, the GUI will enable the textbox writing, otherwise not. + * @return + */ + public boolean needsTextBox(); + + /** + * Called by GuiScreen#drawScreen this method can be used to render additional things like status/info text. + * @param fontRenderer + */ + public void drawAdditionalInfo(FontRenderer fontRenderer); + + /** + * Should return the description of this sensor displayed in the GUI stat. Information should at least include + * when this sensor emits redstone and how (analog (1 through 15), or digital). + * @return + */ + public List getDescription(); + + /** + * Not being used at the moment, I recommend returning null for now. It is going to be used to allow sensors to decide their + * status on a item which can be inserted in a slot in the GUI if this method returns a rectangle with the coordinates of + * the slot. + * @return + */ + public Rectangle needsSlot(); +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/PlayerEventSensor.java b/src/api/java/pneumaticCraft/api/universalSensor/PlayerEventSensor.java new file mode 100644 index 00000000..19bda915 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/PlayerEventSensor.java @@ -0,0 +1,33 @@ +package pneumaticCraft.api.universalSensor; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.event.entity.player.PlayerEvent; +import cpw.mods.fml.common.eventhandler.Event; + +public abstract class PlayerEventSensor implements IEventSensorSetting{ + + @Override + public String getSensorPath(){ + return "entityTracker/Player"; + } + + @Override + public int emitRedstoneOnEvent(Event event, TileEntity sensor, int range, String textboxText){ + if(event instanceof PlayerEvent) { + EntityPlayer player = ((PlayerEvent)event).entityPlayer; + if(Math.abs(player.posX - sensor.xCoord + 0.5D) < range + 0.5D && Math.abs(player.posY - sensor.yCoord + 0.5D) < range + 0.5D && Math.abs(player.posZ - sensor.zCoord + 0.5D) < range + 0.5D) { + return emitRedstoneOnEvent((PlayerEvent)event, sensor, range); + } + } + return 0; + } + + public abstract int emitRedstoneOnEvent(PlayerEvent event, TileEntity sensor, int range); + + @Override + public int getRedstonePulseLength(){ + return 5; + } + +} diff --git a/src/api/java/pneumaticCraft/api/universalSensor/SensorRegistrator.java b/src/api/java/pneumaticCraft/api/universalSensor/SensorRegistrator.java new file mode 100644 index 00000000..f76c0732 --- /dev/null +++ b/src/api/java/pneumaticCraft/api/universalSensor/SensorRegistrator.java @@ -0,0 +1,33 @@ +package pneumaticCraft.api.universalSensor; + +/** + * With this class you can register your own sensors. + */ +public class SensorRegistrator{ + /** + * This field will be initialized in the PreInit phase of PneumaticCraft's loading phase. + * With this field you can register every Universal Sensor sensor you want. Just pass a new instance + * to one of the registerSensor methods. Sensors are singletons. + */ + public static ISensorRegistrator sensorRegistrator; + + public static interface ISensorRegistrator{ + /** + * Registry for IPollSensorSetting, EntityPollSensor and IEventSensorSetting, and any other instance of ISensorSetting. + * @param sensor + */ + public void registerSensor(ISensorSetting sensor); + + /** + * Registry for IBlockAndCoordinateEventSensor + * @param sensor + */ + public void registerSensor(IBlockAndCoordinateEventSensor sensor); + + /** + * Registry for IBlockAndCoordinatePollSensor + * @param sensor + */ + public void registerSensor(IBlockAndCoordinatePollSensor sensor); + } +} diff --git a/src/main/java/WayofTime/alchemicalWizardry/AlchemicalWizardry.java b/src/main/java/WayofTime/alchemicalWizardry/AlchemicalWizardry.java index c828d45b..79e2c6f3 100644 --- a/src/main/java/WayofTime/alchemicalWizardry/AlchemicalWizardry.java +++ b/src/main/java/WayofTime/alchemicalWizardry/AlchemicalWizardry.java @@ -417,6 +417,7 @@ public class AlchemicalWizardry public static boolean isForestryLoaded; public static boolean isBotaniaLoaded; public static boolean isFMPLoaded; + public static boolean isPneumaticCraftLoaded; public static boolean wimpySettings; public static boolean respawnWithDebuff; @@ -1264,8 +1265,10 @@ public class AlchemicalWizardry } isBotaniaLoaded = Loader.isModLoaded("Botania"); - + isPneumaticCraftLoaded = Loader.isModLoaded("PneumaticCraft"); isFMPLoaded = Loader.isModLoaded("ForgeMultipart"); + + BloodMagicConfiguration.loadBlacklist(); BloodMagicConfiguration.blacklistRituals(); diff --git a/src/main/java/WayofTime/alchemicalWizardry/api/guide/PageRitualMultiBlock.java b/src/main/java/WayofTime/alchemicalWizardry/api/guide/PageRitualMultiBlock.java index c23a066f..bc0269c0 100644 --- a/src/main/java/WayofTime/alchemicalWizardry/api/guide/PageRitualMultiBlock.java +++ b/src/main/java/WayofTime/alchemicalWizardry/api/guide/PageRitualMultiBlock.java @@ -58,11 +58,13 @@ public class PageRitualMultiBlock extends PageMultiBlock maxZ = Math.max(comp.getZ(), maxZ); } + System.out.println("Min: (" + minX + ", " + minY + ", " + minZ + "), Max: (" + maxX + ", " + maxY + ", " + maxZ + ")"); + ItemStack[][][] tempStructure = new ItemStack[maxY-minY+1][maxX-minX+1][maxZ-minZ+1]; //First value is vertical, second is down to the left, third is down to the right for(RitualComponent comp : ritualComponents) { - tempStructure[comp.getY() - minY][comp.getX() - minX][comp.getZ() - minZ] = new ItemStack(ModBlocks.ritualStone, 1, comp.getStoneType()); + tempStructure[comp.getY() - minY][comp.getX() - minX][comp.getZ() - minZ] = getStackForRitualStone(comp.getStoneType()); } tempStructure[-minY][-minX][-minZ] = new ItemStack(ModBlocks.blockMasterStone); diff --git a/src/main/java/WayofTime/alchemicalWizardry/common/book/BloodMagicGuide.java b/src/main/java/WayofTime/alchemicalWizardry/common/book/BloodMagicGuide.java index ada145eb..2273e856 100644 --- a/src/main/java/WayofTime/alchemicalWizardry/common/book/BloodMagicGuide.java +++ b/src/main/java/WayofTime/alchemicalWizardry/common/book/BloodMagicGuide.java @@ -12,7 +12,6 @@ import WayofTime.alchemicalWizardry.ModBlocks; import WayofTime.alchemicalWizardry.ModItems; import WayofTime.alchemicalWizardry.api.guide.PageAltarRecipe; import WayofTime.alchemicalWizardry.api.guide.PageOrbRecipe; -import WayofTime.alchemicalWizardry.api.guide.PageRitualMultiBlock; import WayofTime.alchemicalWizardry.common.guide.RecipeHolder; import amerifrance.guideapi.api.GuideRegistry; import amerifrance.guideapi.api.abstraction.CategoryAbstract; @@ -346,9 +345,9 @@ public class BloodMagicGuide { List entries = new ArrayList(); - ArrayList testPages = new ArrayList(); - testPages.add(PageRitualMultiBlock.getPageForRitual("AW031Convocation")); - entries.add(new EntryUniText(testPages, "Test page")); +// ArrayList testPages = new ArrayList(); +// testPages.add(PageRitualMultiBlock.getPageForRitual("AW031Convocation")); +// entries.add(new EntryUniText(testPages, "Test page")); ArrayList introPages = new ArrayList(); @@ -373,9 +372,225 @@ public class BloodMagicGuide entries.add(new EntryUniText(waterRitualPages, "guide.BloodMagic.entryName.rituals.waterRitual")); ArrayList lavaRitualPages = new ArrayList(); - lavaRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/lava.png"), true)); + lavaRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Lava.png"), true)); lavaRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.lavaRitual"))); entries.add(new EntryUniText(lavaRitualPages, "guide.BloodMagic.entryName.rituals.lavaRitual")); + + ArrayList groveRitualPages = new ArrayList(); + groveRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/GreenGrove.png"), true)); + groveRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.groveRitual"))); + entries.add(new EntryUniText(groveRitualPages, "guide.BloodMagic.entryName.rituals.groveRitual")); + + ArrayList interdictionRitualPages = new ArrayList(); + interdictionRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Interdiction.png"), true)); + interdictionRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.interdictionRitual"))); + entries.add(new EntryUniText(interdictionRitualPages, "guide.BloodMagic.entryName.rituals.interdictionRitual")); + + ArrayList containmentRitualPages = new ArrayList(); + containmentRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Containment.png"), true)); + containmentRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.containmentRitual"))); + entries.add(new EntryUniText(containmentRitualPages, "guide.BloodMagic.entryName.rituals.containmentRitual")); + + ArrayList bindingRitualPages = new ArrayList(); + bindingRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Binding.png"), true)); + bindingRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.bindingRitual"))); + entries.add(new EntryUniText(bindingRitualPages, "guide.BloodMagic.entryName.rituals.bindingRitual")); + + ArrayList beastModePages = new ArrayList(); + beastModePages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.beastMode"))); + entries.add(new EntryUniText(beastModePages, "guide.BloodMagic.entryName.rituals.beastMode")); + + ArrayList unbindingRitualPages = new ArrayList(); + unbindingRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Unbinding.png"), true)); + unbindingRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.unbindingRitual"))); + entries.add(new EntryUniText(unbindingRitualPages, "guide.BloodMagic.entryName.rituals.unbindingRitual")); + + ArrayList jumpRitualPages = new ArrayList(); + jumpRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Jump.png"), true)); + jumpRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.jumpRitual"))); + entries.add(new EntryUniText(jumpRitualPages, "guide.BloodMagic.entryName.rituals.jumpRitual")); + + ArrayList duskInkPages = new ArrayList(); + duskInkPages.add(new PageAltarRecipe(RecipeHolder.duskRecipe)); + duskInkPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.duskInk"))); + entries.add(new EntryUniText(duskInkPages, "guide.BloodMagic.entryName.rituals.duskInk")); + + ArrayList magnetismRitualPages = new ArrayList(); + magnetismRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Magnetism.png"), true)); + magnetismRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.magnetismRitual"))); + entries.add(new EntryUniText(magnetismRitualPages, "guide.BloodMagic.entryName.rituals.magnetismRitual")); + + ArrayList crusherRitualPages = new ArrayList(); + crusherRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Crusher.png"), true)); + crusherRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.crusherRitual"))); + entries.add(new EntryUniText(crusherRitualPages, "guide.BloodMagic.entryName.rituals.crusherRitual")); + + ArrayList speedRitualPages = new ArrayList(); + speedRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Speed.png"), true)); + speedRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.speedRitual"))); + entries.add(new EntryUniText(speedRitualPages, "guide.BloodMagic.entryName.rituals.speedRitual")); + + ArrayList shepherdRitualPages = new ArrayList(); + shepherdRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/AnimalGrowth.png"), true)); + shepherdRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.shepherdRitual"))); + entries.add(new EntryUniText(shepherdRitualPages, "guide.BloodMagic.entryName.rituals.shepherdRitual")); + + ArrayList darkMagicPages = new ArrayList(); + darkMagicPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.darkMagic"))); + entries.add(new EntryUniText(darkMagicPages, "guide.BloodMagic.entryName.rituals.darkMagic")); + + ArrayList knifeAndSufferingRitualPages = new ArrayList(); + knifeAndSufferingRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/WellOfSuffering.png"), true)); + knifeAndSufferingRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.knifeAndSufferingRitual.1"))); + knifeAndSufferingRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/FeatheredKnife.png"), true)); + knifeAndSufferingRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.knifeAndSufferingRitual.2"))); + entries.add(new EntryUniText(knifeAndSufferingRitualPages, "guide.BloodMagic.entryName.rituals.knifeAndSufferingRitual")); + + ArrayList regenerationRitualPages = new ArrayList(); + regenerationRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Regeneration.png"), true)); + regenerationRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.regenerationRitual"))); + entries.add(new EntryUniText(regenerationRitualPages, "guide.BloodMagic.entryName.rituals.regenerationRitual")); + + ArrayList harvestFestivalPages = new ArrayList(); + harvestFestivalPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.harvestFestival"))); + entries.add(new EntryUniText(harvestFestivalPages, "guide.BloodMagic.entryName.rituals.harvestFestival")); + + ArrayList thenThereWereFivePages = new ArrayList(); + thenThereWereFivePages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.thenThereWereFive"))); + entries.add(new EntryUniText(thenThereWereFivePages, "guide.BloodMagic.entryName.rituals.thenThereWereFive")); + + ArrayList alchemyRitualPages = new ArrayList(); + alchemyRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Alchemy.png"), true)); + alchemyRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.alchemyRitual"))); + entries.add(new EntryUniText(alchemyRitualPages, "guide.BloodMagic.entryName.rituals.alchemyRitual")); + + ArrayList domeRitualPages = new ArrayList(); + domeRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Dome.png"), true)); + domeRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.domeRitual"))); + entries.add(new EntryUniText(domeRitualPages, "guide.BloodMagic.entryName.rituals.domeRitual")); + + ArrayList awakenedCrystalPages = new ArrayList(); + awakenedCrystalPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.awakenedCrystal"))); + entries.add(new EntryUniText(awakenedCrystalPages, "guide.BloodMagic.entryName.rituals.awakenedCrystal")); + + ArrayList featheredEarthRitualPages = new ArrayList(); + featheredEarthRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/FeatheredEarth.png"), true)); + featheredEarthRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.featheredEarthRitual"))); + entries.add(new EntryUniText(featheredEarthRitualPages, "guide.BloodMagic.entryName.rituals.featheredEarthRitual")); + + ArrayList gaiaRitualPages = new ArrayList(); + gaiaRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Gaia.png"), true)); + gaiaRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.gaiaRitual"))); + entries.add(new EntryUniText(gaiaRitualPages, "guide.BloodMagic.entryName.rituals.gaiaRitual")); + + ArrayList condorRitualPages = new ArrayList(); + condorRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Flight.png"), true)); + condorRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.condorRitual"))); + entries.add(new EntryUniText(condorRitualPages, "guide.BloodMagic.entryName.rituals.condorRitual")); + + ArrayList meteorRitualPages = new ArrayList(); + meteorRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Meteor.png"), true)); + meteorRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.meteorRitual"))); + entries.add(new EntryUniText(meteorRitualPages, "guide.BloodMagic.entryName.rituals.meteorRitual")); + + ArrayList expulsionRitualPages = new ArrayList(); + expulsionRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Expulsion.png"), true)); + expulsionRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.expulsionRitual"))); + entries.add(new EntryUniText(expulsionRitualPages, "guide.BloodMagic.entryName.rituals.expulsionRitual")); + + ArrayList costOfProgressPages = new ArrayList(); + costOfProgressPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.costOfProgress.1"))); + costOfProgressPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.costOfProgress.2"))); + entries.add(new EntryUniText(costOfProgressPages, "guide.BloodMagic.entryName.rituals.costOfProgress")); + + ArrayList zephyrRitualPages = new ArrayList(); + zephyrRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Zeohyr.png"), true)); + zephyrRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.zephyrRitual"))); + entries.add(new EntryUniText(zephyrRitualPages, "guide.BloodMagic.entryName.rituals.zephyrRitual")); + + ArrayList harvestRitualPages = new ArrayList(); + harvestRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Harvest.png"), true)); + harvestRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.harvestRitual"))); + entries.add(new EntryUniText(harvestRitualPages, "guide.BloodMagic.entryName.rituals.harvestRitual")); + + ArrayList eternalSoulRitualPages = new ArrayList(); + eternalSoulRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/EternalSoul.png"), true)); + eternalSoulRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.eternalSoulRitual"))); + entries.add(new EntryUniText(eternalSoulRitualPages, "guide.BloodMagic.entryName.rituals.eternalSoulRitual")); + + ArrayList ellipsoidRitualPages = new ArrayList(); + ellipsoidRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Ellipsoid.png"), true)); + ellipsoidRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.ellipsoidRitual"))); + entries.add(new EntryUniText(ellipsoidRitualPages, "guide.BloodMagic.entryName.rituals.ellipsoidRitual")); + + ArrayList evaporationRitualPages = new ArrayList(); + evaporationRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Evaporation.png"), true)); + evaporationRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.evaporationRitual"))); + entries.add(new EntryUniText(evaporationRitualPages, "guide.BloodMagic.entryName.rituals.evaporationRitual")); + + ArrayList sacrosanctityRitualPages = new ArrayList(); + sacrosanctityRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Sacrosanctity.png"), true)); + sacrosanctityRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.sacrosanctityRitual"))); + entries.add(new EntryUniText(sacrosanctityRitualPages, "guide.BloodMagic.entryName.rituals.sacrosanctityRitual")); + + ArrayList evilRitualPages = new ArrayList(); + evilRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/VeilOfEvil.png"), true)); + evilRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.evilRitual"))); + entries.add(new EntryUniText(evilRitualPages, "guide.BloodMagic.entryName.rituals.evilRitual")); + + ArrayList stomachRitualPages = new ArrayList(); + stomachRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Stomach.png"), true)); + stomachRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.stomachRitual"))); + entries.add(new EntryUniText(stomachRitualPages, "guide.BloodMagic.entryName.rituals.stomachRitual")); + + ArrayList reagentEffectsRitualPages = new ArrayList(); + for(int i=1; i<=24; i++) + { + reagentEffectsRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.reagentEffects." + i))); + } + entries.add(new EntryUniText(reagentEffectsRitualPages, "guide.BloodMagic.entryName.rituals.reagentEffects")); + + ArrayList conclaveOfMagesPages = new ArrayList(); + conclaveOfMagesPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.conclaveOfMages"))); + entries.add(new EntryUniText(conclaveOfMagesPages, "guide.BloodMagic.entryName.rituals.conclaveOfMages")); + + ArrayList forbiddenParadisePages = new ArrayList(); + forbiddenParadisePages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.forbiddenParadise"))); + entries.add(new EntryUniText(forbiddenParadisePages, "guide.BloodMagic.entryName.rituals.forbiddenParadise")); + + ArrayList convocationRitualPages = new ArrayList(); + convocationRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/Convocation.png"), true)); + convocationRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.convocationRitual"))); + entries.add(new EntryUniText(convocationRitualPages, "guide.BloodMagic.entryName.rituals.convocationRitual")); + + ArrayList longHaulPages = new ArrayList(); + longHaulPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.longHaul"))); + entries.add(new EntryUniText(longHaulPages, "guide.BloodMagic.entryName.rituals.longHaul")); + + ArrayList phantomHandsRitualPages = new ArrayList(); + phantomHandsRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/PhantomHands.png"), true)); + phantomHandsRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.phantomHandsRitual"))); + entries.add(new EntryUniText(phantomHandsRitualPages, "guide.BloodMagic.entryName.rituals.phantomHandsRitual")); + + ArrayList anvilRitualPages = new ArrayList(); + anvilRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/BeatingAnvil.png"), true)); + anvilRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.anvilRitual"))); + entries.add(new EntryUniText(anvilRitualPages, "guide.BloodMagic.entryName.rituals.anvilRitual")); + + ArrayList dawnInkPages = new ArrayList(); + dawnInkPages.add(new PageAltarRecipe(RecipeHolder.dawnRecipe)); + dawnInkPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.dawnInk"))); + entries.add(new EntryUniText(dawnInkPages, "guide.BloodMagic.entryName.rituals.dawnInk")); + + ArrayList symmetryRitualPages = new ArrayList(); + symmetryRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/SymmetryOmega.png"), true)); + symmetryRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.symmetryRitual"))); + entries.add(new EntryUniText(lavaRitualPages, "guide.BloodMagic.entryName.rituals.symmetryRitual")); + + ArrayList stallingRitualPages = new ArrayList(); + stallingRitualPages.add(new PageUnlocImage("", new ResourceLocation("alchemicalwizardry:textures/misc/screenshots/rituals/StallingOmega.png"), true)); + stallingRitualPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.stallingRitual"))); + entries.add(new EntryUniText(stallingRitualPages, "guide.BloodMagic.entryName.rituals.stallingRitual")); categories.add(new CategoryItemStack(entries, "guide.BloodMagic.category.rituals", new ItemStack(ModBlocks.blockMasterStone))); } diff --git a/src/main/java/WayofTime/alchemicalWizardry/common/entity/mob/MailOrderEntityItem.java b/src/main/java/WayofTime/alchemicalWizardry/common/entity/mob/MailOrderEntityItem.java index d49fe19b..6a12f1fb 100644 --- a/src/main/java/WayofTime/alchemicalWizardry/common/entity/mob/MailOrderEntityItem.java +++ b/src/main/java/WayofTime/alchemicalWizardry/common/entity/mob/MailOrderEntityItem.java @@ -1,11 +1,15 @@ package WayofTime.alchemicalWizardry.common.entity.mob; -import WayofTime.alchemicalWizardry.ModItems; +import pneumaticCraft.api.PneumaticRegistry; +import cpw.mods.fml.common.Optional; import net.minecraft.entity.Entity; import net.minecraft.entity.effect.EntityLightningBolt; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.world.World; +import WayofTime.alchemicalWizardry.AlchemicalWizardry; +import WayofTime.alchemicalWizardry.common.book.BloodMagicGuide; +import amerifrance.guideapi.api.GuideRegistry; public class MailOrderEntityItem extends EntityItem { @@ -46,13 +50,26 @@ public class MailOrderEntityItem extends EntityItem if(!worldObj.isRemote && this.ticksExisted > 100 && !this.isDead) { - worldObj.addWeatherEffect(new EntityLightningBolt(worldObj, this.posX, this.posY, this.posZ)); - EntityItem entity = new BookEntityItem(worldObj, this.posX, this.posY, this.posZ, new ItemStack(ModItems.itemBloodMagicBook)); - entity.lifespan = 6000; - entity.delayBeforeCanPickup = 20; - entity.motionY = 1; - worldObj.spawnEntityInWorld(entity); + if(AlchemicalWizardry.isPneumaticCraftLoaded) + { + this.deliverItemViaDrone(this.posX, this.posY, this.posZ); + }else + { + worldObj.addWeatherEffect(new EntityLightningBolt(worldObj, this.posX, this.posY, this.posZ)); + EntityItem entity = new BookEntityItem(worldObj, this.posX, this.posY, this.posZ, GuideRegistry.getItemStackForBook(BloodMagicGuide.bloodMagicGuide)); + entity.lifespan = 6000; + entity.delayBeforeCanPickup = 20; + entity.motionY = 1; + worldObj.spawnEntityInWorld(entity); + } + this.setDead(); } } + + @Optional.Method(modid = "PneumaticCraft") + public void deliverItemViaDrone(double x, double y, double z) + { + PneumaticRegistry.getInstance().deliverItemsAmazonStyle(worldObj, (int)x, (int)y, (int)z, GuideRegistry.getItemStackForBook(BloodMagicGuide.bloodMagicGuide)); + } } \ No newline at end of file diff --git a/src/main/java/WayofTime/alchemicalWizardry/common/guide/RecipeHolder.java b/src/main/java/WayofTime/alchemicalWizardry/common/guide/RecipeHolder.java index f515a45d..b76f1a5d 100644 --- a/src/main/java/WayofTime/alchemicalWizardry/common/guide/RecipeHolder.java +++ b/src/main/java/WayofTime/alchemicalWizardry/common/guide/RecipeHolder.java @@ -77,6 +77,8 @@ public class RecipeHolder public static AltarRecipe weakActivationRecipe; public static AltarRecipe filledSocketRecipe; public static AltarRecipe teleposerFocusRecipe1; + public static AltarRecipe duskRecipe; + public static AltarRecipe dawnRecipe; public static void init() { @@ -144,6 +146,8 @@ public class RecipeHolder weakActivationRecipe = getAltarRecipeForItemStack(new ItemStack(ModItems.activationCrystal, 1, 0)); filledSocketRecipe = getAltarRecipeForItemStack(new ItemStack(ModBlocks.bloodSocket)); teleposerFocusRecipe1 = getAltarRecipeForItemStack(new ItemStack(ModItems.telepositionFocus)); + duskRecipe = getAltarRecipeForItemStack(new ItemStack(ModItems.duskScribeTool)); + dawnRecipe = getAltarRecipeForItemStack(new ItemStack(ModItems.dawnScribeTool)); } private static IRecipe getRecipeForItemStack(ItemStack stack) diff --git a/src/main/resources/assets/alchemicalwizardryBooks/lang/en_US.lang b/src/main/resources/assets/alchemicalwizardryBooks/lang/en_US.lang index cb42d082..7d750e4d 100644 --- a/src/main/resources/assets/alchemicalwizardryBooks/lang/en_US.lang +++ b/src/main/resources/assets/alchemicalwizardryBooks/lang/en_US.lang @@ -203,51 +203,51 @@ guide.BloodMagic.entryName.rituals.intro=Introduction guide.BloodMagic.entryName.rituals.weakRitual=Weak Rituals guide.BloodMagic.entryName.rituals.rituals=Rituals guide.BloodMagic.entryName.rituals.waterRitual=Ritual of the Full Spring -guide.BloodMagic.entryName.rituals.lavaRitual= -guide.BloodMagic.entryName.rituals.groveRitual= -guide.BloodMagic.entryName.rituals.interdictionRitual= -guide.BloodMagic.entryName.rituals.containmentRitual= -guide.BloodMagic.entryName.rituals.bindingRitual= -guide.BloodMagic.entryName.rituals.beastMode= -guide.BloodMagic.entryName.rituals.unbindingRitual= -guide.BloodMagic.entryName.rituals.jumpRitual= -guide.BloodMagic.entryName.rituals.duskInk= -guide.BloodMagic.entryName.rituals.magnetismRitual= -guide.BloodMagic.entryName.rituals.crusherRitual= -guide.BloodMagic.entryName.rituals.speedRitual= -guide.BloodMagic.entryName.rituals.shepherdRitual= -guide.BloodMagic.entryName.rituals.darkMagic= -guide.BloodMagic.entryName.rituals.knifeAndSufferingRitual= -guide.BloodMagic.entryName.rituals.regenerationRitual= -guide.BloodMagic.entryName.rituals.harvestFestival= -guide.BloodMagic.entryName.rituals.thenThereWereFive= -guide.BloodMagic.entryName.rituals.alchemyRitual= -guide.BloodMagic.entryName.rituals.domeRitual= -guide.BloodMagic.entryName.rituals.awakenedCrystal= -guide.BloodMagic.entryName.rituals.featheredEarthRitual= -guide.BloodMagic.entryName.rituals.gaiaRitual= -guide.BloodMagic.entryName.rituals.condorRitual= -guide.BloodMagic.entryName.rituals.meteorRitual= -guide.BloodMagic.entryName.rituals.expulsionRitual= -guide.BloodMagic.entryName.rituals.costOfProgress= -guide.BloodMagic.entryName.rituals.zephyrRitual= -guide.BloodMagic.entryName.rituals.harvestRitual= -guide.BloodMagic.entryName.rituals.eternalSoulRitual= -guide.BloodMagic.entryName.rituals.ellipsoidRitual= -guide.BloodMagic.entryName.rituals.evaporationRitual= -guide.BloodMagic.entryName.rituals.sacrosanctityRitual= -guide.BloodMagic.entryName.rituals.evilRitual= -guide.BloodMagic.entryName.rituals.stomachRitual= -guide.BloodMagic.entryName.rituals.reagentEffects= -guide.BloodMagic.entryName.rituals.conclaveOfMages= -guide.BloodMagic.entryName.rituals.forbiddenParadise= -guide.BloodMagic.entryName.rituals.convocationRitual= -guide.BloodMagic.entryName.rituals.longHaul= -guide.BloodMagic.entryName.rituals.phantomHandsRitual= -guide.BloodMagic.entryName.rituals.anvilRitual= -guide.BloodMagic.entryName.rituals.dawnInk= -guide.BloodMagic.entryName.rituals.symmetryRitual= -guide.BloodMagic.entryName.rituals.stallingRitual= +guide.BloodMagic.entryName.rituals.lavaRitual=Serenade of the Nether +guide.BloodMagic.entryName.rituals.groveRitual=Ritual of the Green Grove +guide.BloodMagic.entryName.rituals.interdictionRitual=Ritual of Interdiction +guide.BloodMagic.entryName.rituals.containmentRitual=Ritual of Containment +guide.BloodMagic.entryName.rituals.bindingRitual=Ritual of Binding +guide.BloodMagic.entryName.rituals.beastMode=Beast Mode +guide.BloodMagic.entryName.rituals.unbindingRitual=Ritual of Unbinding +guide.BloodMagic.entryName.rituals.jumpRitual=Ritual of the High Jump +guide.BloodMagic.entryName.rituals.duskInk=Dusk Ink +guide.BloodMagic.entryName.rituals.magnetismRitual=Ritual of Magnetism +guide.BloodMagic.entryName.rituals.crusherRitual=Ritual of the Crusher +guide.BloodMagic.entryName.rituals.speedRitual=Ritual of Speed +guide.BloodMagic.entryName.rituals.shepherdRitual=Ritual of the Shepherd +guide.BloodMagic.entryName.rituals.darkMagic=Dark Side of Magic +guide.BloodMagic.entryName.rituals.knifeAndSufferingRitual=Feathered Knife and Well of Suffering +guide.BloodMagic.entryName.rituals.regenerationRitual=Ritual of Regeneration +guide.BloodMagic.entryName.rituals.harvestFestival=The Hell's Harvest Festival +guide.BloodMagic.entryName.rituals.thenThereWereFive=And Then there were Five +guide.BloodMagic.entryName.rituals.alchemyRitual=The Ballad of Alchemy +guide.BloodMagic.entryName.rituals.domeRitual=Dome of Suppression +guide.BloodMagic.entryName.rituals.awakenedCrystal=Awakened Activation Crystal +guide.BloodMagic.entryName.rituals.featheredEarthRitual=Ritual of the Feathered Earth +guide.BloodMagic.entryName.rituals.gaiaRitual=Gaia's Transformation +guide.BloodMagic.entryName.rituals.condorRitual=Reverence of the Condor +guide.BloodMagic.entryName.rituals.meteorRitual=Mark of the Fallen Tower +guide.BloodMagic.entryName.rituals.expulsionRitual=Aura of Expulsion +guide.BloodMagic.entryName.rituals.costOfProgress=The Cost of Progress +guide.BloodMagic.entryName.rituals.zephyrRitual=Call of the Zephyr +guide.BloodMagic.entryName.rituals.harvestRitual=Reap of the Harvest Moon +guide.BloodMagic.entryName.rituals.eternalSoulRitual=Cry of the Eternal Soul +guide.BloodMagic.entryName.rituals.ellipsoidRitual=Focus of the Ellipsoid +guide.BloodMagic.entryName.rituals.evaporationRitual=Song of Evaporation +guide.BloodMagic.entryName.rituals.sacrosanctityRitual=Ward of Sacrosanctity +guide.BloodMagic.entryName.rituals.evilRitual=Veil of Evil +guide.BloodMagic.entryName.rituals.stomachRitual=Requiem of the Satiated Stomach +guide.BloodMagic.entryName.rituals.reagentEffects=The Effects of Reagents +guide.BloodMagic.entryName.rituals.conclaveOfMages=The Conclave of Mages +guide.BloodMagic.entryName.rituals.forbiddenParadise=Forbidden Paradise +guide.BloodMagic.entryName.rituals.convocationRitual=Convocation of the Damned +guide.BloodMagic.entryName.rituals.longHaul=The Long Haul +guide.BloodMagic.entryName.rituals.phantomHandsRitual=Orchestra of the Phantom Hands +guide.BloodMagic.entryName.rituals.anvilRitual=Rhythm of the Beating Anvil +guide.BloodMagic.entryName.rituals.dawnInk=Dawn Ink +guide.BloodMagic.entryName.rituals.symmetryRitual=Symmetry of the Omega +guide.BloodMagic.entryName.rituals.stallingRitual=Duet of the Fused Souls guide.BloodMagic.entryName.rituals.= guide.BloodMagic.entryName.rituals.=