From 9640255442a748061d5419fc072200e65717c974 Mon Sep 17 00:00:00 2001 From: Prototik Date: Mon, 26 May 2014 16:41:30 +0800 Subject: [PATCH] Next impovements of MjAPI --- api/buildcraft/api/mj/BatteryObject.java | 7 + api/buildcraft/api/mj/IBatteryObject.java | 11 ++ api/buildcraft/api/mj/MjAPI.java | 144 +++++++++++++++----- api/buildcraft/api/mj/MjBattery.java | 2 +- api/buildcraft/api/mj/MjReconfigurator.java | 30 +++- api/buildcraft/api/mj/package-info.java | 11 ++ 6 files changed, 169 insertions(+), 36 deletions(-) create mode 100644 api/buildcraft/api/mj/package-info.java diff --git a/api/buildcraft/api/mj/BatteryObject.java b/api/buildcraft/api/mj/BatteryObject.java index 0077d824..f0dd5680 100755 --- a/api/buildcraft/api/mj/BatteryObject.java +++ b/api/buildcraft/api/mj/BatteryObject.java @@ -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(); diff --git a/api/buildcraft/api/mj/IBatteryObject.java b/api/buildcraft/api/mj/IBatteryObject.java index d93997b3..6bbd222d 100644 --- a/api/buildcraft/api/mj/IBatteryObject.java +++ b/api/buildcraft/api/mj/IBatteryObject.java @@ -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); } diff --git a/api/buildcraft/api/mj/MjAPI.java b/api/buildcraft/api/mj/MjAPI.java index f4ca5854..2e9c8a74 100755 --- a/api/buildcraft/api/mj/MjAPI.java +++ b/api/buildcraft/api/mj/MjAPI.java @@ -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 mjBatteryFields = new HashMap(); - private static Map> mjBatteryKinds = new HashMap>(); + private static Map> mjBatteryKinds = new HashMap>(); private static final BatteryField invalidBatteryField = new BatteryField(); private static final MjReconfigurator reconfigurator = new MjReconfigurator(); private static final Map mjBatteryCache = new WeakHashMap(); + /** * 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 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 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:
+ * + * MjAPI.reconfigure().maxCapacity(battery, 15000); + * + * @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); } - } diff --git a/api/buildcraft/api/mj/MjBattery.java b/api/buildcraft/api/mj/MjBattery.java index 9d981eca..20ed8c71 100755 --- a/api/buildcraft/api/mj/MjBattery.java +++ b/api/buildcraft/api/mj/MjBattery.java @@ -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; } \ No newline at end of file diff --git a/api/buildcraft/api/mj/MjReconfigurator.java b/api/buildcraft/api/mj/MjReconfigurator.java index 50c7ef8f..e5e81dcc 100644 --- a/api/buildcraft/api/mj/MjReconfigurator.java +++ b/api/buildcraft/api/mj/MjReconfigurator.java @@ -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 newSides = new ArrayList(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) { diff --git a/api/buildcraft/api/mj/package-info.java b/api/buildcraft/api/mj/package-info.java new file mode 100644 index 00000000..7ca45ce8 --- /dev/null +++ b/api/buildcraft/api/mj/package-info.java @@ -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;