Merge branch 'development' of https://github.com/aidancbrady/Mekanism into development

This commit is contained in:
Aidan C. Brady 2014-07-10 13:35:37 -04:00
commit 95b6ac8be1
83 changed files with 2997 additions and 274 deletions

View file

@ -0,0 +1,60 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class BCLog {
public static final Logger logger = Logger.getLogger("Buildcraft");
/**
* Deactivate constructor
*/
private BCLog() {
}
public static void initLog() {
// TODO: check if the code below is still useful and remove otherwise.
//logger.setParent(FMLLog.getLogger());
logger.info("Starting BuildCraft " + getVersion());
logger.info("Copyright (c) SpaceToad, 2011");
logger.info("http://www.mod-buildcraft.com");
}
public static void logErrorAPI(String mod, Throwable error, Class<?> classFile) {
StringBuilder msg = new StringBuilder(mod);
msg.append(" API error, please update your mods. Error: ").append(error);
StackTraceElement[] stackTrace = error.getStackTrace();
if (stackTrace.length > 0) {
msg.append(", ").append(stackTrace[0]);
}
logger.log(Level.SEVERE, msg.toString());
if (classFile != null) {
msg = new StringBuilder(mod);
msg.append(" API error: ").append(classFile.getSimpleName()).append(" is loaded from ").append(classFile.getProtectionDomain().getCodeSource().getLocation());
logger.log(Level.SEVERE, msg.toString());
}
}
public static String getVersion() {
try {
Class<?> clazz = Class.forName("buildcraft.core.Version");
Method method = clazz.getDeclaredMethod("getVersion");
return String.valueOf(method.invoke(null));
} catch (Exception e) {
return "UNKNOWN VERSION";
}
}
}

View file

@ -0,0 +1,104 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
/**
* This class is a comparable container for block positions. TODO: should this be merged with position?
*/
public class BlockIndex implements Comparable<BlockIndex> {
public int x;
public int y;
public int z;
public BlockIndex() {
}
/**
* Creates an index for a block located on x, y. z
*/
public BlockIndex(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public BlockIndex(NBTTagCompound c) {
this.x = c.getInteger("i");
this.y = c.getInteger("j");
this.z = c.getInteger("k");
}
public BlockIndex(Entity entity) {
x = (int) Math.floor(entity.posX);
y = (int) Math.floor(entity.posY);
z = (int) Math.floor(entity.posZ);
}
/**
* Provides a deterministic and complete ordering of block positions.
*/
@Override
public int compareTo(BlockIndex o) {
if (o.x < x) {
return 1;
} else if (o.x > x) {
return -1;
} else if (o.z < z) {
return 1;
} else if (o.z > z) {
return -1;
} else if (o.y < y) {
return 1;
} else if (o.y > y) {
return -1;
} else {
return 0;
}
}
public void writeTo(NBTTagCompound c) {
c.setInteger("i", x);
c.setInteger("j", y);
c.setInteger("k", z);
}
public Block getBlock(World world) {
return world.getBlock(x, y, z);
}
@Override
public String toString() {
return "{" + x + ", " + y + ", " + z + "}";
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BlockIndex) {
BlockIndex b = (BlockIndex) obj;
return b.x == x && b.y == y && b.z == z;
}
return super.equals(obj);
}
@Override
public int hashCode() {
return (x * 37 + y) * 37 + z;
}
}

View file

@ -0,0 +1,42 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.world.World;
public final class BuildCraftAPI {
public static ICoreProxy proxy;
public static final Set<Block> softBlocks = new HashSet<Block>();
public static IWorldProperty isSoftProperty;
public static IWorldProperty isWoodProperty;
public static IWorldProperty isLeavesProperty;
public static IWorldProperty isBasicOreProperty;
public static IWorldProperty isExtendedOreProperty;
public static IWorldProperty isHarvestableProperty;
public static IWorldProperty isFarmlandProperty;
public static IWorldProperty isDirtProperty;
public static IWorldProperty isShoveled;
/**
* Deactivate constructor
*/
private BuildCraftAPI() {
}
public static boolean isSoftBlock(World world, int x, int y, int z) {
return isSoftProperty.get(world, x, y, z);
}
}

View file

@ -0,0 +1,33 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
/**
* To be implemented by TileEntities able to provide a square area on the world, typically BuildCraft markers.
*/
public interface IAreaProvider {
int xMin();
int yMin();
int zMin();
int xMax();
int yMax();
int zMax();
/**
* Remove from the world all objects used to define the area.
*/
void removeFromWorld();
}

View file

@ -0,0 +1,25 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
public interface IBox {
IBox expand(int amount);
IBox contract(int amount);
boolean contains(double x, double y, double z);
Position pMin();
Position pMax();
void createLaserData();
}

View file

@ -0,0 +1,18 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import java.lang.ref.WeakReference;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.WorldServer;
public interface ICoreProxy {
WeakReference<EntityPlayer> getBuildCraftPlayer(WorldServer world);
}

View file

@ -0,0 +1,32 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.util.IIcon;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public interface IIconProvider {
/**
* @param iconIndex
*/
@SideOnly(Side.CLIENT)
IIcon getIcon(int iconIndex);
/**
* A call for the provider to register its Icons. This may be called multiple times but should only be executed once per provider
* @param iconRegister
*/
@SideOnly(Side.CLIENT)
void registerIcons(IIconRegister iconRegister);
}

View file

@ -0,0 +1,30 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import net.minecraft.item.ItemStack;
public interface IInvSlot {
/**
* Returns the slot number of the underlying Inventory.
*
* @return the slot number
*/
int getIndex();
boolean canPutStackInSlot(ItemStack stack);
boolean canTakeStackFromSlot(ItemStack stack);
ItemStack decreaseStackInSlot(int amount);
ItemStack getStackInSlot();
void setStackInSlot(ItemStack stack);
}

View file

@ -0,0 +1,18 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import net.minecraft.world.World;
public interface IWorldProperty {
boolean get(World world, int x, int y, int z);
void clear();
}

View file

