diff --git a/src/main/java/li/cil/oc/OpenComponents.java b/src/main/java/li/cil/oc/OpenComponents.java index ba34f9fe0..33a95c8f8 100644 --- a/src/main/java/li/cil/oc/OpenComponents.java +++ b/src/main/java/li/cil/oc/OpenComponents.java @@ -3,8 +3,10 @@ package li.cil.oc; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.event.FMLInitializationEvent; -import li.cil.oc.driver.buildcraft.ComponentsBuildCraft; -import li.cil.oc.driver.vanilla.ComponentsVanilla; +import li.cil.oc.driver.IDriverBundle; +import li.cil.oc.driver.buildcraft.BundleBuildCraft; +import li.cil.oc.driver.enderstorage.BundleEnderStorage; +import li.cil.oc.driver.vanilla.BundleVanilla; @Mod(modid = "OpenComputers|Components", name = "OpenComponents", version = "1.0.0", dependencies = "required-after:OpenComputers@[1.2.0,)") public class OpenComponents { @@ -12,10 +14,15 @@ public class OpenComponents { public static OpenComponents instance; @Mod.EventHandler - public static void init(final FMLInitializationEvent e) { - ComponentsVanilla.register(); - if (Loader.isModLoaded("BuildCraft|Core")) { - ComponentsBuildCraft.register(); + public void init(final FMLInitializationEvent e) { + register(new BundleVanilla()); + register(new BundleBuildCraft()); + register(new BundleEnderStorage()); + } + + private void register(IDriverBundle bundle) { + if (bundle.getModId() == null || bundle.getModId().isEmpty() || Loader.isModLoaded(bundle.getModId())) { + bundle.initialize(); } } } diff --git a/src/main/java/li/cil/oc/driver/IDriverBundle.java b/src/main/java/li/cil/oc/driver/IDriverBundle.java new file mode 100644 index 000000000..30df0c2e8 --- /dev/null +++ b/src/main/java/li/cil/oc/driver/IDriverBundle.java @@ -0,0 +1,7 @@ +package li.cil.oc.driver; + +public interface IDriverBundle { + String getModId(); + + void initialize(); +} diff --git a/src/main/java/li/cil/oc/driver/ManagedTileEntityEnvironment.java b/src/main/java/li/cil/oc/driver/ManagedTileEntityEnvironment.java index 8d273cf58..ed802a90e 100644 --- a/src/main/java/li/cil/oc/driver/ManagedTileEntityEnvironment.java +++ b/src/main/java/li/cil/oc/driver/ManagedTileEntityEnvironment.java @@ -3,7 +3,6 @@ package li.cil.oc.driver; import li.cil.oc.api.Network; import li.cil.oc.api.network.Visibility; import li.cil.oc.api.prefab.ManagedEnvironment; -import net.minecraft.tileentity.TileEntity; public class ManagedTileEntityEnvironment extends ManagedEnvironment { protected final T tileEntity; diff --git a/src/main/java/li/cil/oc/driver/buildcraft/BundleBuildCraft.java b/src/main/java/li/cil/oc/driver/buildcraft/BundleBuildCraft.java new file mode 100644 index 000000000..29500af35 --- /dev/null +++ b/src/main/java/li/cil/oc/driver/buildcraft/BundleBuildCraft.java @@ -0,0 +1,17 @@ +package li.cil.oc.driver.buildcraft; + +import li.cil.oc.api.Driver; +import li.cil.oc.driver.IDriverBundle; + +public final class BundleBuildCraft implements IDriverBundle { + @Override + public String getModId() { + return "BuildCraft|Core"; + } + + @Override + public void initialize() { + Driver.add(new DriverPipe()); + Driver.add(new DriverPowerReceptor()); + } +} diff --git a/src/main/java/li/cil/oc/driver/buildcraft/ComponentsBuildCraft.java b/src/main/java/li/cil/oc/driver/buildcraft/ComponentsBuildCraft.java deleted file mode 100644 index 6406879f7..000000000 --- a/src/main/java/li/cil/oc/driver/buildcraft/ComponentsBuildCraft.java +++ /dev/null @@ -1,13 +0,0 @@ -package li.cil.oc.driver.buildcraft; - -import li.cil.oc.api.Driver; - -public final class ComponentsBuildCraft { - private ComponentsBuildCraft() { - } - - public static void register() { - Driver.add(new DriverPipe()); - Driver.add(new DriverPowerReceptor()); - } -} diff --git a/src/main/java/li/cil/oc/driver/enderstorage/BundleEnderStorage.java b/src/main/java/li/cil/oc/driver/enderstorage/BundleEnderStorage.java new file mode 100644 index 000000000..132e3de55 --- /dev/null +++ b/src/main/java/li/cil/oc/driver/enderstorage/BundleEnderStorage.java @@ -0,0 +1,16 @@ +package li.cil.oc.driver.enderstorage; + +import li.cil.oc.driver.IDriverBundle; +import li.cil.oc.api.Driver; + +public final class BundleEnderStorage implements IDriverBundle { + @Override + public String getModId() { + return "EnderStorage"; + } + + @Override + public void initialize() { + Driver.add(new DriverFrequencyOwner()); + } +} diff --git a/src/main/java/li/cil/oc/driver/enderstorage/DriverFrequencyOwner.java b/src/main/java/li/cil/oc/driver/enderstorage/DriverFrequencyOwner.java new file mode 100644 index 000000000..e54d50bf7 --- /dev/null +++ b/src/main/java/li/cil/oc/driver/enderstorage/DriverFrequencyOwner.java @@ -0,0 +1,57 @@ +package li.cil.oc.driver.enderstorage; + +import li.cil.oc.api.network.Arguments; +import li.cil.oc.api.network.Callback; +import li.cil.oc.api.network.Context; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.driver.ManagedTileEntityEnvironment; +import li.cil.oc.driver.TileEntityDriver; +import li.cil.oc.util.Reflection; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +public class DriverFrequencyOwner extends TileEntityDriver { + // See https://bitbucket.org/ChickenBones/enderstorage/ + private static final Class TileFrequencyOwner = Reflection.getClass("codechicken.enderstorage.common.TileFrequencyOwner"); + + @Override + public Class getFilterClass() { + return TileFrequencyOwner; + } + + @Override + public ManagedEnvironment createEnvironment(final World world, final int x, final int y, final int z) { + return new Environment(world.getBlockTileEntity(x, y, z)); + } + + public static final class Environment extends ManagedTileEntityEnvironment { + public Environment(final TileEntity tileEntity) { + super(tileEntity, "ender_storage"); + } + + @Callback + public Object[] getFrequency(final Context context, final Arguments args) { + return new Object[]{Reflection.get(tileEntity, "freq")}; + } + + @Callback + public Object[] setFrequency(final Context context, final Arguments args) { + final int frequency = args.checkInteger(0); + if ((frequency & 0xFFF) != frequency) { + throw new IllegalArgumentException("invalid frequency"); + } + final String owner = (String) Reflection.get(tileEntity, "owner"); + if (owner == null || owner.isEmpty() || "global".equals(owner)) { + Reflection.invoke(tileEntity, "setFreq", frequency); + } else { + return new Object[]{false, "cannot change frequency of owned storage"}; + } + return null; + } + + @Callback + public Object[] getOwner(final Context context, final Arguments args) { + return new Object[]{Reflection.get(tileEntity, "owner")}; + } + } +} diff --git a/src/main/java/li/cil/oc/driver/vanilla/ComponentsVanilla.java b/src/main/java/li/cil/oc/driver/vanilla/BundleVanilla.java similarity index 69% rename from src/main/java/li/cil/oc/driver/vanilla/ComponentsVanilla.java rename to src/main/java/li/cil/oc/driver/vanilla/BundleVanilla.java index aefa36e4f..cfced2915 100644 --- a/src/main/java/li/cil/oc/driver/vanilla/ComponentsVanilla.java +++ b/src/main/java/li/cil/oc/driver/vanilla/BundleVanilla.java @@ -1,12 +1,16 @@ package li.cil.oc.driver.vanilla; +import li.cil.oc.driver.IDriverBundle; import li.cil.oc.api.Driver; -public final class ComponentsVanilla { - private ComponentsVanilla() { +public final class BundleVanilla implements IDriverBundle { + @Override + public String getModId() { + return null; } - public static void register() { + @Override + public void initialize() { Driver.add(new DriverBeacon()); Driver.add(new DriverBrewingStand()); Driver.add(new DriverComparator()); diff --git a/src/main/java/li/cil/oc/util/Reflection.java b/src/main/java/li/cil/oc/util/Reflection.java new file mode 100644 index 000000000..7941dd9f7 --- /dev/null +++ b/src/main/java/li/cil/oc/util/Reflection.java @@ -0,0 +1,71 @@ +package li.cil.oc.util; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public final class Reflection { + private Reflection() { + } + + public static Class getClass(final String name) { + try { + return Class.forName(name); + } catch (final ClassNotFoundException ignored) { + return null; + } + } + + public static Object get(final Object instance, final String fieldName) { + try { + final Field field = instance.getClass().getField(fieldName); + return field.get(instance); + } catch (final IllegalAccessException ignored) { + return null; + } catch (final NoSuchFieldException ignored) { + return null; + } + } + + public static void set(final Object instance, final String fieldName, final Object value) { + try { + final Field field = instance.getClass().getField(fieldName); + field.set(instance, value); + } catch (final IllegalAccessException ignored) { + } catch (final NoSuchFieldException ignored) { + } + } + + public static Object invoke(final Object instance, final String methodName, final Object... args) { + try { + outer: + for (Method method : instance.getClass().getMethods()) { + if (method.getName().equals(methodName) && method.getParameterTypes().length == args.length) { + Class[] argTypes = method.getParameterTypes(); + for (int i = 0; i < argTypes.length; ++i) { + Class have = argTypes[i]; + Class given = args[i].getClass(); + // Fail if not assignable and not assignable to primitive. + if (!have.isAssignableFrom(given) && (!have.isPrimitive() + || (!(byte.class.equals(have) && Byte.class.equals(given)) + && !(short.class.equals(have) && Short.class.equals(given)) + && !(int.class.equals(have) && Integer.class.equals(given)) + && !(long.class.equals(have) && Long.class.equals(given)) + && !(float.class.equals(have) && Float.class.equals(given)) + && !(double.class.equals(have) && Double.class.equals(given)) + && !(boolean.class.equals(have) && Boolean.class.equals(given)) + && !(char.class.equals(have) && Character.class.equals(given))))) { + continue outer; + } + } + return method.invoke(instance, args); + } + } + return null; + } catch (InvocationTargetException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } + } +}