Delivering packages in style!

This commit is contained in:
WayofTime 2015-05-25 14:58:23 -04:00
parent f553711573
commit 5c01df44c1
52 changed files with 2444 additions and 61 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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<? extends IEntityTrackEntry> entry);
public void registerBlockTrackEntry(IBlockTrackEntry entry);
public void addHackable(Class<? extends Entity> entityClazz, Class<? extends IHackableEntity> iHackable);
public void addHackable(Block block, Class<? extends IHackableBlock> 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<IHackableEntity> 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);
}
}

View file

@ -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<String> getDescription();
/**
*
* @param universalActuator
*/
public void actuate(TileEntity universalActuator);
}

View file

@ -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
*/
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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.");
}
}
}

View file

@ -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<String> 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<String> 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();
}

View file

@ -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<Integer, IAssemblyRenderOverriding> renderOverrides = new HashMap<Integer, IAssemblyRenderOverriding>();
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);
}
}

View file

@ -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<String> 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();
}

View file

@ -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<String> 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){}
}
}

View file

@ -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();
}

View file

@ -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<String> 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<String> 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);
}

View file

@ -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<String> 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<String> 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);
}

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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<IUpgradeRenderHandler> renderHandlers;
}

View file

@ -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;
}
}

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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;
}
}
}
}

View file

@ -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<ItemStack> curStacks);
}

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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
*/
}

View file

@ -0,0 +1,5 @@
@API(apiVersion = "1.0", owner = "PneumaticCraft", provides = "PneumaticCraftApi")
package pneumaticCraft.api;
import cpw.mods.fml.common.API;

View file

@ -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<AssemblyRecipe> drillRecipes = new ArrayList<AssemblyRecipe>();
public static List<AssemblyRecipe> laserRecipes = new ArrayList<AssemblyRecipe>();
public static List<AssemblyRecipe> drillLaserRecipes = new ArrayList<AssemblyRecipe>();
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;
}
}
}

View file

@ -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);
}

View file

@ -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<PressureChamberRecipe> chamberRecipes = new ArrayList<PressureChamberRecipe>();
public static List<IPressureChamberRecipe> specialRecipes = new ArrayList<IPressureChamberRecipe>();
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;
}
}

View file

@ -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);
}
}

View file

@ -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<Pair<ForgeDirection, IPneumaticMachine>> 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();
}

View file

@ -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);
}

View file

@ -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<String> curInfo);
}

View file

@ -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);
}

View file

@ -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<Entity> entities, String textBoxText);
}

View file

@ -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<String> 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);
}

View file

@ -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<String> 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);
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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<String> 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();
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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);

View file

@ -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<EntryAbstract> entries = new ArrayList();
ArrayList<IPage> testPages = new ArrayList();
testPages.add(PageRitualMultiBlock.getPageForRitual("AW031Convocation"));
entries.add(new EntryUniText(testPages, "Test page"));
// ArrayList<IPage> testPages = new ArrayList();
// testPages.add(PageRitualMultiBlock.getPageForRitual("AW031Convocation"));
// entries.add(new EntryUniText(testPages, "Test page"));
ArrayList<IPage> introPages = new ArrayList();
@ -373,9 +372,225 @@ public class BloodMagicGuide
entries.add(new EntryUniText(waterRitualPages, "guide.BloodMagic.entryName.rituals.waterRitual"));
ArrayList<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> beastModePages = new ArrayList();
beastModePages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.beastMode")));
entries.add(new EntryUniText(beastModePages, "guide.BloodMagic.entryName.rituals.beastMode"));
ArrayList<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> darkMagicPages = new ArrayList();
darkMagicPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.darkMagic")));
entries.add(new EntryUniText(darkMagicPages, "guide.BloodMagic.entryName.rituals.darkMagic"));
ArrayList<IPage> 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<IPage> 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<IPage> harvestFestivalPages = new ArrayList();
harvestFestivalPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.harvestFestival")));
entries.add(new EntryUniText(harvestFestivalPages, "guide.BloodMagic.entryName.rituals.harvestFestival"));
ArrayList<IPage> thenThereWereFivePages = new ArrayList();
thenThereWereFivePages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.thenThereWereFive")));
entries.add(new EntryUniText(thenThereWereFivePages, "guide.BloodMagic.entryName.rituals.thenThereWereFive"));
ArrayList<IPage> 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<IPage> 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<IPage> awakenedCrystalPages = new ArrayList();
awakenedCrystalPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.awakenedCrystal")));
entries.add(new EntryUniText(awakenedCrystalPages, "guide.BloodMagic.entryName.rituals.awakenedCrystal"));
ArrayList<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> conclaveOfMagesPages = new ArrayList();
conclaveOfMagesPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.conclaveOfMages")));
entries.add(new EntryUniText(conclaveOfMagesPages, "guide.BloodMagic.entryName.rituals.conclaveOfMages"));
ArrayList<IPage> forbiddenParadisePages = new ArrayList();
forbiddenParadisePages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.forbiddenParadise")));
entries.add(new EntryUniText(forbiddenParadisePages, "guide.BloodMagic.entryName.rituals.forbiddenParadise"));
ArrayList<IPage> 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<IPage> longHaulPages = new ArrayList();
longHaulPages.addAll(PageHelper.pagesForLongText(StatCollector.translateToLocal("aw.entries.rituals.longHaul")));
entries.add(new EntryUniText(longHaulPages, "guide.BloodMagic.entryName.rituals.longHaul"));
ArrayList<IPage> 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<IPage> 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<IPage> 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<IPage> 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<IPage> 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)));
}

View file

@ -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));
}
}

View file

@ -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)

View file

@ -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.=