@ -0,0 +1,92 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class JavaTools {
public static double bounds(double value, double min, double max) {
return Math.max(min, Math.min(value, max));
}
public static <T> T[] concat(T[] first, T[] second) {
T[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
public static int[] concat(int[] first, int[] second) {
int[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
public static float[] concat(float[] first, float[] second) {
float[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
public <T> T[] concatenate (T[] a, T[] b) {
int aLen = a.length;
int bLen = b.length;
@SuppressWarnings("unchecked")
T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
public static List<Field> getAllFields(Class<?> clas) {
List<Field> result = new ArrayList<Field>();
Class<?> current = clas;
while (current != null && current != Object.class) {
for (Field f : current.getDeclaredFields()) {
result.add(f);
}
current = current.getSuperclass();
}
return result;
}
public static List<Method> getAllMethods(Class<?> clas) {
List<Method> result = new ArrayList<Method>();
Class<?> current = clas;
while (current != null && current != Object.class) {
for (Method m : current.getDeclaredMethods()) {
result.add(m);
}
current = current.getSuperclass();
}
return result;
}
public static String surroundWithQuotes(String stringToSurroundWithQuotes) {
return String.format("\"%s\"", stringToSurroundWithQuotes);
}
public static String stripSurroundingQuotes(String stringToStripQuotes) {
return stringToStripQuotes.replaceAll("^\"|\"$", "");
}
}

View file

@ -0,0 +1,19 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface NetworkData {
}

View file

@ -0,0 +1,175 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public class Position {
@NetworkData
public double x, y, z;
@NetworkData
public ForgeDirection orientation;
public Position() {
x = 0;
y = 0;
z = 0;
orientation = ForgeDirection.UNKNOWN;
}
public Position(double ci, double cj, double ck) {
x = ci;
y = cj;
z = ck;
orientation = ForgeDirection.UNKNOWN;
}
public Position(double ci, double cj, double ck, ForgeDirection corientation) {
x = ci;
y = cj;
z = ck;
orientation = corientation;
if (orientation == null) {
orientation = ForgeDirection.UNKNOWN;
}
}
public Position(Position p) {
x = p.x;
y = p.y;
z = p.z;
orientation = p.orientation;
}
public Position(NBTTagCompound nbttagcompound) {
readFromNBT(nbttagcompound);
}
public Position(TileEntity tile) {
x = tile.xCoord;
y = tile.yCoord;
z = tile.zCoord;
orientation = ForgeDirection.UNKNOWN;
}
public void moveRight(double step) {
switch (orientation) {
case SOUTH:
x = x - step;
break;
case NORTH:
x = x + step;
break;
case EAST:
z = z + step;
break;
case WEST:
z = z - step;
break;
default:
}
}
public void moveLeft(double step) {
moveRight(-step);
}
public void moveForwards(double step) {
switch (orientation) {
case UP:
y = y + step;
break;
case DOWN:
y = y - step;
break;
case SOUTH:
z = z + step;
break;
case NORTH:
z = z - step;
break;
case EAST:
x = x + step;
break;
case WEST:
x = x - step;
break;
default:
}
}
public void moveBackwards(double step) {
moveForwards(-step);
}
public void moveUp(double step) {
switch (orientation) {
case SOUTH:
case NORTH:
case EAST:
case WEST:
y = y + step;
break;
default:
}
}
public void moveDown(double step) {
moveUp(-step);
}
public void writeToNBT(NBTTagCompound nbttagcompound) {
if (orientation == null) {
orientation = ForgeDirection.UNKNOWN;
}
nbttagcompound.setDouble("i", x);
nbttagcompound.setDouble("j", y);
nbttagcompound.setDouble("k", z);
nbttagcompound.setByte("orientation", (byte) orientation.ordinal());
}
public void readFromNBT(NBTTagCompound nbttagcompound) {
x = nbttagcompound.getDouble("i");
y = nbttagcompound.getDouble("j");
z = nbttagcompound.getDouble("k");
orientation = ForgeDirection.values() [nbttagcompound.getByte("orientation")];
}
@Override
public String toString() {
return "{" + x + ", " + y + ", " + z + "}";
}
public Position min(Position p) {
return new Position(p.x > x ? x : p.x, p.y > y ? y : p.y, p.z > z ? z : p.z);
}
public Position max(Position p) {
return new Position(p.x < x ? x : p.x, p.y < y ? y : p.y, p.z < z ? z : p.z);
}
public boolean isClose(Position newPosition, float f) {
double dx = x - newPosition.x;
double dy = y - newPosition.y;
double dz = z - newPosition.z;
double sqrDis = dx * dx + dy * dy + dz * dz;
return !(sqrDis > f * f);
}
}

View file

@ -55,8 +55,9 @@ public class SafeTimeTracker {
* this function without a parameter
*/
public boolean markTimeIfDelay(World world, long delay) {
if (world == null)
if (world == null) {
return false;
}
long currentTime = world.getTotalWorldTime();

View file

@ -0,0 +1,56 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.core;
import net.minecraft.item.ItemStack;
/**
* This class is used whenever stacks needs to be stored as keys.
*/
public class StackKey {
public final ItemStack stack;
public StackKey(ItemStack stack) {
this.stack = stack;
}
@Override
public int hashCode() {
int hash = 5;
hash = 67 * hash + stack.getItem().hashCode();
hash = 67 * hash + stack.getItemDamage();
if (stack.stackTagCompound != null) {
hash = 67 * hash + stack.stackTagCompound.hashCode();
}
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (getClass() != obj.getClass()) {
return false;
}
final StackKey other = (StackKey) obj;
if (stack.getItem() != other.stack.getItem()) {
return false;
} else if (stack.getHasSubtypes() && stack.getItemDamage() != other.stack.getItemDamage()) {
return false;
} else {
return !(stack.stackTagCompound != null && !stack.stackTagCompound.equals(other.stack.stackTagCompound));
}
}
}

View file

@ -0,0 +1,11 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "1.0", owner = "BuildCraft|Core", provides = "BuildCraftAPI|core")
package buildcraft.api.core;
import cpw.mods.fml.common.API;

View file

@ -0,0 +1,92 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.fuels;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import buildcraft.api.core.StackKey;
public final class IronEngineCoolant {
public static Map<String, Coolant> liquidCoolants = new HashMap<String, Coolant>();
public static Map<StackKey, FluidStack> solidCoolants = new HashMap<StackKey, FluidStack>();
private IronEngineCoolant() {
}
public static FluidStack getFluidCoolant(ItemStack stack) {
return solidCoolants.get(new StackKey(stack));
}
public static Coolant getCoolant(ItemStack stack) {
return getCoolant(getFluidCoolant(stack));
}
public static Coolant getCoolant(FluidStack fluidStack) {
return fluidStack != null && fluidStack.getFluid() != null ? liquidCoolants.get(fluidStack.getFluid().getName()) : null;
}
public interface Coolant {
float getDegreesCoolingPerMB(float currentHeat);
}
public static void addCoolant(final Fluid fluid, final float degreesCoolingPerMB) {
if (fluid != null) {
liquidCoolants.put(fluid.getName(), new Coolant() {
@Override
public float getDegreesCoolingPerMB(float currentHeat) {
return degreesCoolingPerMB;
}
});
}
}
/**
* Adds a solid coolant like Ice Blocks. The FluidStack must contain a registered
* Coolant Fluid or nothing will happen. You do not need to call this for
* Fluid Containers.
*
* @param stack
* @param coolant
*/
public static void addCoolant(final ItemStack stack, final FluidStack coolant) {
if (stack != null && stack.getItem() != null && coolant != null) {
solidCoolants.put(new StackKey(stack), coolant);
}
}
/**
* Adds a solid coolant like Ice Blocks. The FluidStack must contain a
* registered Coolant Fluid or nothing will happen. You do not need to call
* this for Fluid Containers.
*
* @param item
* @param coolant
*/
public static void addCoolant(final Item item, final int metadata, final FluidStack coolant) {
addCoolant(new ItemStack(item, 1, metadata), coolant);
}
public static void addCoolant(final Block block, final int metadata, final FluidStack coolant) {
addCoolant(new ItemStack(block, 1, metadata), coolant);
}
public static boolean isCoolant(Fluid fluid) {
return liquidCoolants.containsKey(fluid.getName());
}
}

View file

@ -10,21 +10,22 @@ package buildcraft.api.fuels;
import java.util.HashMap;
import java.util.Map;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
public class IronEngineFuel {
public final class IronEngineFuel {
public static Map<String, Fuel> fuels = new HashMap<String, Fuel>();
private IronEngineFuel() {
}
public static Fuel getFuelForFluid(Fluid liquid) {
return liquid == null ? null : fuels.get(liquid.getName());
}
private IronEngineFuel() {
}
public static class Fuel {
public static final class Fuel {
public final Fluid liquid;
public final float powerPerCycle;

View file

@ -1,3 +1,11 @@
@API(apiVersion="1.0",owner="BuildCraftAPI|core",provides="BuildCraftAPI|fuels")
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "1.0", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|fuels")
package buildcraft.api.fuels;
import cpw.mods.fml.common.API;

View file

@ -0,0 +1,199 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import java.lang.reflect.Field;
import java.util.logging.Level;
import buildcraft.api.core.BCLog;
import buildcraft.api.core.JavaTools;
/**
* A battery object is a wrapper around a battery field in an object. This
* battery field is of type double, and is the only piece of data specific to
* this object. Others are class-wide.
*/
public class BatteryObject implements IBatteryIOObject, MjReconfigurator.IConfigurableBatteryObject {
protected Field energyStored;
protected Object obj;
protected MjBattery batteryData;
/**
* {@inheritDoc}
*/
@Override
public double getEnergyRequested() {
if (!batteryData.mode().canReceive) {
return 0;
}
try {
return JavaTools.bounds(batteryData.maxCapacity() - energyStored.getDouble(obj),
batteryData.minimumConsumption(), batteryData.maxReceivedPerCycle());
} catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't get energy requested", e);
}
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public double addEnergy(double mj) {
return addEnergy(mj, false);
}
/**
* {@inheritDoc}
*/
@Override
public double addEnergy(double mj, boolean ignoreCycleLimit) {
try {
double contained = energyStored.getDouble(obj);
double maxAccepted = batteryData.maxCapacity() - contained + batteryData.minimumConsumption();
if (!ignoreCycleLimit && maxAccepted > batteryData.maxReceivedPerCycle()) {
maxAccepted = batteryData.maxReceivedPerCycle();
}
double used = Math.min(maxAccepted, mj);
if (used > 0) {
energyStored.setDouble(obj, Math.min(contained + used, batteryData.maxCapacity()));
return used;
}
} catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't add energy", e);
}
return 0;
}
@Override
public double extractEnergy(double mj) {
return extractEnergy(mj, false);
}
@Override
public double extractEnergy(double mj, boolean ignoreCycleLimit) {
try {
double contained = energyStored.getDouble(obj);
double maxExtracted = contained;
if (!ignoreCycleLimit && maxExtracted > batteryData.maxSendedPerCycle()) {
maxExtracted = batteryData.maxSendedPerCycle();
}
double used = Math.min(maxExtracted, mj);
if (used > 0) {
energyStored.setDouble(obj, Math.max(contained - used, 0));
return used;
}
} catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't extract energy", e);
}
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public double getEnergyStored() {
try {
return energyStored.getDouble(obj);
} catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't get return energy stored", e);
return 0;
}
}
/**
* {@inheritDoc}
*/
@Override
public void setEnergyStored(double mj) {
try {
energyStored.setDouble(obj, mj);
} catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't set energy stored", e);
throw new RuntimeException(e);
}
}
/**
* {@inheritDoc}
*/
@Override
public double maxCapacity() {
return batteryData.maxCapacity();
}
/**
* {@inheritDoc}
*/
@Override
public double minimumConsumption() {
return batteryData.minimumConsumption();
}
/**
* {@inheritDoc}
*/
@Override
public double maxReceivedPerCycle() {
return batteryData.maxReceivedPerCycle();
}
@Override
public String kind() {
return batteryData.kind();
}
@Override
public void init(Object object, Field storedField, MjBattery battery) {
this.obj = object;
this.energyStored = storedField;
this.batteryData = battery;
}
@Override
public double maxSendedPerCycle() {
return batteryData.maxSendedPerCycle();
}
@Override
public IOMode mode() {
return batteryData.mode();
}
@Override
public boolean canSend() {
return batteryData.mode().canSend;
}
@Override
public boolean canReceive() {
return batteryData.mode().canReceive;
}
@Override
public boolean isActive() {
return batteryData.mode().active;
}
@Override
public boolean isCacheable() {
return batteryData.cacheable();
}
@Override
public MjBattery getMjBattery() {
return batteryData;
}
@Override
public void setMjBattery(MjBattery battery) {
batteryData = battery;
}
}

View file

@ -0,0 +1,27 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
public interface IBatteryIOObject extends IBatteryObject {
double maxSendedPerCycle();
double extractEnergy(double mj);
double extractEnergy(double mj, boolean ignoreCycleLimit);
IOMode mode();
boolean canSend();
boolean canReceive();
boolean isActive();
boolean isCacheable();
}

View file

@ -0,0 +1,77 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import java.lang.reflect.Field;
public interface IBatteryObject {
/**
* @return Current energy requirement for keeping machine state
*/
double getEnergyRequested();
/**
* Add energy to this battery
*
* @param mj Energy amount
* @return Used energy
*/
double addEnergy(double mj);
/**
* Add energy to this battery
*
* @param mj Energy amount
* @param ignoreCycleLimit Force add all energy even if "maxReceivedPerCycle" limit is reached
* @return Used energy
*/
double addEnergy(double mj, boolean ignoreCycleLimit);
/**
* @return Current stored energy amount in this battery
*/
double getEnergyStored();
/**
* Set current stored energy amount.
* Doesn't use it for your machines! Decrease your battery field directly.
*
* @param mj New energy amount
*/
void setEnergyStored(double mj);
/**
* @return Maximal energy amount for this battery.
*/
double maxCapacity();
/**
* @return Minimal energy amount for keep your machine in active state
*/
double minimumConsumption();
/**
* @return Maximal energy received per one tick
*/
double maxReceivedPerCycle();
/**
* @return kind of this energy battery
*/
String kind();
/**
* Basic initialization method
*
* @param object Basic object which hold a battery field
* @param storedField Field for energy storing
* @param battery Battery data
*/
void init(Object object, Field storedField, MjBattery battery);
}

View file

@ -0,0 +1,13 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
public interface IBatteryProvider {
IBatteryObject getMjBattery(String kind);
}

View file

@ -0,0 +1,30 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
public enum IOMode {
Both(true, true, false),
BothActive(true, true, true),
Receive(true, false, false),
ReceiveActive(true, false, true),
Send(false, true, false),
SendActive(false, true, true),
None(false, false, false);
public final boolean canReceive, canSend, active;
IOMode(boolean canReceive, boolean canSend, boolean active) {
this.canReceive = canReceive;
this.canSend = canSend;
this.active = active;
}
}

View file

@ -0,0 +1,15 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import net.minecraftforge.common.util.ForgeDirection;
public interface ISidedBatteryProvider {
IBatteryObject getMjBattery(String kind, ForgeDirection direction);
}

View file

@ -0,0 +1,439 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.core.BCLog;
import buildcraft.api.core.JavaTools;
import buildcraft.api.power.IPowerReceptor;
import buildcraft.api.power.PowerHandler;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
/**
* The class MjAPI provides services to the Minecraft Joules power framework.
* BuildCraft implements a default power model on top of this, the "kinesis"
* power model. Third party mods may provide they own version of Minecraft
* Joules batteries and provide different models.
*/
public final class MjAPI {
public static final String DEFAULT_POWER_FRAMEWORK = "buildcraft.kinesis";
private static Map<BatteryHolder, BatteryField> mjBatteryFields = new HashMap<BatteryHolder, BatteryField>();
private static Map<String, Class<? extends IBatteryObject>> mjBatteryKinds = new HashMap<String, Class<? extends IBatteryObject>>();
private static final BatteryField invalidBatteryField = new BatteryField();
private static final MjReconfigurator reconfigurator = new MjReconfigurator();
private static final Map<Object, BatteryCache> mjBatteryCache = new WeakHashMap<Object, BatteryCache>();
/**
* Deactivate constructor
*/
private MjAPI() {
}
/**
* @see #getMjBattery(Object, String, ForgeDirection)
*/
public static IBatteryObject getMjBattery(Object o) {
return getMjBattery(o, null, null);
}
/**
* @see #getMjBattery(Object, String, ForgeDirection)
*/
public static IBatteryObject getMjBattery(Object o, String kind) {
return getMjBattery(o, kind, null);
}
/**
* @see #getMjBattery(Object, String, ForgeDirection)
*/
public static IBatteryObject getMjBattery(Object o, ForgeDirection side) {
return getMjBattery(o, null, side);
}
/**
* Returns the battery related to the object given in parameter.
*/
public static IBatteryObject getMjBattery(Object o, String kindRaw, ForgeDirection sideRaw) {
if (o == null) {
return null;
}
String kind = kindRaw == null ? DEFAULT_POWER_FRAMEWORK : kindRaw;
ForgeDirection side = sideRaw == null ? ForgeDirection.UNKNOWN : sideRaw;
IBatteryObject battery;
BatteryCache cache = mjBatteryCache.get(o);
if (cache == null) {
cache = new BatteryCache();
mjBatteryCache.put(o, cache);
} else {
battery = cache.get(kind, side);
if (isCacheable(battery)) {
return battery;
}
}
if (o instanceof ISidedBatteryProvider) {
battery = ((ISidedBatteryProvider) o).getMjBattery(kind, side);
if (battery == null && side != ForgeDirection.UNKNOWN) {
battery = ((ISidedBatteryProvider) o).getMjBattery(kind, ForgeDirection.UNKNOWN);
}
} else if (o instanceof IBatteryProvider) {
battery = ((IBatteryProvider) o).getMjBattery(kind);
} else {
battery = createBattery(o, kind, side);
}
if (battery == null && o instanceof IPowerReceptor) {
PowerHandler.PowerReceiver receiver = ((IPowerReceptor) o).getPowerReceiver(side);
if (receiver == null && side != ForgeDirection.UNKNOWN) {
receiver = ((IPowerReceptor) o).getPowerReceiver(ForgeDirection.UNKNOWN);
}
if (receiver != null) {
battery = receiver.getMjBattery();
}
}
cache.put(kind, side, battery);
return battery;
}
/**
* Create new battery instance.
* This method ignore all providers/caches and only create battery for given kind/side.
*
* @param o Object which contains {@link MjBattery}
* @param kind Kind of power
* @param side Side of block
* @return New {@link IBatteryObject} implementation registered for given kind of power
*/
public static IBatteryObject createBattery(Object o, String kind, ForgeDirection side) {
if (o == null) {
return null;
}
BatteryField f = getMjBatteryField(o.getClass(), kind, side);
if (f == null && side != ForgeDirection.UNKNOWN) {
f = getMjBatteryField(o.getClass(), kind, ForgeDirection.UNKNOWN);
}
if (f == null) {
return null;
} else if (!mjBatteryKinds.containsKey(kind)) {
return null;
} else if (f.kind == BatteryKind.Value) {
try {
IBatteryObject obj = mjBatteryKinds.get(kind).newInstance();
obj.init(o, f.field, f.battery);
return obj;
} catch (InstantiationException e) {
BCLog.logger.log(Level.WARNING, "can't instantiate class for energy kind \"" + kind + "\"");
return null;
} catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't instantiate class for energy kind \"" + kind + "\"");
return null;
}
} else {
try {
return createBattery(f.field.get(o), kind, side);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
}
/**
* @return All non-sided batteries for passed object
*/
public static IBatteryObject[] getAllMjBatteries(Object o) {
return getAllMjBatteries(o, ForgeDirection.UNKNOWN);
}
/**
* @param direction Side of block
* @return All sided batteries for passed object
*/
public static IBatteryObject[] getAllMjBatteries(Object o, ForgeDirection direction) {
IBatteryObject[] result = new IBatteryObject[mjBatteryFields.size()];
int id = 0;
for (String kind : mjBatteryKinds.keySet()) {
result[id] = getMjBattery(o, kind, direction);
if (result[id] != null) {
id++;
}
}
return Arrays.copyOfRange(result, 0, id);
}
/**
* Register new battery kind implementation.
* Allowing to have a custom power types alongside default "kinesis" kind
* @param kind Kind name
* @param clazz Battery implementation class
*/
public static void registerMJBatteryKind(String kind, Class<? extends IBatteryObject> clazz) {
if (!mjBatteryKinds.containsKey(kind)) {
mjBatteryKinds.put(kind, clazz);
} else {
BCLog.logger.log(Level.WARNING,
"energy kind \"" + kind + "\" already registered with " + clazz.getCanonicalName());
}
}
/**
* @see IOMode#canReceive
*/
public static boolean canReceive(IBatteryObject battery) {
return battery != null && (!(battery instanceof IBatteryIOObject) || ((IBatteryIOObject) battery).canReceive());
}
/**
* @see IOMode#canSend
*/
public static boolean canSend(IBatteryObject battery) {
return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).canSend();
}
/**
* @see IOMode#active
*/
public static boolean isActive(IBatteryObject battery) {
return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).isActive();
}
/**
* @see MjBattery#cacheable()
*/
public static boolean isCacheable(IBatteryObject battery) {
return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).isCacheable();
}
/**
* @see MjBattery#maxReceivedPerCycle()
* @see MjBattery#maxSendedPerCycle()
* @return Actual IO limit for passed mode (only send/receive supported)
*/
public static double getIOLimit(IBatteryObject batteryObject, IOMode mode) {
if (mode == IOMode.Receive && canReceive(batteryObject)) {
return batteryObject.maxReceivedPerCycle();
} else if (mode == IOMode.Send && canSend(batteryObject)) {
return ((IBatteryIOObject) batteryObject).maxSendedPerCycle();
}
return 0;
}
/**
* Obtain battery parameters reconfigurator.
* Usage:<br />
* <code>
* MjAPI.reconfigure().maxCapacity(battery, 15000);
* </code>
* @return Reconfigurator instance
*/
public static MjReconfigurator reconfigure() {
return reconfigurator;
}
/**
* Transfer mj energy amount from battery "fromBattery" to "toBattery"
* @param fromBattery Source battery
* @param toBattery Target battery
* @param mj Amount of energy
* @return Transferred amount
*/
public static double transferEnergy(IBatteryObject fromBattery, IBatteryObject toBattery, double mj) {
if (!canSend(fromBattery) || !canReceive(toBattery)) {
return 0;
}
IBatteryIOObject from = (IBatteryIOObject) fromBattery;
double attemptToTransfer = Math.min(getIOLimit(from, IOMode.Send), mj);
attemptToTransfer = Math.min(attemptToTransfer, getIOLimit(toBattery, IOMode.Receive));
double extracted = from.extractEnergy(attemptToTransfer);
double received = toBattery.addEnergy(extracted);
if (extracted > received) {
from.addEnergy(extracted - received);
}
return received;
}
/**
* Transfer maximal energy amount from battery "fromBattery" to "toBattery"
* @param fromBattery Source battery
* @param toBattery Target battery
* @return Transferred amount
*/
public static double transferEnergy(IBatteryObject fromBattery, IBatteryObject toBattery) {
return transferEnergy(fromBattery, toBattery, Math.min(
getIOLimit(fromBattery, IOMode.Send),
getIOLimit(toBattery, IOMode.Receive)));
}
/**
* Helper method which you should invoke in every game tick for supporting Active IO modes
* @param tile Tile which contains active battery
*/
public static void updateEntity(TileEntity tile) {
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
IBatteryObject batteryObject = getMjBattery(tile, direction);
TileEntity anotherTile = tile.getWorldObj().getTileEntity(tile.xCoord + direction.offsetX, tile.yCoord + direction.offsetY, tile.zCoord + direction.offsetZ);
IBatteryObject anotherBattery = getMjBattery(anotherTile, direction.getOpposite());
if (batteryObject == null || anotherBattery == null) {
continue;
}
if (canSend(batteryObject) && canReceive(anotherBattery) && isActive(batteryObject)) {
transferEnergy(batteryObject, anotherBattery);
}
if (canReceive(batteryObject) && canSend(anotherBattery) && isActive(anotherBattery) && !isActive(batteryObject)) {
transferEnergy(anotherBattery, batteryObject);
}
}
}
/**
* Reset all caches for passed tile
*/
public static void resetBatteriesCache(TileEntity tile) {
mjBatteryCache.remove(tile);
}
/**
* Remove cached instance of passed battery
*/
public static void resetBatteriesCache(IBatteryObject battery) {
for (BatteryCache cache : mjBatteryCache.values()) {
cache.reset(battery);
}
}
private enum BatteryKind {
Value, Container
}
private static final class BatteryCache {
TIntObjectMap<IBatteryObject> cache = new TIntObjectHashMap<IBatteryObject>();
IBatteryObject get(String kind, ForgeDirection side) {
return cache.get(hash(kind, side));
}
void put(String kind, ForgeDirection side, IBatteryObject battery) {
cache.put(hash(kind, side), battery);
}
void reset(IBatteryObject battery) {
for (int key : cache.keys()) {
if (cache.get(key) == battery) {
cache.remove(key);
}
}
}
private int hash(String kind, ForgeDirection side) {
return kind.hashCode() * 31 + side.hashCode();
}
}
private static final class BatteryHolder {
private String kind;
private ForgeDirection side;
private Class<? extends Object> clazz;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BatteryHolder that = (BatteryHolder) o;
return kind.equals(that.kind) && clazz.equals(that.clazz) && side.equals(that.side);
}
@Override
public int hashCode() {
int result = kind.hashCode();
result = 31 * result + clazz.hashCode();
result = 31 * result + side.hashCode();
return result;
}
}
private static class BatteryField {
public Field field;
public MjBattery battery;
public BatteryKind kind;
}
private static BatteryField getMjBatteryField(Class<?> c, String kind, ForgeDirection side) {
BatteryHolder holder = new BatteryHolder();
holder.clazz = c;
holder.kind = kind;
holder.side = side;
BatteryField bField = mjBatteryFields.get(holder);
if (bField == null) {
for (Field f : JavaTools.getAllFields(c)) {
MjBattery battery = f.getAnnotation(MjBattery.class);
if (battery != null && kind.equals(battery.kind())) {
if (!contains(battery.sides(), side) && !contains(battery.sides(), ForgeDirection.UNKNOWN)) {
continue;
}
f.setAccessible(true);
bField = new BatteryField();
bField.field = f;
bField.battery = battery;
if (double.class.equals(f.getType())) {
bField.kind = BatteryKind.Value;
} else if (f.getType().isPrimitive()) {
throw new RuntimeException(
"MJ battery needs to be object or double type");
} else {
bField.kind = BatteryKind.Container;
}
mjBatteryFields.put(holder, bField);
return bField;
}
}
mjBatteryFields.put(holder, invalidBatteryField);
}
return bField == invalidBatteryField ? null : bField;
}
private static <T> boolean contains(T[] array, T value) {
for (T t : array) {
if (t == value) {
return true;
}
}
return false;
}
static {
registerMJBatteryKind(DEFAULT_POWER_FRAMEWORK, BatteryObject.class);
}
}

View file

@ -0,0 +1,60 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.power.IPowerReceptor;
import buildcraft.api.power.PowerHandler;
public class MjAPILegacy implements IPowerReceptor {
private final PowerHandler powerHandler;
private final World world;
protected MjAPILegacy(World world, IBatteryObject battery, PowerHandler.Type type) {
if (battery == null) {
throw new NullPointerException();
}
this.world = world;
this.powerHandler = new PowerHandler(this, type, battery);
}
public static MjAPILegacy from(World world, IBatteryObject battery, PowerHandler.Type type) {
if (battery == null) {
return null;
}
return new MjAPILegacy(world, battery, type);
}
public static MjAPILegacy from(World world, Object object, PowerHandler.Type type) {
return from(world, MjAPI.getMjBattery(object), type);
}
public static MjAPILegacy from(TileEntity tileEntity, PowerHandler.Type type) {
return from(tileEntity.getWorldObj(), MjAPI.getMjBattery(tileEntity), type);
}
@Override
public PowerHandler.PowerReceiver getPowerReceiver(ForgeDirection side) {
return powerHandler.getPowerReceiver();
}
@Override
public void doWork(PowerHandler workProvider) {
}
@Override
public World getWorld() {
return world;
}
}

View file

@ -0,0 +1,86 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.minecraftforge.common.util.ForgeDirection;
/**
* This annotation is used for tiles that need to interface with BuildCraft
* energy framework, a.k.a MinecraftJoule or MJ. In order to receive power,
* tiles, need to declare a double field, with the annotation MjBattery. MJ
* provider machines able to provide power will then connect to these tiles, and
* feed energy up to max capacity. It's the responsibility of the implementer to
* manually decrease the value of the energy, as he simulates energy
* consumption. On each cycle, per power input, machines can receive up to
* "maxReceivedPerCycle" units of energy. As an optional behavior, the system
* can have a minimum amount of energy consumed even if the system is at max
* capacity, modelized by the "minimumConsumption" value.
*
* If the field designated by MjBattery is an object, then it will be considered
* as a nested battery, and will look for the field in the designated object.
*
* All the properties defined in this annotation are class wide. If you need to
* change them on a tile by tile basis, you will need to use interfaces, either
* {@link IBatteryProvider} or {@link ISidedBatteryProvider}
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Inherited
public @interface MjBattery {
/**
* @return Max energy capacity of battery
*/
double maxCapacity() default 100.0;
/**
* @return Max energy received per one tick
*/
double maxReceivedPerCycle() default 10.0;
/**
* @return Max energy received per one tick
*/
double maxSendedPerCycle() default 10.0;
/**
* @return Minimal energy for keep machine is active
*/
double minimumConsumption() default 0.1;
/**
* @return The kind of battery stored. Specific power systems can be created
* through this system, as several battery of different kind can
* coexist in the same tile.
*/
String kind() default MjAPI.DEFAULT_POWER_FRAMEWORK;
/**
* @return Sides on which this battery should works.
*/
ForgeDirection[] sides() default {ForgeDirection.UNKNOWN};
/**
* @return Current battery input/output mode
*/
IOMode mode() default IOMode.Receive;
/**
* @return Ability to cache this battery instance for performance reasons. Usual
* not required to modify it for every battery, you can dynamicaly reconfigure
* your batteries with {@link MjAPI#reconfigure()} and reset cache
* for tile with {@link MjAPI#resetBatteriesCache(IBatteryObject)}
*/
boolean cacheable() default true;
}

View file

@ -0,0 +1,183 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.mj;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.core.BCLog;
/**
* Reconfiguration helper.
* Allow to change battery parameters in runtime.
*/
public class MjReconfigurator {
private static final class ConfigurableMjBattery implements MjBattery {
double maxCapacity, maxReceivedPerCycle, maxSendedPerCycle, minimumConsumption;
String kind;
ForgeDirection[] sides;
IOMode mode;
boolean cacheable;
@Override
public double maxCapacity() {
return maxCapacity;
}
@Override
public double maxReceivedPerCycle() {
return maxReceivedPerCycle;
}
@Override
public double minimumConsumption() {
return minimumConsumption;
}
@Override
public double maxSendedPerCycle() {
return maxSendedPerCycle;
}
@Override
public String kind() {
return kind;
}
@Override
public ForgeDirection[] sides() {
return sides;
}
@Override
public IOMode mode() {
return mode;
}
@Override
public boolean cacheable() {
return cacheable;
}
@Override
public Class<? extends Annotation> annotationType() {
return MjBattery.class;
}
}
/**
* Helper interface which should implement all configurable batteries.
*/
public interface IConfigurableBatteryObject extends IBatteryObject {
MjBattery getMjBattery();
void setMjBattery(MjBattery battery);
}
private ConfigurableMjBattery obtainConfigurableBattery(IBatteryObject battery) {
if (!(battery instanceof IConfigurableBatteryObject)) {
BCLog.logger.warning("Attempt to reconfigure unsupported battery: " + battery);
return null;
}
IConfigurableBatteryObject configurableBattery = (IConfigurableBatteryObject) battery;
MjBattery mjBattery = configurableBattery.getMjBattery();
if (mjBattery instanceof ConfigurableMjBattery) {
return (ConfigurableMjBattery) mjBattery;
}
ConfigurableMjBattery configurableMjBattery = new ConfigurableMjBattery();
configurableMjBattery.maxCapacity = mjBattery.maxCapacity();
configurableMjBattery.maxReceivedPerCycle = mjBattery.maxReceivedPerCycle();
configurableMjBattery.maxSendedPerCycle = mjBattery.maxSendedPerCycle();
configurableMjBattery.minimumConsumption = mjBattery.minimumConsumption();
configurableMjBattery.kind = mjBattery.kind();
configurableMjBattery.sides = mjBattery.sides();
configurableMjBattery.mode = mjBattery.mode();
configurableMjBattery.cacheable = mjBattery.cacheable();
configurableBattery.setMjBattery(configurableMjBattery);
return configurableMjBattery;
}
public void maxCapacity(IBatteryObject batteryObject, double maxCapacity) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.maxCapacity = maxCapacity;
}
}
public void maxReceivedPerCycle(IBatteryObject batteryObject, double maxReceivedPerCycle) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.maxReceivedPerCycle = maxReceivedPerCycle;
}
}
public void maxSendedPerCycle(IBatteryObject batteryObject, double maxSendedPerCycle) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.maxSendedPerCycle = maxSendedPerCycle;
}
}
public void minimumConsumption(IBatteryObject batteryObject, double minimumConsumption) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.minimumConsumption = minimumConsumption;
}
}
public void kind(IBatteryObject batteryObject, String kind) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.kind = kind;
MjAPI.resetBatteriesCache(batteryObject);
}
}
/**
* Reconfigure passed battery instance for working with passed sides only
* @param sides Enabled sides
*/
public void sides(IBatteryObject batteryObject, ForgeDirection... sides) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.sides = sides;
MjAPI.resetBatteriesCache(batteryObject);
}
}
/**
* Reconfigure passed battery instance for working with all sides exclude passed
* @param sides Disabled sides
*/
public void sidesExclude(IBatteryObject batteryObject, ForgeDirection... sides) {
List<ForgeDirection> newSides = new ArrayList<ForgeDirection>(Arrays.asList(ForgeDirection.VALID_DIRECTIONS));
for (ForgeDirection side : sides) {
newSides.remove(side);
}
sides(batteryObject, newSides.toArray(new ForgeDirection[newSides.size()]));
}
public void mode(IBatteryObject batteryObject, IOMode mode) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.mode = mode;
}
}
public void cacheable(IBatteryObject batteryObject, boolean cacheable) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.cacheable = cacheable;
}
}
}

