Merge branch '6.1.x' of github.com:BuildCraft/BuildCraft into 6.1.x

This commit is contained in:
SpaceToad 2014-05-29 11:30:18 +02:00
commit e204fa275d
6 changed files with 169 additions and 36 deletions

View file

@ -150,6 +150,13 @@ public class BatteryObject implements IBatteryIOObject, MjReconfigurator.IConfig
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();

View file

@ -8,6 +8,8 @@
*/
package buildcraft.api.mj;
import java.lang.reflect.Field;
public interface IBatteryObject {
/**
* @return Current energy requirement for keeping machine state
@ -63,4 +65,13 @@ public interface IBatteryObject {
* @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

@ -35,10 +35,11 @@ import gnu.trove.map.hash.TIntObjectHashMap;
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 BatteryObject>> mjBatteryKinds = new HashMap<String, Class<? extends BatteryObject>>();
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
*/
@ -46,41 +47,36 @@ public final class MjAPI {
}
/**
* Returns the default battery related to the object given in parameter. For
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
* @see #getMjBattery(Object, String, ForgeDirection)
*/
public static IBatteryObject getMjBattery(Object o) {
return getMjBattery(o, DEFAULT_POWER_FRAMEWORK, ForgeDirection.UNKNOWN);
return getMjBattery(o, null, null);
}
/**
* Returns the battery related to the object given in parameter. For
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
* @see #getMjBattery(Object, String, ForgeDirection)
*/
public static IBatteryObject getMjBattery(Object o, String kind) {
return getMjBattery(o, kind, ForgeDirection.UNKNOWN);
return getMjBattery(o, kind, null);
}
/**
* Returns the battery related to the object given in parameter. For
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
* @see #getMjBattery(Object, String, ForgeDirection)
*/
public static IBatteryObject getMjBattery(Object o, ForgeDirection side) {
return getMjBattery(o, DEFAULT_POWER_FRAMEWORK, side);
return getMjBattery(o, null, side);
}
/**
* Returns the battery related to the object given in parameter. For
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
* Returns the battery related to the object given in parameter.
*/
public static IBatteryObject getMjBattery(Object o, String kind, ForgeDirection side) {
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) {
@ -104,6 +100,9 @@ public final class MjAPI {
}
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();
}
@ -112,38 +111,37 @@ public final class MjAPI {
return battery;
}
private static boolean isCacheable(IBatteryObject battery) {
return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).isCacheable();
}
/**
* 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 {
BatteryObject obj = mjBatteryKinds.get(kind).newInstance();
obj.obj = o;
obj.energyStored = f.field;
obj.batteryData = f.battery;
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 {
@ -156,10 +154,17 @@ public final class MjAPI {
}
}
/**
* @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()];
@ -175,27 +180,54 @@ public final class MjAPI {
return Arrays.copyOfRange(result, 0, id);
}
public static void registerMJBatteryKind(String kind, Class<? extends BatteryObject> clas) {
/**
* 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, clas);
mjBatteryKinds.put(kind, clazz);
} else {
BCLog.logger.log(Level.WARNING,
"energy kind \"" + kind + "\" already registered with " + clas.getCanonicalName());
"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();
@ -205,10 +237,25 @@ public final class MjAPI {
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;
@ -224,12 +271,22 @@ public final class MjAPI {
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);
@ -247,10 +304,22 @@ public final class MjAPI {
}
}
/**
* 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
}
@ -266,6 +335,14 @@ public final class MjAPI {
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();
}
@ -356,7 +433,6 @@ public final class MjAPI {
}
static {
mjBatteryKinds.put(MjAPI.DEFAULT_POWER_FRAMEWORK, BatteryObject.class);
registerMJBatteryKind(DEFAULT_POWER_FRAMEWORK, BatteryObject.class);
}
}

View file

@ -80,7 +80,7 @@ public @interface MjBattery {
* @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()}
* for tile with {@link MjAPI#resetBatteriesCache(IBatteryObject)}
*/
boolean cacheable() default true;
}

View file

@ -9,11 +9,18 @@
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;
@ -68,6 +75,9 @@ public class MjReconfigurator {
}
}
/**
* Helper interface which should implement all configurable batteries.
*/
public interface IConfigurableBatteryObject extends IBatteryObject {
MjBattery getMjBattery();
@ -129,16 +139,34 @@ public class MjReconfigurator {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) {
battery.kind = kind;
MjAPI.resetBatteriesCache(batteryObject);
}
}
public void sides(IBatteryObject batteryObject, ForgeDirection[] sides) {
/**
* 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) {

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;