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(); return batteryData.kind();
} }
@Override
public void init(Object object, Field storedField, MjBattery battery) {
this.obj = object;
this.energyStored = storedField;
this.batteryData = battery;
}
@Override @Override
public double maxSendedPerCycle() { public double maxSendedPerCycle() {
return batteryData.maxSendedPerCycle(); return batteryData.maxSendedPerCycle();

View file

@ -8,6 +8,8 @@
*/ */
package buildcraft.api.mj; package buildcraft.api.mj;
import java.lang.reflect.Field;
public interface IBatteryObject { public interface IBatteryObject {
/** /**
* @return Current energy requirement for keeping machine state * @return Current energy requirement for keeping machine state
@ -63,4 +65,13 @@ public interface IBatteryObject {
* @return kind of this energy battery * @return kind of this energy battery
*/ */
String kind(); 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 final class MjAPI {
public static final String DEFAULT_POWER_FRAMEWORK = "buildcraft.kinesis"; public static final String DEFAULT_POWER_FRAMEWORK = "buildcraft.kinesis";
private static Map<BatteryHolder, BatteryField> mjBatteryFields = new HashMap<BatteryHolder, BatteryField>(); 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 BatteryField invalidBatteryField = new BatteryField();
private static final MjReconfigurator reconfigurator = new MjReconfigurator(); private static final MjReconfigurator reconfigurator = new MjReconfigurator();
private static final Map<Object, BatteryCache> mjBatteryCache = new WeakHashMap<Object, BatteryCache>(); private static final Map<Object, BatteryCache> mjBatteryCache = new WeakHashMap<Object, BatteryCache>();
/** /**
* Deactivate constructor * Deactivate constructor
*/ */
@ -46,41 +47,36 @@ public final class MjAPI {
} }
/** /**
* Returns the default battery related to the object given in parameter. For * @see #getMjBattery(Object, String, ForgeDirection)
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
*/ */
public static IBatteryObject getMjBattery(Object o) { 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 * @see #getMjBattery(Object, String, ForgeDirection)
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
*/ */
public static IBatteryObject getMjBattery(Object o, String kind) { 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 * @see #getMjBattery(Object, String, ForgeDirection)
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
*/ */
public static IBatteryObject getMjBattery(Object o, ForgeDirection side) { 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 * Returns the battery related to the object given in parameter.
* performance optimization, it's good to cache this object in the providing
* power framework if possible.
*/ */
public static IBatteryObject getMjBattery(Object o, String kind, ForgeDirection side) { public static IBatteryObject getMjBattery(Object o, String kindRaw, ForgeDirection sideRaw) {
if (o == null) { if (o == null) {
return null; return null;
} }
String kind = kindRaw == null ? DEFAULT_POWER_FRAMEWORK : kindRaw;
ForgeDirection side = sideRaw == null ? ForgeDirection.UNKNOWN : sideRaw;
IBatteryObject battery; IBatteryObject battery;
BatteryCache cache = mjBatteryCache.get(o); BatteryCache cache = mjBatteryCache.get(o);
if (cache == null) { if (cache == null) {
@ -104,6 +100,9 @@ public final class MjAPI {
} }
if (battery == null && o instanceof IPowerReceptor) { if (battery == null && o instanceof IPowerReceptor) {
PowerHandler.PowerReceiver receiver = ((IPowerReceptor) o).getPowerReceiver(side); PowerHandler.PowerReceiver receiver = ((IPowerReceptor) o).getPowerReceiver(side);
if (receiver == null && side != ForgeDirection.UNKNOWN) {
receiver = ((IPowerReceptor) o).getPowerReceiver(ForgeDirection.UNKNOWN);
}
if (receiver != null) { if (receiver != null) {
battery = receiver.getMjBattery(); battery = receiver.getMjBattery();
} }
@ -112,38 +111,37 @@ public final class MjAPI {
return battery; 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) { public static IBatteryObject createBattery(Object o, String kind, ForgeDirection side) {
if (o == null) { if (o == null) {
return null; return null;
} }
BatteryField f = getMjBatteryField(o.getClass(), kind, side); BatteryField f = getMjBatteryField(o.getClass(), kind, side);
if (f == null && side != ForgeDirection.UNKNOWN) { if (f == null && side != ForgeDirection.UNKNOWN) {
f = getMjBatteryField(o.getClass(), kind, ForgeDirection.UNKNOWN); f = getMjBatteryField(o.getClass(), kind, ForgeDirection.UNKNOWN);
} }
if (f == null) { if (f == null) {
return null; return null;
} else if (!mjBatteryKinds.containsKey(kind)) { } else if (!mjBatteryKinds.containsKey(kind)) {
return null; return null;
} else if (f.kind == BatteryKind.Value) { } else if (f.kind == BatteryKind.Value) {
try { try {
BatteryObject obj = mjBatteryKinds.get(kind).newInstance(); IBatteryObject obj = mjBatteryKinds.get(kind).newInstance();
obj.obj = o; obj.init(o, f.field, f.battery);
obj.energyStored = f.field;
obj.batteryData = f.battery;
return obj; return obj;
} catch (InstantiationException e) { } catch (InstantiationException e) {
BCLog.logger.log(Level.WARNING, "can't instantiate class for energy kind \"" + kind + "\""); BCLog.logger.log(Level.WARNING, "can't instantiate class for energy kind \"" + kind + "\"");
return null; return null;
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
BCLog.logger.log(Level.WARNING, "can't instantiate class for energy kind \"" + kind + "\""); BCLog.logger.log(Level.WARNING, "can't instantiate class for energy kind \"" + kind + "\"");
return null; return null;
} }
} else { } else {
@ -156,10 +154,17 @@ public final class MjAPI {
} }
} }
/**
* @return All non-sided batteries for passed object
*/
public static IBatteryObject[] getAllMjBatteries(Object o) { public static IBatteryObject[] getAllMjBatteries(Object o) {
return getAllMjBatteries(o, ForgeDirection.UNKNOWN); 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) { public static IBatteryObject[] getAllMjBatteries(Object o, ForgeDirection direction) {
IBatteryObject[] result = new IBatteryObject[mjBatteryFields.size()]; IBatteryObject[] result = new IBatteryObject[mjBatteryFields.size()];
@ -175,27 +180,54 @@ public final class MjAPI {
return Arrays.copyOfRange(result, 0, id); 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)) { if (!mjBatteryKinds.containsKey(kind)) {
mjBatteryKinds.put(kind, clas); mjBatteryKinds.put(kind, clazz);
} else { } else {
BCLog.logger.log(Level.WARNING, 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) { public static boolean canReceive(IBatteryObject battery) {
return battery != null && (!(battery instanceof IBatteryIOObject) || ((IBatteryIOObject) battery).canReceive()); return battery != null && (!(battery instanceof IBatteryIOObject) || ((IBatteryIOObject) battery).canReceive());
} }
/**
* @see IOMode#canSend
*/
public static boolean canSend(IBatteryObject battery) { public static boolean canSend(IBatteryObject battery) {
return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).canSend(); return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).canSend();
} }
/**
* @see IOMode#active
*/
public static boolean isActive(IBatteryObject battery) { public static boolean isActive(IBatteryObject battery) {
return battery != null && battery instanceof IBatteryIOObject && ((IBatteryIOObject) battery).isActive(); 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) { public static double getIOLimit(IBatteryObject batteryObject, IOMode mode) {
if (mode == IOMode.Receive && canReceive(batteryObject)) { if (mode == IOMode.Receive && canReceive(batteryObject)) {
return batteryObject.maxReceivedPerCycle(); return batteryObject.maxReceivedPerCycle();
@ -205,10 +237,25 @@ public final class MjAPI {
return 0; return 0;
} }
/**
* Obtain battery parameters reconfigurator.
* Usage:<br />
* <code>
* MjAPI.reconfigure().maxCapacity(battery, 15000);
* </code>
* @return Reconfigurator instance
*/
public static MjReconfigurator reconfigure() { public static MjReconfigurator reconfigure() {
return reconfigurator; 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) { public static double transferEnergy(IBatteryObject fromBattery, IBatteryObject toBattery, double mj) {
if (!canSend(fromBattery) || !canReceive(toBattery)) { if (!canSend(fromBattery) || !canReceive(toBattery)) {
return 0; return 0;
@ -224,12 +271,22 @@ public final class MjAPI {
return 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) { public static double transferEnergy(IBatteryObject fromBattery, IBatteryObject toBattery) {
return transferEnergy(fromBattery, toBattery, Math.min( return transferEnergy(fromBattery, toBattery, Math.min(
getIOLimit(fromBattery, IOMode.Send), getIOLimit(fromBattery, IOMode.Send),
getIOLimit(toBattery, IOMode.Receive))); 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) { public static void updateEntity(TileEntity tile) {
for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) { for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
IBatteryObject batteryObject = getMjBattery(tile, direction); 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) { public static void resetBatteriesCache(TileEntity tile) {
mjBatteryCache.remove(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 { private enum BatteryKind {
Value, Container Value, Container
} }
@ -266,6 +335,14 @@ public final class MjAPI {
cache.put(hash(kind, side), 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) { private int hash(String kind, ForgeDirection side) {
return kind.hashCode() * 31 + side.hashCode(); return kind.hashCode() * 31 + side.hashCode();
} }
@ -356,7 +433,6 @@ public final class MjAPI {
} }
static { 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 * @return Ability to cache this battery instance for performance reasons. Usual
* not required to modify it for every battery, you can dynamicaly reconfigure * not required to modify it for every battery, you can dynamicaly reconfigure
* your batteries with {@link MjAPI#reconfigure()} and reset cache * 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; boolean cacheable() default true;
} }

View file

@ -9,11 +9,18 @@
package buildcraft.api.mj; package buildcraft.api.mj;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.core.BCLog; import buildcraft.api.core.BCLog;
/**
* Reconfiguration helper.
* Allow to change battery parameters in runtime.
*/
public class MjReconfigurator { public class MjReconfigurator {
private static final class ConfigurableMjBattery implements MjBattery { private static final class ConfigurableMjBattery implements MjBattery {
double maxCapacity, maxReceivedPerCycle, maxSendedPerCycle, minimumConsumption; 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 { public interface IConfigurableBatteryObject extends IBatteryObject {
MjBattery getMjBattery(); MjBattery getMjBattery();
@ -129,16 +139,34 @@ public class MjReconfigurator {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject); ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) { if (battery != null) {
battery.kind = kind; 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); ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) { if (battery != null) {
battery.sides = sides; 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) { public void mode(IBatteryObject batteryObject, IOMode mode) {
ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject); ConfigurableMjBattery battery = obtainConfigurableBattery(batteryObject);
if (battery != null) { 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;