View file

@ -0,0 +1,11 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "1.1", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|mj")
package buildcraft.api.mj;
import cpw.mods.fml.common.API;

View file

@ -1,3 +1,11 @@
@API(apiVersion="1.0",owner="BuildCraft|Core",provides="BuildCraftAPI|core")
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "1.0", owner = "BuildCraft|Core", provides = "BuildCraftAPI|core")
package buildcraft.api;
import cpw.mods.fml.common.API;

View file

@ -0,0 +1,41 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.power;
public interface ILaserTarget {
/**
* Returns true if the target currently needs power. For example, if the Advanced
* Crafting Table has work to do.
*
* @return true if needs power
*/
boolean requiresLaserEnergy();
/**
* Transfers energy from the laser to the target.
*
* @param energy
*/
void receiveLaserEnergy(double energy);
/**
* Return true if the Tile Entity object is no longer a valid target. For
* example, if its been invalidated.
*
* @return true if no longer a valid target object
*/
boolean isInvalidTarget();
int getXCoord();
int getYCoord();
int getZCoord();
}

View file

@ -17,6 +17,5 @@ import net.minecraftforge.common.util.ForgeDirection;
* from a specific side.
*/
public interface IPowerEmitter {
public boolean canEmitPowerFrom(ForgeDirection side);
boolean canEmitPowerFrom(ForgeDirection side);
}

View file

@ -9,6 +9,7 @@
package buildcraft.api.power;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
@ -27,9 +28,8 @@ public interface IPowerReceptor {
* engines to eventually explode.
*
* @param side
* @return
*/
public PowerHandler.PowerReceiver getPowerReceiver(ForgeDirection side);
PowerHandler.PowerReceiver getPowerReceiver(ForgeDirection side);
/**
* Call back from the PowerHandler that is called when the stored power
@ -39,7 +39,7 @@ public interface IPowerReceptor {
*
* @param workProvider
*/
public void doWork(PowerHandler workProvider);
void doWork(PowerHandler workProvider);
public World getWorld();
World getWorld();
}

View file

@ -8,27 +8,35 @@
*/
package buildcraft.api.power;
import buildcraft.api.core.SafeTimeTracker;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.core.SafeTimeTracker;
import buildcraft.api.mj.BatteryObject;
import buildcraft.api.mj.IBatteryObject;
import buildcraft.api.mj.IBatteryProvider;
import buildcraft.api.mj.IOMode;
import buildcraft.api.mj.MjAPI;
import buildcraft.api.mj.MjBattery;
/**
* The PowerHandler is similar to FluidTank in that it holds your power and
* allows standardized interaction between machines.
*
* <p/>
* To receive power to your machine you needs create an instance of PowerHandler
* and implement IPowerReceptor on the TileEntity.
*
* <p/>
* If you plan emit power, you need only implement IPowerEmitter. You do not
* need a PowerHandler. Engines have a PowerHandler because they can also
* receive power from other Engines.
*
* <p/>
* See TileRefinery for a simple example of a power using machine.
*
* @see IPowerReceptor
* @see IPowerEmitter
*/
public final class PowerHandler {
public final class PowerHandler implements IBatteryProvider {
public static enum Type {
@ -57,7 +65,7 @@ public final class PowerHandler {
/**
* Extend this class to create custom Perdition algorithms (its not final).
*
* <p/>
* NOTE: It is not possible to create a Zero perdition algorithm.
*/
public static class PerditionCalculator {
@ -76,9 +84,6 @@ public final class PowerHandler {
* @param powerLoss power loss per tick
*/
public PerditionCalculator(double powerLoss) {
if (powerLoss < MIN_POWERLOSS) {
powerLoss = MIN_POWERLOSS;
}
this.powerLoss = powerLoss;
}
@ -88,21 +93,22 @@ public final class PowerHandler {
* every tick. It is triggered by any manipulation of the stored energy.
*
* @param powerHandler the PowerHandler requesting the perdition update
* @param current the current stored energy
* @param ticksPassed ticks since the last time this function was called
* @return
* @param current the current stored energy
* @param ticksPassed ticks since the last time this function was called
*/
public double applyPerdition(PowerHandler powerHandler, double current, long ticksPassed) {
current -= powerLoss * ticksPassed;
if (current < 0) {
current = 0;
double newPower = current - powerLoss * ticksPassed;
if (newPower < 0) {
newPower = 0;
}
return current;
return newPower;
}
/**
* Taxes a flat rate on all incoming power.
*
* <p/>
* Defaults to 0% tax rate.
*
* @return percent of input to tax
@ -111,33 +117,50 @@ public final class PowerHandler {
return 0;
}
}
public static final PerditionCalculator DEFAULT_PERDITION = new PerditionCalculator();
public static final double ROLLING_AVERAGE_WEIGHT = 100.0;
public static final double ROLLING_AVERAGE_NUMERATOR = ROLLING_AVERAGE_WEIGHT - 1;
public static final double ROLLING_AVERAGE_DENOMINATOR = 1.0 / ROLLING_AVERAGE_WEIGHT;
private double minEnergyReceived;
private double maxEnergyReceived;
private double maxEnergyStored;
private double activationEnergy;
private double energyStored = 0;
private final SafeTimeTracker doWorkTracker = new SafeTimeTracker();
private final SafeTimeTracker sourcesTracker = new SafeTimeTracker();
private final SafeTimeTracker perditionTracker = new SafeTimeTracker();
public static final double ROLLING_AVERAGE_DENOMINATOR = 1.0 / ROLLING_AVERAGE_WEIGHT;
public final int[] powerSources = new int[6];
public final IPowerReceptor receptor;
private double activationEnergy;
private final SafeTimeTracker doWorkTracker = new SafeTimeTracker(1);
private final SafeTimeTracker sourcesTracker = new SafeTimeTracker(1);
private final SafeTimeTracker perditionTracker = new SafeTimeTracker(1);
private PerditionCalculator perdition;
private final PowerReceiver receiver;
private final Type type;
private IBatteryObject battery;
// Tracking
private double averageLostPower = 0;
private double averageReceivedPower = 0;
private double averageUsedPower = 0;
public PowerHandler(IPowerReceptor receptor, Type type) {
this(receptor, type, null);
}
public PowerHandler(IPowerReceptor receptor, Type type, Object battery) {
this.receptor = receptor;
this.type = type;
this.receiver = new PowerReceiver();
this.perdition = DEFAULT_PERDITION;
boolean created = false;
if (battery instanceof IBatteryObject) {
this.battery = (BatteryObject) battery;
} else if (battery != null) {
this.battery = MjAPI.createBattery(battery, MjAPI.DEFAULT_POWER_FRAMEWORK, ForgeDirection.UNKNOWN);
created = true;
} else {
this.battery = MjAPI.createBattery(new AnonymousBattery(), MjAPI.DEFAULT_POWER_FRAMEWORK, ForgeDirection.UNKNOWN);
created = true;
}
if (receptor instanceof IPowerEmitter && created) {
MjAPI.reconfigure().mode(this.battery, IOMode.Send);
}
}
public PowerReceiver getPowerReceiver() {
@ -145,15 +168,15 @@ public final class PowerHandler {
}
public double getMinEnergyReceived() {
return minEnergyReceived;
return battery.minimumConsumption();
}
public double getMaxEnergyReceived() {
return maxEnergyReceived;
return battery.getEnergyRequested();
}
public double getMaxEnergyStored() {
return maxEnergyStored;
return battery.maxCapacity();
}
public double getActivationEnergy() {
@ -161,40 +184,54 @@ public final class PowerHandler {
}
public double getEnergyStored() {
return energyStored;
return battery.getEnergyStored();
}
@Override
public IBatteryObject getMjBattery(String kind) {
return battery.kind().equals(kind) ? battery : null;
}
/**
* Setup your PowerHandler's settings.
*
* @param minEnergyReceived This is the minimum about of power that will be
* accepted by the PowerHandler. This should generally be greater than the
* activationEnergy if you plan to use the doWork() callback. Anything
* greater than 1 will prevent Redstone Engines from powering this Provider.
* @param maxEnergyReceived The maximum amount of power accepted by the
* PowerHandler. This should generally be less than 500. Too low and larger
* engines will overheat while trying to power the machine. Too high, and
* the engines will never warm up. Greater values also place greater strain
* on the power net.
* @param activationEnergy If the stored energy is greater than this value,
* the doWork() callback is called (once per tick).
* @param maxStoredEnergy The maximum amount of power this PowerHandler can
* store. Values tend to range between 100 and 5000. With 1000 and 1500
* being common.
* @param minEnergyReceived
* This is the minimum about of power that will be accepted by
* the PowerHandler. This should generally be greater than the
* activationEnergy if you plan to use the doWork() callback.
* Anything greater than 1 will prevent Redstone Engines from
* powering this Provider.
* @param maxEnergyReceived
* The maximum amount of power accepted by the PowerHandler. This
* should generally be less than 500. Too low and larger engines
* will overheat while trying to power the machine. Too high, and
* the engines will never warm up. Greater values also place
* greater strain on the power net.
* @param activationEnergy
* If the stored energy is greater than this value, the doWork()
* callback is called (once per tick).
* @param maxStoredEnergy
* The maximum amount of power this PowerHandler can store.
* Values tend to range between 100 and 5000. With 1000 and 1500
* being common.
*/
public void configure(double minEnergyReceived, double maxEnergyReceived, double activationEnergy, double maxStoredEnergy) {
if (minEnergyReceived > maxEnergyReceived) {
maxEnergyReceived = minEnergyReceived;
public void configure(double minEnergyReceived, double maxEnergyReceived, double activationEnergy,
double maxStoredEnergy) {
double localMaxEnergyReceived = maxEnergyReceived;
if (minEnergyReceived > localMaxEnergyReceived) {
localMaxEnergyReceived = minEnergyReceived;
}
this.minEnergyReceived = minEnergyReceived;
this.maxEnergyReceived = maxEnergyReceived;
this.maxEnergyStored = maxStoredEnergy;
this.activationEnergy = activationEnergy;
MjAPI.reconfigure().maxCapacity(battery, maxStoredEnergy);
MjAPI.reconfigure().maxReceivedPerCycle(battery, localMaxEnergyReceived);
MjAPI.reconfigure().minimumConsumption(battery, minEnergyReceived);
}
/**
* Allows you define perdition in terms of loss/ticks.
*
* <p/>
* This function is mostly for legacy implementations. See
* PerditionCalculator for more complex perdition formulas.
*
@ -213,28 +250,32 @@ public final class PowerHandler {
/**
* Allows you to define a new PerditionCalculator class to handler perdition
* calculations.
*
* <p/>
* For example if you want exponentially increasing loss based on amount
* stored.
*
* @param perdition
*/
public void setPerdition(PerditionCalculator perdition) {
if (perdition == null)
perdition = DEFAULT_PERDITION;
this.perdition = perdition;
if (perdition == null) {
this.perdition = DEFAULT_PERDITION;
} else {
this.perdition = perdition;
}
}
public PerditionCalculator getPerdition() {
if (perdition == null)
if (perdition == null) {
return DEFAULT_PERDITION;
return perdition;
} else {
return perdition;
}
}
/**
* Ticks the power handler. You should call this if you can, but its not
* required.
*
* <p/>
* If you don't call it, the possibility exists for some weirdness with the
* perdition algorithm and work callback as its possible they will not be
* called on every tick they otherwise would be. You should be able to
@ -247,29 +288,28 @@ public final class PowerHandler {
}
private void applyPerdition() {
if (perditionTracker.markTimeIfDelay(receptor.getWorld(), 1) && energyStored > 0) {
double prev = energyStored;
double energyStored = getEnergyStored();
if (perditionTracker.markTimeIfDelay(receptor.getWorld()) && energyStored > 0) {
double newEnergy = getPerdition().applyPerdition(this, energyStored, perditionTracker.durationOfLastDelay());
if (newEnergy == 0 || newEnergy < energyStored)
energyStored = newEnergy;
else
energyStored = DEFAULT_PERDITION.applyPerdition(this, energyStored, perditionTracker.durationOfLastDelay());
if (newEnergy != energyStored) {
battery.setEnergyStored(energyStored = newEnergy);
}
validateEnergy();
averageLostPower = (averageLostPower * ROLLING_AVERAGE_NUMERATOR + (prev - energyStored)) * ROLLING_AVERAGE_DENOMINATOR;
averageLostPower = (averageLostPower * ROLLING_AVERAGE_NUMERATOR + (getEnergyStored() - energyStored)) * ROLLING_AVERAGE_DENOMINATOR;
}
}
private void applyWork() {
if (energyStored >= activationEnergy) {
if (doWorkTracker.markTimeIfDelay(receptor.getWorld(), 1)) {
if (getEnergyStored() >= activationEnergy) {
if (doWorkTracker.markTimeIfDelay(receptor.getWorld())) {
receptor.doWork(this);
}
}
}
private void updateSources(ForgeDirection source) {
if (sourcesTracker.markTimeIfDelay(receptor.getWorld(), 1)) {
if (sourcesTracker.markTimeIfDelay(receptor.getWorld())) {
for (int i = 0; i < 6; ++i) {
powerSources[i] -= sourcesTracker.durationOfLastDelay();
if (powerSources[i] < 0) {
@ -278,8 +318,9 @@ public final class PowerHandler {
}
}
if (source != null)
if (source != null) {
powerSources[source.ordinal()] = 10;
}
}
/**
@ -296,6 +337,7 @@ public final class PowerHandler {
double result = 0;
double energyStored = getEnergyStored();
if (energyStored >= min) {
if (energyStored <= max) {
result = energyStored;
@ -309,11 +351,15 @@ public final class PowerHandler {
}
}
}
if (energyStored != getEnergyStored()) {
battery.setEnergyStored(energyStored);
}
validateEnergy();
if (doUse)
if (doUse) {
averageUsedPower = (averageUsedPower * ROLLING_AVERAGE_NUMERATOR + result) * ROLLING_AVERAGE_DENOMINATOR;
}
return result;
}
@ -324,7 +370,7 @@ public final class PowerHandler {
public void readFromNBT(NBTTagCompound data, String tag) {
NBTTagCompound nbt = data.getCompoundTag(tag);
energyStored = nbt.getDouble("energyStored");
battery.setEnergyStored(nbt.getDouble("energyStored"));
}
public void writeToNBT(NBTTagCompound data) {
@ -333,7 +379,7 @@ public final class PowerHandler {
public void writeToNBT(NBTTagCompound data, String tag) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setDouble("energyStored", energyStored);
nbt.setDouble("energyStored", battery.getEnergyStored());
data.setTag(tag, nbt);
}
@ -343,15 +389,15 @@ public final class PowerHandler {
}
public double getMinEnergyReceived() {
return minEnergyReceived;
return PowerHandler.this.getMinEnergyReceived();
}
public double getMaxEnergyReceived() {
return maxEnergyReceived;
return PowerHandler.this.getMaxEnergyReceived();
}
public double getMaxEnergyStored() {
return maxEnergyStored;
return PowerHandler.this.getMaxEnergyStored();
}
public double getActivationEnergy() {
@ -359,7 +405,7 @@ public final class PowerHandler {
}
public double getEnergyStored() {
return energyStored;
return PowerHandler.this.getEnergyStored();
}
public double getAveragePowerReceived() {
@ -384,17 +430,15 @@ public final class PowerHandler {
/**
* The amount of power that this PowerHandler currently needs.
*
* @return
*/
public double powerRequest() {
update();
return Math.min(maxEnergyReceived, maxEnergyStored - energyStored);
return battery.getEnergyRequested();
}
/**
* Add power to the PowerReceiver from an external source.
*
* <p/>
* IPowerEmitters are responsible for calling this themselves.
*
* @param quantity
@ -404,10 +448,10 @@ public final class PowerHandler {
public double receiveEnergy(Type source, final double quantity, ForgeDirection from) {
double used = quantity;
if (source == Type.ENGINE) {
if (used < minEnergyReceived) {
if (used < getMinEnergyReceived()) {
return 0;
} else if (used > maxEnergyReceived) {
used = maxEnergyReceived;
} else if (used > getMaxEnergyReceived()) {
used = getMaxEnergyReceived();
}
}
@ -420,37 +464,30 @@ public final class PowerHandler {
applyWork();
if (source == Type.ENGINE && type.eatsEngineExcess()) {
used = Math.min(quantity, maxEnergyReceived);
used = Math.min(quantity, getMaxEnergyReceived());
}
averageReceivedPower = (averageReceivedPower * ROLLING_AVERAGE_NUMERATOR + used) * ROLLING_AVERAGE_DENOMINATOR;
return used;
}
public IBatteryObject getMjBattery() {
return battery;
}
}
/**
*
* @return the amount the power changed by
*/
public double addEnergy(double quantity) {
energyStored += quantity;
if (energyStored > maxEnergyStored) {
quantity -= energyStored - maxEnergyStored;
energyStored = maxEnergyStored;
} else if (energyStored < 0) {
quantity -= energyStored;
energyStored = 0;
}
final double used = battery.addEnergy(quantity);
applyPerdition();
return quantity;
return used;
}
public void setEnergy(double quantity) {
this.energyStored = quantity;
battery.setEnergyStored(quantity);
validateEnergy();
}
@ -459,11 +496,21 @@ public final class PowerHandler {
}
private void validateEnergy() {
double energyStored = getEnergyStored();
double maxEnergyStored = getMaxEnergyStored();
if (energyStored < 0) {
energyStored = 0;
}
if (energyStored > maxEnergyStored) {
energyStored = maxEnergyStored;
}
if (energyStored != battery.getEnergyStored()) {
battery.setEnergyStored(energyStored);
}
}
private static class AnonymousBattery {
@MjBattery
public double mjStored;
}
}

View file

@ -1,3 +1,11 @@
@API(apiVersion="1.1",owner="BuildCraftAPI|core",provides="BuildCraftAPI|power")
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "1.1", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|power")
package buildcraft.api.power;
import cpw.mods.fml.common.API;

View file

@ -0,0 +1,19 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
public final class BuildcraftRecipeRegistry {
public static IAssemblyRecipeManager assemblyTable;
public static IIntegrationRecipeManager integrationTable;
public static IRefineryRecipeManager refinery;
private BuildcraftRecipeRegistry() {
}
}

View file

@ -0,0 +1,25 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import java.util.ArrayList;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
public class CraftingResult<T> {
public T crafted = null;
public ArrayList<ItemStack> usedItems = new ArrayList<ItemStack>();
public ArrayList<FluidStack> usedFluids = new ArrayList<FluidStack>();
public double energyCost = 0;
public long craftingTime = 0;
public IFlexibleRecipe<?> recipe;
}

View file

@ -0,0 +1,33 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import java.util.Collection;
import net.minecraft.item.ItemStack;
public interface IAssemblyRecipeManager {
/**
* Add an Assembly Table recipe.
*
* @param input
* Object... containing either an ItemStack, or a paired string
* and integer(ex: "dyeBlue", 1)
* @param energyCost
* MJ cost to produce
* @param output
* resulting ItemStack
*/
void addRecipe(String id, double energyCost, ItemStack output, Object... input);
void addRecipe(IFlexibleRecipe<ItemStack> recipe);
Collection<IFlexibleRecipe<ItemStack>> getRecipes();
}

View file

@ -0,0 +1,29 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
public interface IFlexibleCrafter {
int getCraftingItemStackSize();
ItemStack getCraftingItemStack(int slotid);
ItemStack decrCraftingItemgStack(int slotid, int val);
FluidStack getCraftingFluidStack(int tankid);
FluidStack decrCraftingFluidStack(int tankid, int val);
int getCraftingFluidStackSize();
}

View file

@ -0,0 +1,18 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
public interface IFlexibleRecipe<T> {
boolean canBeCrafted(IFlexibleCrafter crafter);
CraftingResult<T> craft(IFlexibleCrafter crafter, boolean preview);
String getId();
}

View file

@ -0,0 +1,19 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import net.minecraft.item.ItemStack;
public interface IIntegrationRecipe extends IFlexibleRecipe<ItemStack> {
boolean isValidInputA(ItemStack inputA);
boolean isValidInputB(ItemStack inputB);
}

View file

@ -0,0 +1,25 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import java.util.List;
/**
* The Integration Table's primary purpose is to modify an input item's NBT
* data. As such its not a "traditional" type of recipe. Rather than predefined
* inputs and outputs, it takes an input and transforms it.
*/
public interface IIntegrationRecipeManager {
/**
* Add an Integration Table recipe.
*/
void addRecipe(IIntegrationRecipe recipe);
List<? extends IIntegrationRecipe> getRecipes();
}

View file

@ -0,0 +1,25 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.recipes;
import java.util.Collection;
import net.minecraftforge.fluids.FluidStack;
public interface IRefineryRecipeManager {
void addRecipe(String id, FluidStack ingredient, FluidStack result, int energy, int delay);
void addRecipe(String id, FluidStack ingredient1, FluidStack ingredient2, FluidStack result, int energy, int delay);
Collection<IFlexibleRecipe<FluidStack>> getRecipes();
IFlexibleRecipe<FluidStack> getRecipe(String currentRecipeId);
}

View file

@ -0,0 +1,12 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "2.0", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|recipes")
package buildcraft.api.recipes;
import cpw.mods.fml.common.API;

View file

@ -25,7 +25,7 @@ public interface IToolWrench {
*
* @return true if wrenching is allowed, false if not
*/
public boolean canWrench(EntityPlayer player, int x, int y, int z);
boolean canWrench(EntityPlayer player, int x, int y, int z);
/***
* Callback after the wrench has been used. This can be used to decrease durability or for other purposes. To get the ItemStack that was used, check
@ -36,5 +36,5 @@ public interface IToolWrench {
* @param x
* ,y,z - The coordinates of the block being wrenched
*/
public void wrenchUsed(EntityPlayer player, int x, int y, int z);
void wrenchUsed(EntityPlayer player, int x, int y, int z);
}

View file

@ -1,3 +1,11 @@
@API(apiVersion="1.0",owner="BuildCraftAPI|core",provides="BuildCraftAPI|tools")
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "1.0", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|tools")
package buildcraft.api.tools;
import cpw.mods.fml.common.API;

View file

@ -0,0 +1,29 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.transport;
import net.minecraft.world.World;
/**
* Implement and register with the PipeManager if you want to suppress connections from wooden pipes.
*/
public interface IExtractionHandler {
/**
* Can this pipe extract items from the block located at these coordinates?
* param extractor can be null
*/
boolean canExtractItems(Object extractor, World world, int i, int j, int k);
/**
* Can this pipe extract liquids from the block located at these coordinates?
* param extractor can be null
*/
boolean canExtractFluids(Object extractor, World world, int i, int j, int k);
}

View file

@ -0,0 +1,26 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.transport;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public interface IPipe {
int x();
int y();
int z();
IPipeTile getTile();
TileEntity getAdjacentTile(ForgeDirection dir);
}

View file

@ -0,0 +1,31 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.transport;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.transport.IPipeTile.PipeType;
public interface IPipeConnection {
enum ConnectOverride {
CONNECT, DISCONNECT, DEFAULT
};
/**
* Allows you to override pipe connection logic.
*
* @param type
* @param with
* @return CONNECT to force a connection, DISCONNECT to force no connection,
* and DEFAULT to let the pipe decide.
*/
ConnectOverride overridePipeConnection(PipeType type, ForgeDirection with);
}

View file

@ -0,0 +1,32 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.transport;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
public interface IPipePluggable {
void writeToNBT(NBTTagCompound nbt);
void readFromNBT(NBTTagCompound nbt);
ItemStack[] getDropItems(IPipeTile pipe);
void onAttachedPipe(IPipeTile pipe, ForgeDirection direction);
void onDetachedPipe(IPipeTile pipe, ForgeDirection direction);
boolean blocking(IPipeTile pipe, ForgeDirection direction);
void invalidate();
void validate(IPipeTile pipe, ForgeDirection direction);
}

View file

@ -9,6 +9,7 @@
package buildcraft.api.transport;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
public interface IPipeTile {
@ -35,7 +36,7 @@ public interface IPipeTile {
/**
* True if the pipe is connected to the block/pipe in the specific direction
*
* @param wire
* @param with
* @return true if connect
*/
boolean isPipeConnected(ForgeDirection with);

View file

@ -0,0 +1,49 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.transport;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.world.World;
public abstract class PipeManager {
public static List<IExtractionHandler> extractionHandlers = new ArrayList<IExtractionHandler>();
public static void registerExtractionHandler(IExtractionHandler handler) {
extractionHandlers.add(handler);
}
/**
* param extractor can be null
*/
public static boolean canExtractItems(Object extractor, World world, int i, int j, int k) {
for (IExtractionHandler handler : extractionHandlers) {
if (!handler.canExtractItems(extractor, world, i, j, k)) {
return false;
}
}
return true;
}
/**
* param extractor can be null
*/
public static boolean canExtractFluids(Object extractor, World world, int i, int j, int k) {
for (IExtractionHandler handler : extractionHandlers) {
if (!handler.canExtractFluids(extractor, world, i, j, k)) {
return false;
}
}
return true;
}
}

View file

@ -9,6 +9,7 @@
package buildcraft.api.transport;
import java.util.Locale;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@ -35,27 +36,39 @@ public enum PipeWire {
return name().toLowerCase(Locale.ENGLISH) + "PipeWire";
}
public String getColor() {
String name = this.toString().toLowerCase(Locale.ENGLISH);
char first = Character.toUpperCase(name.charAt(0));
return first + name.substring(1);
}
public ItemStack getStack() {
return getStack(1);
}
public ItemStack getStack(int qty) {
if (item == null)
if (item == null) {
return null;
return new ItemStack(item, qty, ordinal());
} else {
return new ItemStack(item, qty, ordinal());
}
}
public boolean isPipeWire(ItemStack stack) {
if (stack == null)
if (stack == null) {
return false;
if (stack.getItem() != item)
} else if (stack.getItem() != item) {
return false;
return stack.getItemDamage() == ordinal();
} else {
return stack.getItemDamage() == ordinal();
}
}
public static PipeWire fromOrdinal(int ordinal) {
if (ordinal < 0 || ordinal >= VALUES.length)
if (ordinal < 0 || ordinal >= VALUES.length) {
return RED;
return VALUES[ordinal];
} else {
return VALUES[ordinal];
}
}
}

View file

@ -1,3 +1,12 @@
@API(apiVersion="2.0",owner="BuildCraftAPI|core",provides="BuildCraftAPI|transport")
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
@API(apiVersion = "2.0", owner = "BuildCraftAPI|core", provides = "BuildCraftAPI|transport")
package buildcraft.api.transport;
import cpw.mods.fml.common.API;

View file

@ -0,0 +1,18 @@
package ic2.api.energy;
/**
* Provides access to the energy network.
*
* The old EnergyNet methods missing in IEnergyNet have been migrated to events (load, unload) or
* removed (tiles no longer emit energy actively, the energy net implementation requests it).
*
* See ic2/api/energy/usage.txt for an overall description of the energy net api.
*/
public final class EnergyNet {
/**
* Instance of the global EnergyNet class.
*/
public static IEnergyNet instance;
}

View file

@ -0,0 +1,72 @@
package ic2.api.energy;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Interface representing the methods provided by the global EnergyNet class.
*
* See ic2/api/energy/usage.txt for an overall description of the energy net api.
*/
public interface IEnergyNet {
/**
* Get the EnergyNet-registered tile entity at the specified position.
*
* This is not the same as World.getTileEntity(), it's possible to register delegate tile
* entities with the energy net which are different from what's actually in the world. Those
* delegates allow to use separate TileEntity objects just for the EnergyNet interfaces,
* simplifying cross-mod dependencies and multi-blocks.
*
* @param world World containing the tile entity
* @param x x-coordinate
* @param y y-coordinate
* @param z z-coordinate
* @return tile entity registered to the energy net or null if none is registered
*/
TileEntity getTileEntity(World world, int x, int y, int z);
/**
* Get the EnergyNet-registered neighbor tile entity at the specified position.
*
* @param te TileEntity indicating the world and position to search from
* @param dir direction the neighbor is to be found
* @return neighbor tile entity registered to the energy net or null if none is registered
*/
TileEntity getNeighbor(TileEntity te, ForgeDirection dir);
/**
* determine how much energy has been emitted by the EnergyEmitter specified
*
* @note call this twice with x ticks delay to get the avg. emitted power p = (call2 - call1) / x EU/tick
*
* @param tileEntity energy emitter
*/
double getTotalEnergyEmitted(TileEntity tileEntity);
/**
* determine how much energy has been sunken by the EnergySink specified
*
* @note call this twice with x ticks delay to get the avg. sunken power p = (call2 - call1) / x EU/tick
*
* @param tileEntity energy emitter
*/
double getTotalEnergySunken(TileEntity tileEntity);
/**
* Determine the typical power used by the specific tier, e.g. 128 eu/t for tier 2.
*
* @param tier tier
* @return power in eu/t
*/
double getPowerFromTier(int tier);
/**
* Determine minimum tier required to handle the specified power, e.g. tier 2 for 128 eu/t.
*
* @param power in eu/t
* @return tier
*/
int getTierFromPower(double power);
}

View file

@ -11,15 +11,23 @@ public interface IEnergySink extends IEnergyAcceptor {
/**
* Determine how much energy the sink accepts.
*
* This value is unrelated to getMaxSafeInput().
*
* Make sure that injectEnergy() does accepts energy if demandsEnergy() returns anything > 0.
*
* @note Modifying the energy net from this method is disallowed.
*
* @return max accepted input in eu
*/
double demandedEnergyUnits();
double getDemandedEnergy();
/**
* Determine the tier of this energy sink.
* 1 = LV, 2 = MV, 3 = HV, 4 = EV etc.
*
* @note Modifying the energy net from this method is disallowed.
*
* @return tier of this energy sink
*/
int getSinkTier();
/**
* Transfer energy to the sink.
@ -31,20 +39,6 @@ public interface IEnergySink extends IEnergyAcceptor {
* @param amount energy to be transferred
* @return Energy not consumed (leftover)
*/
double injectEnergyUnits(ForgeDirection directionFrom, double amount);
/**
* Determine the amount of eu which can be safely injected into the specific energy sink without exploding.
*
* Typical values are 32 for LV, 128 for MV, 512 for HV and 2048 for EV. A value of Integer.MAX_VALUE indicates no
* limit.
*
* This value is unrelated to demandsEnergy().
*
* @note Modifying the energy net from this method is disallowed.
*
* @return max safe input in eu
*/
int getMaxSafeInput();
double injectEnergy(ForgeDirection directionFrom, double amount, double voltage);
}

View file

@ -24,5 +24,15 @@ public interface IEnergySource extends IEnergyEmitter {
* @param amount amount of EU to draw, may be negative
*/
void drawEnergy(double amount);
/**
* Determine the tier of this energy source.
* 1 = LV, 2 = MV, 3 = HV, 4 = EV etc.
*
* @note Modifying the energy net from this method is disallowed.
*
* @return tier of this energy source
*/
int getSourceTier();
}

View file

@ -10,5 +10,5 @@ public interface IEnergyValueProvider {
* @param itemStack ItemStack containing the item to evaluate.
* @return energy in EU
*/
int getEnergyValue(ItemStack itemStack);
double getEnergyValue(ItemStack itemStack);
}

View file

@ -1,13 +1,12 @@
package ic2.api.item;
import net.minecraft.entity.player.EntityPlayer;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.ItemStack;
/**
* Allows for charging, discharging and using electric items (IElectricItem).
*
* The charge or remaining capacity of an item can be determined by calling charge/discharge with
* ignoreTransferLimit and simulate set to true.
*/
public final class ElectricItem {
/**
@ -25,84 +24,36 @@ public final class ElectricItem {
public static IElectricItemManager rawManager;
/**
* Charge an item with a specified amount of energy
* Register an electric item manager for items not implementing IElectricItem.
*
* @param itemStack electric item's stack
* @param amount amount of energy to charge in EU
* @param tier tier of the charging device, has to be at least as high as the item to charge
* @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit()
* @param simulate don't actually change the item, just determine the return value
* @return Energy transferred into the electric item
* This method is only designed for special purposes, implementing IElectricItem or
* ISpecialElectricItem instead of using this is faster.
*
* @deprecated use manager.charge() instead
* Managers used with ISpecialElectricItem shouldn't be registered.
*
* @param manager Manager to register.
*/
@Deprecated
public static int charge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate) {
return manager.charge(itemStack, amount, tier, ignoreTransferLimit, simulate);
public static void registerBackupManager(IBackupElectricItemManager manager) {
backupManagers.add(manager);
}
/**
* Discharge an item by a specified amount of energy
* Get the electric item manager suitable for the supplied item stack.
*
* @param itemStack electric item's stack
* @param amount amount of energy to charge in EU
* @param tier tier of the discharging device, has to be at least as high as the item to discharge
* @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit()
* @param simulate don't actually discharge the item, just determine the return value
* @return Energy retrieved from the electric item
* This method is for internal use only.
*
* @deprecated use manager.discharge() instead
* @param stack ItemStack to be handled.
* @return First suitable electric item manager.
*/
@Deprecated
public static int discharge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate) {
return manager.discharge(itemStack, amount, tier, ignoreTransferLimit, simulate);
public static IBackupElectricItemManager getBackupManager(ItemStack stack) {
for (IBackupElectricItemManager manager : backupManagers) {
if (manager.handles(stack)) return manager;
}
return null;
}
/**
* Determine if the specified electric item has at least a specific amount of EU.
* This is supposed to be used in the item code during operation, for example if you want to implement your own electric item.
* BatPacks are not taken into account.
*
* @param itemStack electric item's stack
* @param amount minimum amount of energy required
* @return true if there's enough energy
*
* @deprecated use manager.canUse() instead
*/
@Deprecated
public static boolean canUse(ItemStack itemStack, int amount) {
return manager.canUse(itemStack, amount);
}
/**
* Try to retrieve a specific amount of energy from an Item, and if applicable, a BatPack.
* This is supposed to be used in the item code during operation, for example if you want to implement your own electric item.
*
* @param itemStack electric item's stack
* @param amount amount of energy to discharge in EU
* @param player player holding the item
* @return true if the operation succeeded
*
* @deprecated use manager.use() instead
*/
@Deprecated
public static boolean use(ItemStack itemStack, int amount, EntityPlayer player) {
return manager.use(itemStack, amount, player);
}
/**
* Charge an item from the BatPack a player is wearing.
* This is supposed to be used in the item code during operation, for example if you want to implement your own electric item.
* use() already contains this functionality.
*
* @param itemStack electric item's stack
* @param player player holding the item
*
* @deprecated use manager.chargeFromArmor() instead
*/
@Deprecated
public static void chargeFromArmor(ItemStack itemStack, EntityPlayer player) {
manager.chargeFromArmor(itemStack, player);
}
private static final List<IBackupElectricItemManager> backupManagers = new ArrayList<IBackupElectricItemManager>();
}

View file

@ -0,0 +1,12 @@
package ic2.api.item;
import net.minecraft.item.ItemStack;
/**
* This interface specifies a manager applicable to items not implementing IElectricItem.
*
* The manager implementing this has to be registered with ElectricItem.registerBackupManager().
*/
public interface IBackupElectricItemManager extends IElectricItemManager {
boolean handles(ItemStack stack);
}

View file

@ -35,7 +35,7 @@ public interface IElectricItem {
*
* @return Maximum charge energy
*/
int getMaxCharge(ItemStack itemStack);
double getMaxCharge(ItemStack itemStack);
/**
* Get the item's tier, lower tiers can't send energy to higher ones.
@ -50,6 +50,6 @@ public interface IElectricItem {
*
* @return Transfer limit
*/
int getTransferLimit(ItemStack itemStack);
double getTransferLimit(ItemStack itemStack);
}

View file

@ -19,7 +19,7 @@ import net.minecraft.item.ItemStack;
*/
public interface IElectricItemManager {
/**
* Charge an item with a specified amount of energy
* Charge an item with a specified amount of energy.
*
* @param itemStack electric item's stack
* @param amount amount of energy to charge in EU
@ -28,27 +28,28 @@ public interface IElectricItemManager {
* @param simulate don't actually change the item, just determine the return value
* @return Energy transferred into the electric item
*/
int charge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate);
double charge(ItemStack stack, double amount, int tier, boolean ignoreTransferLimit, boolean simulate);
/**
* Discharge an item by a specified amount of energy
*
* @param itemStack electric item's stack
* @param amount amount of energy to charge in EU
* @param amount amount of energy to discharge in EU
* @param tier tier of the discharging device, has to be at least as high as the item to discharge
* @param ignoreTransferLimit ignore the transfer limit specified by getTransferLimit()
* @param externally use the supplied item externally, i.e. to power something else as if it was a battery
* @param simulate don't actually discharge the item, just determine the return value
* @return Energy retrieved from the electric item
*/
int discharge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate);
double discharge(ItemStack stack, double amount, int tier, boolean ignoreTransferLimit, boolean externally, boolean simulate);
/**
* Determine the charge level for the specified item
* Determine the charge level for the specified item.
*
* @param itemStack ItemStack containing the electric item
* @return charge level in EU
*/
int getCharge(ItemStack itemStack);
double getCharge(ItemStack stack);
/**
* Determine if the specified electric item has at least a specific amount of EU.
@ -59,7 +60,7 @@ public interface IElectricItemManager {
* @param amount minimum amount of energy required
* @return true if there's enough energy
*/
boolean canUse(ItemStack itemStack, int amount);
boolean canUse(ItemStack stack, double amount);
/**
* Try to retrieve a specific amount of energy from an Item, and if applicable, a BatPack.
@ -70,7 +71,7 @@ public interface IElectricItemManager {
* @param entity entity holding the item
* @return true if the operation succeeded
*/
boolean use(ItemStack itemStack, int amount, EntityLivingBase entity);
boolean use(ItemStack stack, double amount, EntityLivingBase entity);
/**
* Charge an item from the BatPack a player is wearing.
@ -80,7 +81,7 @@ public interface IElectricItemManager {
* @param itemStack electric item's stack
* @param entity entity holding the item
*/
void chargeFromArmor(ItemStack itemStack, EntityLivingBase entity);
void chargeFromArmor(ItemStack stack, EntityLivingBase entity);
/**
* Get the tool tip to display for electric items.
@ -88,5 +89,5 @@ public interface IElectricItemManager {
* @param itemStack ItemStack to determine the tooltip for
* @return tool tip string or null for none
*/
String getToolTip(ItemStack itemStack);
String getToolTip(ItemStack stack);
}

View file

@ -0,0 +1,32 @@
package ic2.api.recipe;
import java.util.Map;
import net.minecraftforge.fluids.Fluid;
public interface IFluidHeatManager extends ILiquidAcceptManager {
/**
* Add a new fluid to the Fluid Heat Generator.
*
* @param fluidName the fluid to burn
* @param amount amount of fluid to consume per tick
* @param heat amount of heat generated per tick
*/
void addFluid(String fluidName, int amount, int heat);
BurnProperty getBurnProperty(Fluid fluid);
Map<String, BurnProperty> getBurnProperties();
public static class BurnProperty {
public BurnProperty(int amount1, int heat1) {
this.amount = amount1;
this.heat = heat1;
}
public final int amount;
public final int heat;
}
}

View file

@ -1,7 +1,5 @@
package ic2.api.recipe;
/**
* General recipe registry.
*
@ -55,5 +53,6 @@ public class Recipes {
public static ICraftingRecipeManager advRecipes;
public static ISemiFluidFuelManager semiFluidGenerator;
public static IFluidHeatManager FluidHeatGenerator;
}

View file

@ -0,0 +1,6 @@
package mekanism.api.reactor;
public interface INeutronCapture extends IReactorBlock
{
public int absorbNeutrons(int neutrons);
}

View file

@ -0,0 +1,7 @@
package mekanism.api.reactor;
public interface IReactorBlock
{
public boolean isFrame();
}

View file

@ -1,5 +1,6 @@
package mekanism.common;
import ic2.api.energy.EnergyNet;
import ic2.api.energy.tile.IEnergySink;
import java.util.Arrays;
@ -210,9 +211,9 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
}
else if(MekanismUtils.useIC2() && acceptor instanceof IEnergySink)
{
double toSend = Math.min(currentSending, ((IEnergySink)acceptor).getMaxSafeInput()*Mekanism.FROM_IC2);
toSend = Math.min(toSend, ((IEnergySink)acceptor).demandedEnergyUnits()*Mekanism.FROM_IC2);
sent += (toSend - (((IEnergySink)acceptor).injectEnergyUnits(side.getOpposite(), toSend*Mekanism.TO_IC2)*Mekanism.FROM_IC2));
double toSend = Math.min(currentSending, EnergyNet.instance.getPowerFromTier(((IEnergySink) acceptor).getSinkTier())*Mekanism.FROM_IC2);
toSend = Math.min(toSend, ((IEnergySink)acceptor).getDemandedEnergy()*Mekanism.FROM_IC2);
sent += (toSend - (((IEnergySink)acceptor).injectEnergy(side.getOpposite(), toSend*Mekanism.TO_IC2, 0)*Mekanism.FROM_IC2));
}
else if(MekanismUtils.useBuildCraft() && acceptor instanceof IPowerReceptor)
{
@ -280,7 +281,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
if(handler.acceptsEnergyFrom(null, side.getOpposite()))
{
if(Math.min((handler.demandedEnergyUnits()*Mekanism.FROM_IC2), (handler.getMaxSafeInput()*Mekanism.FROM_IC2)) > 0)
if(Math.min((handler.getDemandedEnergy()*Mekanism.FROM_IC2), (EnergyNet.instance.getPowerFromTier(handler.getSinkTier())*Mekanism.FROM_IC2)) > 0)
{
toReturn.add(acceptor);
}

View file

@ -182,7 +182,7 @@ public class EntityRobit extends EntityCreature implements IInventory, ISustaine
if(item.canProvideEnergy(inventory[27]))
{
double gain = ElectricItem.manager.discharge(inventory[27], (int)((MAX_ELECTRICITY - getEnergy())*Mekanism.TO_IC2), 4, true, false)*Mekanism.FROM_IC2;
double gain = ElectricItem.manager.discharge(inventory[27], (MAX_ELECTRICITY - getEnergy())*Mekanism.TO_IC2, 4, true, true, false)*Mekanism.FROM_IC2;
setEnergy(getEnergy() + gain);
}
}

View file

@ -19,7 +19,7 @@ public class IC2ItemManager implements IElectricItemManager
}
@Override
public int charge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate)
public double charge(ItemStack itemStack, double amount, int tier, boolean ignoreTransferLimit, boolean simulate)
{
if(energizedItem.canReceive(itemStack))
{
@ -38,7 +38,7 @@ public class IC2ItemManager implements IElectricItemManager
}
@Override
public int discharge(ItemStack itemStack, int amount, int tier, boolean ignoreTransferLimit, boolean simulate)
public double discharge(ItemStack itemStack, double amount, int tier, boolean ignoreTransferLimit, boolean external, boolean simulate)
{
if(energizedItem.canSend(itemStack))
{
@ -57,19 +57,19 @@ public class IC2ItemManager implements IElectricItemManager
}
@Override
public boolean canUse(ItemStack itemStack, int amount)
public boolean canUse(ItemStack itemStack, double amount)
{
return energizedItem.getEnergy(itemStack) >= amount*Mekanism.FROM_IC2;
}
@Override
public int getCharge(ItemStack itemStack)
public double getCharge(ItemStack itemStack)
{
return (int)Math.round(energizedItem.getEnergy(itemStack)*Mekanism.TO_IC2);
}
@Override
public boolean use(ItemStack itemStack, int amount, EntityLivingBase entity)
public boolean use(ItemStack itemStack, double amount, EntityLivingBase entity)
{
return false;
}

View file

@ -142,7 +142,7 @@ public class ItemBlockEnergyCube extends ItemBlock implements IEnergizedItem, IE
@Override
@Method(modid = "IC2API")
public int getMaxCharge(ItemStack itemStack)
public double getMaxCharge(ItemStack itemStack)
{
return 0;
}
@ -156,7 +156,7 @@ public class ItemBlockEnergyCube extends ItemBlock implements IEnergizedItem, IE
@Override
@Method(modid = "IC2API")
public int getTransferLimit(ItemStack itemStack)
public double getTransferLimit(ItemStack itemStack)
{
return 0;
}

View file

@ -401,7 +401,7 @@ public class ItemBlockMachine extends ItemBlock implements IEnergizedItem, ISpec
@Override
@Method(modid = "IC2API")
public int getMaxCharge(ItemStack itemStack)
public double getMaxCharge(ItemStack itemStack)
{
return 0;
}
@ -415,7 +415,7 @@ public class ItemBlockMachine extends ItemBlock implements IEnergizedItem, ISpec
@Override
@Method(modid = "IC2API")
public int getTransferLimit(ItemStack itemStack)
public double getTransferLimit(ItemStack itemStack)
{
return 0;
}
@ -443,7 +443,7 @@ public class ItemBlockMachine extends ItemBlock implements IEnergizedItem, ISpec
if(item.canProvideEnergy(inv.getStackInSlot(54)))
{
double gain = ElectricItem.manager.discharge(inv.getStackInSlot(54), (int)((getMaxEnergy(itemstack) - getEnergy(itemstack))*Mekanism.TO_IC2), 3, false, false)*Mekanism.FROM_IC2;
double gain = ElectricItem.manager.discharge(inv.getStackInSlot(54), (int)((getMaxEnergy(itemstack) - getEnergy(itemstack))*Mekanism.TO_IC2), 3, false, true, false)*Mekanism.FROM_IC2;
setEnergy(itemstack, getEnergy(itemstack) + gain);
}
}

View file

@ -87,7 +87,7 @@ public class ItemEnergized extends ItemMekanism implements IEnergizedItem, ISpec
@Override
@Method(modid = "IC2API")
public int getMaxCharge(ItemStack itemStack)
public double getMaxCharge(ItemStack itemStack)
{
return 0;
}
@ -101,7 +101,7 @@ public class ItemEnergized extends ItemMekanism implements IEnergizedItem, ISpec
@Override
@Method(modid = "IC2API")
public int getTransferLimit(ItemStack itemStack)
public double getTransferLimit(ItemStack itemStack)
{
return 0;
}

View file

@ -126,7 +126,7 @@ public class ItemFreeRunners extends ItemArmor implements IEnergizedItem, ISpeci
@Override
@Method(modid = "IC2API")
public int getMaxCharge(ItemStack itemStack)
public double getMaxCharge(ItemStack itemStack)
{
return 0;
}
@ -140,7 +140,7 @@ public class ItemFreeRunners extends ItemArmor implements IEnergizedItem, ISpeci
@Override
@Method(modid = "IC2API")
public int getTransferLimit(ItemStack itemStack)
public double getTransferLimit(ItemStack itemStack)
{
return 0;
}

View file

@ -359,38 +359,38 @@ public class TileEntityAdvancedBoundingBlock extends TileEntityBoundingBlock imp
@Override
@Method(modid = "IC2API")
public double demandedEnergyUnits()
public double getDemandedEnergy()
{
if(getInv() == null)
{
return 0;
}
return getInv().demandedEnergyUnits();
return getInv().getDemandedEnergy();
}
@Override
@Method(modid = "IC2API")
public double injectEnergyUnits(ForgeDirection directionFrom, double amount)
public double injectEnergy(ForgeDirection directionFrom, double amount, double voltage)
{
if(getInv() == null)
{
return amount;
}
return getInv().injectEnergyUnits(directionFrom, amount);
return getInv().injectEnergy(directionFrom, amount, voltage);
}
@Override
@Method(modid = "IC2API")
public int getMaxSafeInput()
public int getSinkTier()
{
if(getInv() == null)
{
return 0;
}
return getInv().getMaxSafeInput();
return getInv().getSinkTier();
}
public IAdvancedBoundingBlock getInv()

View file

@ -308,9 +308,9 @@ public abstract class TileEntityElectricBlock extends TileEntityContainerBlock i
@Override
@Method(modid = "IC2API")
public int getMaxSafeInput()
public int getSinkTier()
{
return Integer.MAX_VALUE;
return 4;
}
@Override
@ -371,7 +371,7 @@ public abstract class TileEntityElectricBlock extends TileEntityContainerBlock i
@Override
@Method(modid = "IC2API")
public double demandedEnergyUnits()
public double getDemandedEnergy()
{
return (getMaxEnergy() - getEnergy())*Mekanism.TO_IC2;
}
@ -391,7 +391,7 @@ public abstract class TileEntityElectricBlock extends TileEntityContainerBlock i
@Override
@Method(modid = "IC2API")
public double injectEnergyUnits(ForgeDirection direction, double i)
public double injectEnergy(ForgeDirection direction, double i, double v)
{
if(Coord4D.get(this).getFromSide(direction).getTileEntity(worldObj) instanceof IGridTransmitter)
{

View file

@ -1,5 +1,6 @@
package mekanism.common.util;
import ic2.api.energy.EnergyNet;
import ic2.api.energy.tile.IEnergyAcceptor;
import ic2.api.energy.tile.IEnergySink;
import ic2.api.energy.tile.IEnergySource;
@ -319,8 +320,8 @@ public final class CableUtils
{
if(((IEnergySink)tileEntity).acceptsEnergyFrom(from, side.getOpposite()))
{
double toSend = Math.min(sendingEnergy, Math.min(((IEnergySink)tileEntity).getMaxSafeInput(), ((IEnergySink)tileEntity).demandedEnergyUnits())*Mekanism.FROM_IC2);
double rejects = ((IEnergySink)tileEntity).injectEnergyUnits(side.getOpposite(), toSend*Mekanism.TO_IC2)*Mekanism.FROM_IC2;
double toSend = Math.min(sendingEnergy, Math.min(EnergyNet.instance.getPowerFromTier(((IEnergySink) tileEntity).getSinkTier()), ((IEnergySink)tileEntity).getDemandedEnergy())*Mekanism.FROM_IC2);
double rejects = ((IEnergySink)tileEntity).injectEnergy(side.getOpposite(), toSend*Mekanism.TO_IC2, 0)*Mekanism.FROM_IC2;
sent += (toSend - rejects);
}
}

View file

@ -31,7 +31,7 @@ public final class ChargeUtils
if(item.canProvideEnergy(storer.inventory[slotID]))
{
double gain = ElectricItem.manager.discharge(storer.inventory[slotID], (int)((storer.getMaxEnergy() - storer.getEnergy())*Mekanism.TO_IC2), 4, true, false)*Mekanism.FROM_IC2;
double gain = ElectricItem.manager.discharge(storer.inventory[slotID], (int)((storer.getMaxEnergy() - storer.getEnergy())*Mekanism.TO_IC2), 4, true, true, false)*Mekanism.FROM_IC2;
storer.setEnergy(storer.getEnergy() + gain);
}
}

View file

@ -0,0 +1,119 @@
package mekanism.generators.common;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mekanism.api.gas.GasRegistry;
import mekanism.api.gas.GasStack;
import mekanism.api.gas.GasTank;
import mekanism.api.reactor.INeutronCapture;
import mekanism.api.reactor.IReactorBlock;
import mekanism.generators.common.tile.TileEntityReactorController;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidTank;
import static java.lang.Math.min;
import static java.lang.Math.max;
public class FusionReactor
{
public static final int MAX_WATER = 100 * FluidContainerRegistry.BUCKET_VOLUME;
public static final int MAX_FUEL = 100 * FluidContainerRegistry.BUCKET_VOLUME;
public FluidTank waterTank = new FluidTank(MAX_WATER);
public GasTank steamTank = new GasTank(MAX_WATER*1000);
public GasTank deuteriumTank = new GasTank(MAX_FUEL);
public GasTank tritiumTank = new GasTank(MAX_FUEL);
public GasTank fuelTank = new GasTank(MAX_FUEL);
public TileEntityReactorController controller;
public Set<IReactorBlock> reactorBlocks = new HashSet<IReactorBlock>();
public Set<INeutronCapture> neutronCaptors = new HashSet<INeutronCapture>();
public double temperature;
public double ignitionTemperature = 10^7;
public double burnRatio = 1;
public double tempPerFuel = 100000;
public int injectionRate;
public boolean burning = false;
public boolean hasHohlraum = false;
public void simulate()
{
if(temperature >= ignitionTemperature)
{
if(!burning && hasHohlraum)
{
vaporiseHohlraum();
}
injectFuel();
int fuelBurned = burnFuel();
neutronFlux(fuelBurned);
}
else {
burning = false;
}
boilWater();
ambientLoss();
}
public void vaporiseHohlraum()
{
fuelTank.receive(new GasStack(GasRegistry.getGas("fusionFuel"), 1000), true);
burning = true;
}
public void injectFuel()
{
int amountNeeded = fuelTank.getNeeded();
int amountAvailable = 2*min(deuteriumTank.getStored(), tritiumTank.getStored());
int amountToInject = min(amountNeeded, min(amountAvailable, injectionRate));
amountToInject -= amountToInject % 2;
deuteriumTank.draw(amountToInject/2, true);
tritiumTank.draw(amountToInject/2, true);
fuelTank.receive(new GasStack(GasRegistry.getGas("fusionFuel"), amountToInject), true);
}
public int burnFuel()
{
int fuelBurned = (int)min(fuelTank.getStored(), max(0, temperature-ignitionTemperature)*burnRatio);
fuelTank.draw(fuelBurned, true);
temperature += tempPerFuel * fuelBurned;
return fuelBurned;
}
public void neutronFlux(int fuelBurned)
{
int neutronsRemaining = fuelBurned;
List<INeutronCapture> list = new ArrayList<INeutronCapture>(neutronCaptors);
Collections.shuffle(list);
for(INeutronCapture captor: neutronCaptors)
{
if(neutronsRemaining <= 0)
break;
neutronsRemaining = captor.absorbNeutrons(neutronsRemaining);
}
controller.radiateNeutrons(neutronsRemaining);
}
public void boilWater()
{
int waterToBoil = (int)min(waterTank.getFluidAmount(), temperature/1000);
}
public void ambientLoss()
{
temperature -= 0.1*temperature;
}
}

View file

@ -0,0 +1,12 @@
package mekanism.generators.common.block;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
public class BlockReactor extends Block
{
protected BlockReactor()
{
super(Material.iron);
}
}

View file

@ -207,7 +207,7 @@ public class ItemBlockGenerator extends ItemBlock implements IEnergizedItem, ISp
@Override
@Method(modid = "IC2API")
public int getMaxCharge(ItemStack itemStack)
public double getMaxCharge(ItemStack itemStack)
{
return 0;
}
@ -221,7 +221,7 @@ public class ItemBlockGenerator extends ItemBlock implements IEnergizedItem, ISp
@Override
@Method(modid = "IC2API")
public int getTransferLimit(ItemStack itemStack)
public double getTransferLimit(ItemStack itemStack)
{
return 0;
}

View file

@ -0,0 +1,10 @@
package mekanism.generators.common.tile;
import mekanism.api.reactor.IReactorBlock;
/**
* Created by ben on 10/07/14.
*/
public abstract class TileEntityReactorBlock implements IReactorBlock
{
}

View file

@ -0,0 +1,15 @@
package mekanism.generators.common.tile;
public class TileEntityReactorController extends TileEntityReactorBlock
{
@Override
public boolean isFrame()
{
return false;
}
public void radiateNeutrons(int neutrons)
{
}
}