From 795762df858a6288e8b9e176baa4c81b70d93efb Mon Sep 17 00:00:00 2001 From: Vexatos Date: Wed, 4 Oct 2017 20:12:16 +0200 Subject: [PATCH] Re-added IC2 integration. Hopefully it works. (cherry picked from commit 151ddecb2c305d6827c183d384690761272d5e16) --- build.gradle | 6 +- build.properties | 1 + .../scala/li/cil/oc/common/EventHandler.scala | 11 +- .../cil/oc/common/block/PowerConverter.scala | 3 + .../scala/li/cil/oc/common/item/Wrench.scala | 8 ++ .../oc/common/item/traits/Chargeable.scala | 11 ++ .../tileentity/traits/PowerAcceptor.scala | 3 +- .../power/IndustrialCraft2Experimental.scala | 96 +++++++++++++++++ .../scala/li/cil/oc/integration/Mods.scala | 3 + .../ic2/ConverterElectricItem.java | 27 +++++ .../cil/oc/integration/ic2/DriverEnergy.java | 61 +++++++++++ .../ic2/DriverEnergyConductor.java | 50 +++++++++ .../cil/oc/integration/ic2/DriverMassFab.java | 47 ++++++++ .../cil/oc/integration/ic2/DriverReactor.java | 67 ++++++++++++ .../ic2/DriverReactorRedstonePort.java | 102 ++++++++++++++++++ .../integration/ic2/ElectricItemManager.scala | 54 ++++++++++ .../ic2/EventHandlerIndustrialCraft2.scala | 80 ++++++++++++++ .../integration/ic2/ModIndustrialCraft2.scala | 31 ++++++ 18 files changed, 657 insertions(+), 4 deletions(-) create mode 100644 src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala create mode 100644 src/main/scala/li/cil/oc/integration/ic2/ConverterElectricItem.java create mode 100644 src/main/scala/li/cil/oc/integration/ic2/DriverEnergy.java create mode 100644 src/main/scala/li/cil/oc/integration/ic2/DriverEnergyConductor.java create mode 100644 src/main/scala/li/cil/oc/integration/ic2/DriverMassFab.java create mode 100644 src/main/scala/li/cil/oc/integration/ic2/DriverReactor.java create mode 100644 src/main/scala/li/cil/oc/integration/ic2/DriverReactorRedstonePort.java create mode 100644 src/main/scala/li/cil/oc/integration/ic2/ElectricItemManager.scala create mode 100644 src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala create mode 100644 src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala diff --git a/build.gradle b/build.gradle index 62e31173b..24ef7ee2f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,8 +16,8 @@ apply plugin: 'scala' apply plugin: 'net.minecraftforge.gradle.forge' apply plugin: 'maven-publish' -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 +sourceCompatibility = JavaVersion.VERSION_1_7 +targetCompatibility = JavaVersion.VERSION_1_7 file "build.properties" withReader { def prop = new Properties() @@ -78,6 +78,8 @@ dependencies { deobfCompile "mezz.jei:jei_${config.minecraft.version}:${config.jei.version}" deobfCompile "net.sengir.forestry:forestry_${config.minecraft.version}:${config.forestry.version}" + deobfCompile "net.industrial-craft:industrialcraft-2:${config.ic2.version}" + embedded files('libs/OpenComputers-JNLua.jar', 'libs/OpenComputers-LuaJ.jar') testCompile "org.mockito:mockito-all:1.10.19" diff --git a/build.properties b/build.properties index 2c4135ba6..b11d301a5 100644 --- a/build.properties +++ b/build.properties @@ -7,6 +7,7 @@ mod.group=li.cil.oc mod.version=1.7.0 forestry.version=5.3.1.38 +ic2.version=2.7.85-ex111 jei.version=4.2.11.251 mcmp.version=2.0.0_17 tis3d.version=1.1.1.37 diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala index 1351055d8..0448b83e0 100644 --- a/src/main/scala/li/cil/oc/common/EventHandler.scala +++ b/src/main/scala/li/cil/oc/common/EventHandler.scala @@ -26,7 +26,6 @@ import li.cil.oc.common.recipe.Recipes import li.cil.oc.common.tileentity.Robot import li.cil.oc.common.tileentity.traits.power import li.cil.oc.integration.Mods -import li.cil.oc.integration.util import li.cil.oc.server.component.Keyboard import li.cil.oc.server.machine.Callbacks import li.cil.oc.server.machine.Machine @@ -110,6 +109,16 @@ object EventHandler { } } + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + def scheduleIC2Add(tileEntity: power.IndustrialCraft2Experimental) { + if (SideTracker.isServer) pendingServer.synchronized { + pendingServer += (() => if (!tileEntity.addedToIC2PowerGrid && !tileEntity.isInvalid) { + MinecraftForge.EVENT_BUS.post(new ic2.api.energy.event.EnergyTileLoadEvent(tileEntity.asInstanceOf[ic2.api.energy.tile.IEnergyTile])) + tileEntity.addedToIC2PowerGrid = true + }) + } + } + @SubscribeEvent def onAttachCapabilities(event: AttachCapabilitiesEvent[TileEntity]): Unit = { event.getObject match { diff --git a/src/main/scala/li/cil/oc/common/block/PowerConverter.scala b/src/main/scala/li/cil/oc/common/block/PowerConverter.scala index 3ebe48fa2..982df72f7 100644 --- a/src/main/scala/li/cil/oc/common/block/PowerConverter.scala +++ b/src/main/scala/li/cil/oc/common/block/PowerConverter.scala @@ -28,6 +28,9 @@ class PowerConverter extends SimpleBlock with traits.PowerAcceptor { // if (Mods.Factorization.isAvailable) { // addRatio(tooltip, "Factorization", Settings.get.ratioFactorization) // } + if (Mods.IndustrialCraft2.isModAvailable) { + addRatio(tooltip, "IndustrialCraft2", Settings.get.ratioIndustrialCraft2) + } } private def addExtension(x: Double) = diff --git a/src/main/scala/li/cil/oc/common/item/Wrench.scala b/src/main/scala/li/cil/oc/common/item/Wrench.scala index 3878b5328..d2741a32e 100644 --- a/src/main/scala/li/cil/oc/common/item/Wrench.scala +++ b/src/main/scala/li/cil/oc/common/item/Wrench.scala @@ -1,6 +1,8 @@ package li.cil.oc.common.item import li.cil.oc.api +import li.cil.oc.common.asm.Injectable +import li.cil.oc.integration.Mods import net.minecraft.block.Block import net.minecraft.entity.player.EntityPlayer import net.minecraft.init.Blocks @@ -12,6 +14,9 @@ import net.minecraft.util.math.BlockPos import net.minecraft.world.IBlockAccess import net.minecraft.world.World +@Injectable.InterfaceList(Array( + new Injectable.Interface(value = "ic2.api.item.IBoxable", modid = Mods.IDs.IndustrialCraft2) +)) class Wrench extends traits.SimpleItem with api.internal.Wrench { setHarvestLevel("wrench", 1) setMaxStackSize(1) @@ -34,4 +39,7 @@ class Wrench extends traits.SimpleItem with api.internal.Wrench { if (!simulate) player.swingArm(EnumHand.MAIN_HAND) true } + + // IndustrialCraft 2 + def canBeStoredInToolbox(stack: ItemStack): Boolean = true } diff --git a/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala b/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala index 1f58aba45..d51aaf7f9 100644 --- a/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala +++ b/src/main/scala/li/cil/oc/common/item/traits/Chargeable.scala @@ -1,13 +1,24 @@ package li.cil.oc.common.item.traits +import ic2.api.item.IElectricItemManager import li.cil.oc.api +import li.cil.oc.common.asm.Injectable +import li.cil.oc.integration.Mods +import li.cil.oc.integration.ic2.ElectricItemManager import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.Optional // TODO Forge power capabilities. +@Injectable.InterfaceList(Array( + new Injectable.Interface(value = "ic2.api.item.ISpecialElectricItem", modid = Mods.IDs.IndustrialCraft2) +)) trait Chargeable extends api.driver.item.Chargeable { def maxCharge(stack: ItemStack): Double def getCharge(stack: ItemStack): Double def setCharge(stack: ItemStack, amount: Double): Unit + + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + def getManager(stack: ItemStack): IElectricItemManager = ElectricItemManager } diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala index 7a3d77581..68c1196db 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala @@ -1,4 +1,5 @@ package li.cil.oc.common.tileentity.traits trait PowerAcceptor - extends power.Common \ No newline at end of file + extends power.Common + with power.IndustrialCraft2Experimental diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala new file mode 100644 index 000000000..b1b7eecea --- /dev/null +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/power/IndustrialCraft2Experimental.scala @@ -0,0 +1,96 @@ +package li.cil.oc.common.tileentity.traits.power + +import ic2.api.energy.tile.IEnergyEmitter +import li.cil.oc.OpenComputers +import li.cil.oc.Settings +import li.cil.oc.common.EventHandler +import li.cil.oc.common.asm.Injectable +import li.cil.oc.common.tileentity.traits +import li.cil.oc.integration.Mods +import li.cil.oc.integration.util.Power +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.EnumFacing +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.fml.common.Optional +import net.minecraftforge.fml.common.eventhandler.Event + +@Injectable.Interface(value = "ic2.api.energy.tile.IEnergySink", modid = Mods.IDs.IndustrialCraft2) +trait IndustrialCraft2Experimental extends Common with IndustrialCraft2Common with traits.Tickable { + private var conversionBuffer = 0.0 + + private lazy val useIndustrialCraft2Power = isServer && Mods.IndustrialCraft2.isModAvailable + + // ----------------------------------------------------------------------- // + + override def updateEntity() { + super.updateEntity() + if (useIndustrialCraft2Power && getWorld.getTotalWorldTime % Settings.get.tickFrequency == 0) { + updateEnergy() + } + } + + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + private def updateEnergy() { + tryAllSides((demand, _) => { + val result = math.min(demand, conversionBuffer) + conversionBuffer -= result + result + }, Power.fromEU, Power.toEU) + } + + override def validate() { + super.validate() + if (useIndustrialCraft2Power && !addedToIC2PowerGrid) EventHandler.scheduleIC2Add(this) + } + + override def invalidate() { + super.invalidate() + if (useIndustrialCraft2Power && addedToIC2PowerGrid) removeFromIC2Grid() + } + + override def onChunkUnload() { + super.onChunkUnload() + if (useIndustrialCraft2Power && addedToIC2PowerGrid) removeFromIC2Grid() + } + + private def removeFromIC2Grid() { + try MinecraftForge.EVENT_BUS.post(Class.forName("ic2.api.energy.event.EnergyTileUnloadEvent").getConstructor(Class.forName("ic2.api.energy.tile.IEnergyTile")).newInstance(this).asInstanceOf[Event]) catch { + case t: Throwable => OpenComputers.log.warn("Error removing node from IC2 grid.", t) + } + addedToIC2PowerGrid = false + } + + // ----------------------------------------------------------------------- // + + override def readFromNBTForServer(nbt: NBTTagCompound) { + super.readFromNBTForServer(nbt) + conversionBuffer = nbt.getDouble(Settings.namespace + "ic2power") + } + + override def writeToNBTForServer(nbt: NBTTagCompound) { + super.writeToNBTForServer(nbt) + nbt.setDouble(Settings.namespace + "ic2power", conversionBuffer) + } + + // ----------------------------------------------------------------------- // + + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + def getSinkTier: Int = Int.MaxValue + + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + def acceptsEnergyFrom(emitter: IEnergyEmitter, direction: EnumFacing): Boolean = useIndustrialCraft2Power && canConnectPower(direction) + + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + def injectEnergy(directionFrom: EnumFacing, amount: Double, voltage: Double): Double = { + conversionBuffer += amount + 0.0 + } + + @Optional.Method(modid = Mods.IDs.IndustrialCraft2) + def getDemandedEnergy: Double = { + if (!useIndustrialCraft2Power) 0.0 + else if (conversionBuffer < energyThroughput * Settings.get.tickFrequency) + math.min(EnumFacing.VALUES.map(globalDemand).max, Power.toEU(energyThroughput)) + else 0 + } +} diff --git a/src/main/scala/li/cil/oc/integration/Mods.scala b/src/main/scala/li/cil/oc/integration/Mods.scala index 9fc691199..bfc9c727d 100644 --- a/src/main/scala/li/cil/oc/integration/Mods.scala +++ b/src/main/scala/li/cil/oc/integration/Mods.scala @@ -19,6 +19,7 @@ object Mods { def All: ArrayBuffer[ModBase] = knownMods.clone() val Forestry = new SimpleMod(IDs.Forestry, version = "@[5.2,)") + val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2) val Forge = new SimpleMod(IDs.Forge) val JustEnoughItems = new SimpleMod(IDs.JustEnoughItems) val Minecraft = new SimpleMod(IDs.Minecraft) @@ -29,6 +30,7 @@ object Mods { val Proxies = Array( integration.forestry.ModForestry, + integration.ic2.ModIndustrialCraft2, integration.minecraftforge.ModMinecraftForge, integration.tis3d.ModTIS3D, integration.minecraft.ModMinecraft, @@ -61,6 +63,7 @@ object Mods { object IDs { final val Forestry = "forestry" final val Forge = "forge" + final val IndustrialCraft2 = "ic2" final val JustEnoughItems = "jei" final val Minecraft = "minecraft" final val OpenComputers = "opencomputers" diff --git a/src/main/scala/li/cil/oc/integration/ic2/ConverterElectricItem.java b/src/main/scala/li/cil/oc/integration/ic2/ConverterElectricItem.java new file mode 100644 index 000000000..981a3faf6 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/ConverterElectricItem.java @@ -0,0 +1,27 @@ +package li.cil.oc.integration.ic2; + +import ic2.api.item.ElectricItem; +import ic2.api.item.IElectricItem; +import li.cil.oc.api.driver.Converter; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.util.Map; + +public class ConverterElectricItem implements Converter { + @Override + public void convert(final Object value, final Map output) { + if (value instanceof ItemStack) { + final ItemStack stack = (ItemStack) value; + final Item item = stack.getItem(); + if (item instanceof IElectricItem) { + final IElectricItem electricItem = (IElectricItem) item; + output.put("canProvideEnergy", electricItem.canProvideEnergy(stack)); + output.put("charge", ElectricItem.manager.getCharge(stack)); + output.put("maxCharge", electricItem.getMaxCharge(stack)); + output.put("tier", electricItem.getTier(stack)); + output.put("transferLimit", electricItem.getTransferLimit(stack)); + } + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/DriverEnergy.java b/src/main/scala/li/cil/oc/integration/ic2/DriverEnergy.java new file mode 100644 index 000000000..aa8cc52bc --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/DriverEnergy.java @@ -0,0 +1,61 @@ +package li.cil.oc.integration.ic2; + +import ic2.core.block.TileEntityBlock; +import ic2.core.block.comp.Energy; +import li.cil.oc.api.driver.DriverBlock; +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public final class DriverEnergy implements DriverBlock { + @Override + public boolean worksWith(final World world, final BlockPos pos, final EnumFacing side) { + final TileEntity tileEntity = world.getTileEntity(pos); + if (tileEntity instanceof TileEntityBlock) { + final TileEntityBlock tileEntityBlock = (TileEntityBlock) tileEntity; + return tileEntityBlock.hasComponent(Energy.class); + } + return false; + } + + @Override + public ManagedEnvironment createEnvironment(final World world, final BlockPos pos, final EnumFacing side) { + return new Environment((TileEntityBlock) world.getTileEntity(pos)); + } + + public static final class Environment extends ManagedTileEntityEnvironment { + public Environment(final TileEntityBlock tileEntity) { + super(tileEntity, "ic2_energy"); + } + + @Callback + public Object[] getCapacity(final Context context, final Arguments args) { + final Energy energy = tileEntity.getComponent(Energy.class); + return new Object[]{energy.getCapacity()}; + } + + @Callback + public Object[] getEnergy(final Context context, final Arguments args) { + final Energy energy = tileEntity.getComponent(Energy.class); + return new Object[]{energy.getEnergy()}; + } + + @Callback + public Object[] getSinkTier(final Context context, final Arguments args) { + final Energy energy = tileEntity.getComponent(Energy.class); + return new Object[]{energy.getSinkTier()}; + } + + @Callback + public Object[] getSourceTier(final Context context, final Arguments args) { + final Energy energy = tileEntity.getComponent(Energy.class); + return new Object[]{energy.getSourceTier()}; + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/DriverEnergyConductor.java b/src/main/scala/li/cil/oc/integration/ic2/DriverEnergyConductor.java new file mode 100644 index 000000000..8485265cb --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/DriverEnergyConductor.java @@ -0,0 +1,50 @@ +package li.cil.oc.integration.ic2; + +import ic2.api.energy.tile.IEnergyConductor; +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.api.prefab.DriverSidedTileEntity; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public final class DriverEnergyConductor extends DriverSidedTileEntity { + @Override + public Class getTileEntityClass() { + return IEnergyConductor.class; + } + + @Override + public ManagedEnvironment createEnvironment(final World world, final BlockPos pos, final EnumFacing side) { + return new Environment((IEnergyConductor) world.getTileEntity(pos)); + } + + public static final class Environment extends ManagedTileEntityEnvironment { + public Environment(final IEnergyConductor tileEntity) { + super(tileEntity, "energy_conductor"); + } + + @Callback + public Object[] getConductionLoss(final Context context, final Arguments args) { + return new Object[]{tileEntity.getConductionLoss()}; + } + + @Callback + public Object[] getConductorBreakdownEnergy(final Context context, final Arguments args) { + return new Object[]{tileEntity.getConductorBreakdownEnergy()}; + } + + @Callback + public Object[] getInsulationBreakdownEnergy(final Context context, final Arguments args) { + return new Object[]{tileEntity.getInsulationBreakdownEnergy()}; + } + + @Callback + public Object[] getInsulationEnergyAbsorption(final Context context, final Arguments args) { + return new Object[]{tileEntity.getInsulationEnergyAbsorption()}; + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/DriverMassFab.java b/src/main/scala/li/cil/oc/integration/ic2/DriverMassFab.java new file mode 100644 index 000000000..a32e3e45e --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/DriverMassFab.java @@ -0,0 +1,47 @@ +package li.cil.oc.integration.ic2; + +import ic2.core.block.comp.Energy; +import ic2.core.block.machine.tileentity.TileEntityMatter; +import li.cil.oc.api.driver.NamedBlock; +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import li.cil.oc.api.prefab.AbstractManagedEnvironment; +import li.cil.oc.api.prefab.DriverSidedTileEntity; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public final class DriverMassFab extends DriverSidedTileEntity { + @Override + public Class getTileEntityClass() { + return TileEntityMatter.class; + } + + @Override + public AbstractManagedEnvironment createEnvironment(final World world, final BlockPos pos, final EnumFacing side) { + return new Environment((TileEntityMatter) world.getTileEntity(pos)); + } + + public static final class Environment extends ManagedTileEntityEnvironment implements NamedBlock { + public Environment(final TileEntityMatter tileEntity) { + super(tileEntity, "mass_fab"); + } + + @Override + public String preferredName() { + return "mass_fab"; + } + + @Override + public int priority() { + return 0; + } + + @Callback + public Object[] getProgress(final Context context, final Arguments args) { + return new Object[]{Math.min(100 * tileEntity.getComponent(Energy.class).getFillRatio(), 100)}; + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/DriverReactor.java b/src/main/scala/li/cil/oc/integration/ic2/DriverReactor.java new file mode 100644 index 000000000..0d7231ea8 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/DriverReactor.java @@ -0,0 +1,67 @@ +package li.cil.oc.integration.ic2; + + +import ic2.api.reactor.IReactor; +import li.cil.oc.api.driver.NamedBlock; +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.api.prefab.DriverSidedTileEntity; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public final class DriverReactor extends DriverSidedTileEntity { + @Override + public Class getTileEntityClass() { + return IReactor.class; + } + + @Override + public ManagedEnvironment createEnvironment(final World world, final BlockPos pos, final EnumFacing side) { + return new Environment((IReactor) world.getTileEntity(pos)); + } + + public static final class Environment extends ManagedTileEntityEnvironment implements NamedBlock { + public Environment(final IReactor tileEntity) { + super(tileEntity, "reactor"); + } + + @Override + public String preferredName() { + return "reactor"; + } + + @Override + public int priority() { + return 0; + } + + @Callback(doc = "function():number -- Get the reactor's heat.") + public Object[] getHeat(final Context context, final Arguments args) { + return new Object[]{tileEntity.getHeat()}; + } + + @Callback(doc = "function():number -- Get the reactor's maximum heat before exploding.") + public Object[] getMaxHeat(final Context context, final Arguments args) { + return new Object[]{tileEntity.getMaxHeat()}; + } + + @Callback(doc = "function():number -- Get the reactor's energy output. Not multiplied with the base EU/t value.") + public Object[] getReactorEnergyOutput(final Context context, final Arguments args) { + return new Object[]{tileEntity.getReactorEnergyOutput()}; + } + + @Callback(doc = "function():number -- Get the reactor's base EU/t value.") + public Object[] getReactorEUOutput(final Context context, final Arguments args) { + return new Object[]{tileEntity.getReactorEUEnergyOutput()}; + } + + @Callback(doc = "function():boolean -- Get whether the reactor is active and supposed to produce energy.") + public Object[] producesEnergy(final Context context, final Arguments args) { + return new Object[]{tileEntity.produceEnergy()}; + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/DriverReactorRedstonePort.java b/src/main/scala/li/cil/oc/integration/ic2/DriverReactorRedstonePort.java new file mode 100644 index 000000000..103a7adec --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/DriverReactorRedstonePort.java @@ -0,0 +1,102 @@ +package li.cil.oc.integration.ic2; + +import ic2.api.reactor.IReactor; +import ic2.core.block.comp.FluidReactorLookup; +import ic2.core.block.reactor.tileentity.TileEntityReactorRedstonePort; +import li.cil.oc.api.driver.NamedBlock; +import li.cil.oc.api.machine.Arguments; +import li.cil.oc.api.machine.Callback; +import li.cil.oc.api.machine.Context; +import li.cil.oc.api.network.ManagedEnvironment; +import li.cil.oc.api.prefab.DriverSidedTileEntity; +import li.cil.oc.integration.ManagedTileEntityEnvironment; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; + +public final class DriverReactorRedstonePort extends DriverSidedTileEntity { + @Override + public Class getTileEntityClass() { + return TileEntityReactorRedstonePort.class; + } + + @Override + public ManagedEnvironment createEnvironment(final World world, final BlockPos pos, final EnumFacing side) { + return new Environment((TileEntityReactorRedstonePort) world.getTileEntity(pos)); + } + + public static final class Environment extends ManagedTileEntityEnvironment implements NamedBlock { + public Environment(final TileEntityReactorRedstonePort tileEntity) { + super(tileEntity, "reactor_redstone_port"); + } + + @Override + public String preferredName() { + return "reactor_redstone_port"; + } + + @Override + public int priority() { + return 0; + } + + private IReactor getReactor() { + final FluidReactorLookup lookup = tileEntity.getComponent(FluidReactorLookup.class); + if (lookup != null) { + return lookup.getReactor(); + } else { + return null; + } + } + + @Callback(doc = "function():number -- Get the reactor's heat.") + public Object[] getHeat(final Context context, final Arguments args) { + final IReactor reactor = getReactor(); + if (reactor != null) { + return new Object[]{reactor.getHeat()}; + } else { + return new Object[]{0}; + } + } + + @Callback(doc = "function():number -- Get the reactor's maximum heat before exploding.") + public Object[] getMaxHeat(final Context context, final Arguments args) { + final IReactor reactor = getReactor(); + if (reactor != null) { + return new Object[]{reactor.getMaxHeat()}; + } else { + return new Object[]{0}; + } + } + + @Callback(doc = "function():number -- Get the reactor's energy output. Not multiplied with the base EU/t value.") + public Object[] getReactorEnergyOutput(final Context context, final Arguments args) { + final IReactor reactor = getReactor(); + if (reactor != null) { + return new Object[]{reactor.getReactorEnergyOutput()}; + } else { + return new Object[]{0}; + } + } + + @Callback(doc = "function():number -- Get the reactor's base EU/t value.") + public Object[] getReactorEUOutput(final Context context, final Arguments args) { + final IReactor reactor = getReactor(); + if (reactor != null) { + return new Object[]{getReactor().getReactorEUEnergyOutput()}; + } else { + return new Object[]{false}; + } + } + + @Callback(doc = "function():boolean -- Get whether the reactor is active and supposed to produce energy.") + public Object[] producesEnergy(final Context context, final Arguments args) { + final IReactor reactor = getReactor(); + if (reactor != null) { + return new Object[]{reactor.produceEnergy()}; + } else { + return new Object[]{false}; + } + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/ElectricItemManager.scala b/src/main/scala/li/cil/oc/integration/ic2/ElectricItemManager.scala new file mode 100644 index 000000000..cb0f13511 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/ElectricItemManager.scala @@ -0,0 +1,54 @@ +package li.cil.oc.integration.ic2 + +import ic2.api.item.IElectricItem +import ic2.api.item.IElectricItemManager +import li.cil.oc.Settings +import li.cil.oc.api.driver.item.Chargeable +import li.cil.oc.integration.util.Power +import net.minecraft.entity.EntityLivingBase +import net.minecraft.item.ItemStack + +object ElectricItemManager extends IElectricItemManager { + override def getCharge(stack: ItemStack): Double = { + if (stack == null) 0 + else stack.getItem match { + case chargeable: Chargeable => + Power.toEU(Int.MaxValue + chargeable.charge(stack, -Int.MaxValue, true)) + case _ => 0 + } + } + + override def charge(stack: ItemStack, amount: Double, tier: Int, ignoreTransferLimit: Boolean, simulate: Boolean): Double = { + if (stack == null) 0 + else stack.getItem match { + case chargeable: Chargeable => + val limitedAmount = if (ignoreTransferLimit) math.min(Int.MaxValue, amount) else math.min(amount, Settings.get.chargeRateTablet) + limitedAmount - Power.toEU(chargeable.charge(stack, Power.fromEU(limitedAmount), simulate)) + case _ => 0 + } + } + + override def discharge(stack: ItemStack, amount: Double, tier: Int, ignoreTransferLimit: Boolean, externally: Boolean, simulate: Boolean): Double = { + 0.0 // TODO if we ever need it... + } + + override def chargeFromArmor(stack: ItemStack, entity: EntityLivingBase): Unit = {} + + override def canUse(stack: ItemStack, amount: Double): Boolean = getCharge(stack) >= amount + + override def use(stack: ItemStack, amount: Double, entity: EntityLivingBase): Boolean = canUse(stack, amount) && { + false // TODO if we ever need it... + } + + override def getToolTip(stack: ItemStack): String = "" + + override def getMaxCharge(stack: ItemStack): Double = Option(stack).map(_.getItem) match { + case Some(item: IElectricItem) => item.getMaxCharge(stack) + case _ => 0 + } + + override def getTier(stack: ItemStack): Int = Option(stack).map(_.getItem) match { + case Some(item: IElectricItem) => item.getTier(stack) + case _ => 0 + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala b/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala new file mode 100644 index 000000000..6aae5711b --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/EventHandlerIndustrialCraft2.scala @@ -0,0 +1,80 @@ +package li.cil.oc.integration.ic2 + +import ic2.api.item.ElectricItem +import ic2.api.item.IElectricItem +import ic2.api.item.ISpecialElectricItem +import ic2.core.item.tool.ItemToolWrench +import li.cil.oc.api.event.RobotUsedToolEvent +import li.cil.oc.integration.util.Power +import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack +import net.minecraft.util.math.BlockPos +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object EventHandlerIndustrialCraft2 { + @SubscribeEvent + def onRobotApplyDamageRate(e: RobotUsedToolEvent.ApplyDamageRate) { + val optManagerBefore = e.toolBeforeUse.getItem match { + case item: ISpecialElectricItem => Option(item.getManager(e.toolBeforeUse)) + case item: IElectricItem => Option(ElectricItem.manager) + case _ => None + } + val optManagerAfter = e.toolAfterUse.getItem match { + case item: ISpecialElectricItem => Option(item.getManager(e.toolAfterUse)) + case item: IElectricItem => Option(ElectricItem.manager) + case _ => None + } + (optManagerBefore, optManagerAfter) match { + case (Some(managerBefore), Some(managerAfter)) => + val damage = managerBefore.getCharge(e.toolBeforeUse) - managerAfter.getCharge(e.toolAfterUse) + if (damage > 0) { + val actualDamage = damage * e.getDamageRate + val repairedDamage = + if (e.agent.player.getRNG.nextDouble() > 0.5) + damage - math.floor(actualDamage).toInt + else + damage - math.ceil(actualDamage).toInt + managerAfter.charge(e.toolAfterUse, repairedDamage, Int.MaxValue, true, false) + } + case _ => + } + } + + def getDurability(stack: ItemStack): Double = { + stack.getItem match { + case item: ISpecialElectricItem => item.getManager(stack).getCharge(stack) / item.getManager(stack).getMaxCharge(stack) + case item: IElectricItem => ElectricItem.manager.getCharge(stack) / item.getMaxCharge(stack) + case _ => Double.NaN + } + } + + def useWrench(player: EntityPlayer, pos: BlockPos, changeDurability: Boolean): Boolean = { + player.getHeldItemMainhand.getItem match { + case wrench: ItemToolWrench => + if (changeDurability) { + wrench.damage(player.getHeldItemMainhand, 1, player) + true + } + else wrench.canTakeDamage(player.getHeldItemMainhand, 1) + case _ => false + } + } + + def isWrench(stack: ItemStack): Boolean = stack.getItem.isInstanceOf[ItemToolWrench] + + def canCharge(stack: ItemStack): Boolean = stack.getItem match { + case chargeable: IElectricItem => chargeable.getMaxCharge(stack) > 0 + case _ => false + } + + def charge(stack: ItemStack, amount: Double, simulate: Boolean): Double = { + (stack.getItem match { + case item: ISpecialElectricItem => Option(item.getManager(stack)) + case item: IElectricItem => Option(ElectricItem.manager) + case _ => None + }) match { + case Some(manager) => amount - Power.fromEU(manager.charge(stack, Power.toEU(amount), Int.MaxValue, true, false)) + case _ => amount + } + } +} diff --git a/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala b/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala new file mode 100644 index 000000000..e47c3fb47 --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/ic2/ModIndustrialCraft2.scala @@ -0,0 +1,31 @@ +package li.cil.oc.integration.ic2 + +import li.cil.oc.api +import li.cil.oc.api.Driver +import li.cil.oc.integration.ModProxy +import li.cil.oc.integration.Mods +import net.minecraftforge.common.MinecraftForge + +object ModIndustrialCraft2 extends ModProxy { + override def getMod = Mods.IndustrialCraft2 + + override def initialize() { + api.IMC.registerToolDurabilityProvider("li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.getDurability") + api.IMC.registerWrenchTool("li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.useWrench") + api.IMC.registerWrenchToolCheck("li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.isWrench") + api.IMC.registerItemCharge( + "IndustrialCraft2", + "li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.canCharge", + "li.cil.oc.integration.ic2.EventHandlerIndustrialCraft2.charge") + + MinecraftForge.EVENT_BUS.register(EventHandlerIndustrialCraft2) + + Driver.add(new DriverEnergyConductor) + Driver.add(new DriverEnergy) + Driver.add(new DriverMassFab) + Driver.add(new DriverReactor) + Driver.add(new DriverReactorRedstonePort) + + Driver.add(new ConverterElectricItem) + } +}