diff --git a/assets/opencomputers/textures/blocks/charger.png b/assets/opencomputers/textures/blocks/charger.png index 913e2512b..0b8bf00a0 100644 Binary files a/assets/opencomputers/textures/blocks/charger.png and b/assets/opencomputers/textures/blocks/charger.png differ diff --git a/assets/opencomputers/textures/blocks/charger_on.png b/assets/opencomputers/textures/blocks/charger_on.png new file mode 100644 index 000000000..43969ffee Binary files /dev/null and b/assets/opencomputers/textures/blocks/charger_on.png differ diff --git a/buildcraft/api/tools/IToolWrench.java b/buildcraft/api/tools/IToolWrench.java new file mode 100644 index 000000000..bd0c3c595 --- /dev/null +++ b/buildcraft/api/tools/IToolWrench.java @@ -0,0 +1,32 @@ +package buildcraft.api.tools; + +import net.minecraft.entity.player.EntityPlayer; + +/*** + * Implement this interface on subclasses of Item to have that item work as a wrench for buildcraft + */ +public interface IToolWrench { + + /*** + * Called to ensure that the wrench can be used. To get the ItemStack that is used, check player.inventory.getCurrentItem() + * + * @param player + * - The player doing the wrenching + * @param x + * ,y,z - The coordinates for the block being wrenched + * + * @return true if wrenching is allowed, false if not + */ + public boolean canWrench(EntityPlayer player, int x, int y, int z); + + /*** + * Callback after the wrench has been used. This can be used to decrease durability or for other purposes. To get the ItemStack that was used, check + * player.inventory.getCurrentItem() + * + * @param player + * - The player doing the wrenching + * @param x + * ,y,z - The coordinates of the block being wrenched + */ + public void wrenchUsed(EntityPlayer player, int x, int y, int z); +} diff --git a/li/cil/oc/client/PacketHandler.scala b/li/cil/oc/client/PacketHandler.scala index 0923afa78..44eab9c83 100644 --- a/li/cil/oc/client/PacketHandler.scala +++ b/li/cil/oc/client/PacketHandler.scala @@ -64,7 +64,9 @@ class PacketHandler extends CommonPacketHandler { def onChargerState(p: PacketParser) = p.readTileEntity[Charger]() match { - case Some(t) => t.chargeSpeed = p.readDouble() + case Some(t) => + t.chargeSpeed = p.readDouble() + t.world.markBlockForRenderUpdate(t.x, t.y, t.z) case _ => // Invalid packet. } diff --git a/li/cil/oc/common/block/Case.scala b/li/cil/oc/common/block/Case.scala index 9f1e6e3f3..0043d4039 100644 --- a/li/cil/oc/common/block/Case.scala +++ b/li/cil/oc/common/block/Case.scala @@ -3,6 +3,7 @@ package li.cil.oc.common.block import java.util import li.cil.oc.common.{GuiType, tileentity} import li.cil.oc.util.Tooltip +import li.cil.oc.util.mods.BuildCraft import li.cil.oc.{OpenComputers, Settings} import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.entity.player.EntityPlayer @@ -72,7 +73,7 @@ abstract class Case(val parent: SimpleDelegator) extends RedstoneAware with Simp override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = { - if (!player.isSneaking) { + if (!player.isSneaking && !BuildCraft.holdsApplicableWrench(player, x, y, z)) { if (!world.isRemote) { player.openGui(OpenComputers, GuiType.Case.id, world, x, y, z) } diff --git a/li/cil/oc/common/block/Charger.scala b/li/cil/oc/common/block/Charger.scala index 705c8f5db..00590390e 100644 --- a/li/cil/oc/common/block/Charger.scala +++ b/li/cil/oc/common/block/Charger.scala @@ -1,9 +1,12 @@ package li.cil.oc.common.block +import cpw.mods.fml.relauncher.{Side, SideOnly} import java.util import li.cil.oc.Settings import li.cil.oc.common.tileentity +import li.cil.oc.server.PacketSender import li.cil.oc.util.Tooltip +import li.cil.oc.util.mods.BuildCraft import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack @@ -15,6 +18,7 @@ class Charger(val parent: SimpleDelegator) extends RedstoneAware with SimpleDele val unlocalizedName = "Charger" private val icons = Array.fill[Icon](6)(null) + private val iconsCharging = Array.fill[Icon](6)(null) override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) { tooltip.addAll(Tooltip.get(unlocalizedName)) @@ -22,6 +26,13 @@ class Charger(val parent: SimpleDelegator) extends RedstoneAware with SimpleDele override def icon(side: ForgeDirection) = Some(icons(side.ordinal())) + @SideOnly(Side.CLIENT) + override def icon(world: IBlockAccess, x: Int, y: Int, z: Int, worldSide: ForgeDirection, localSide: ForgeDirection) = + world.getBlockTileEntity(x, y, z) match { + case charger: tileentity.Charger if charger.chargeSpeed > 0 => Some(iconsCharging(localSide.ordinal())) + case _ => Some(icons(localSide.ordinal())) + } + override def registerIcons(iconRegister: IconRegister) = { icons(ForgeDirection.DOWN.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":generic_top") icons(ForgeDirection.UP.ordinal) = icons(ForgeDirection.DOWN.ordinal) @@ -30,12 +41,33 @@ class Charger(val parent: SimpleDelegator) extends RedstoneAware with SimpleDele icons(ForgeDirection.SOUTH.ordinal) = icons(ForgeDirection.NORTH.ordinal) icons(ForgeDirection.WEST.ordinal) = icons(ForgeDirection.NORTH.ordinal) icons(ForgeDirection.EAST.ordinal) = icons(ForgeDirection.NORTH.ordinal) + + iconsCharging(ForgeDirection.DOWN.ordinal) = icons(ForgeDirection.DOWN.ordinal) + iconsCharging(ForgeDirection.UP.ordinal) = icons(ForgeDirection.UP.ordinal) + + iconsCharging(ForgeDirection.NORTH.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":charger_on") + iconsCharging(ForgeDirection.SOUTH.ordinal) = iconsCharging(ForgeDirection.NORTH.ordinal) + iconsCharging(ForgeDirection.WEST.ordinal) = iconsCharging(ForgeDirection.NORTH.ordinal) + iconsCharging(ForgeDirection.EAST.ordinal) = iconsCharging(ForgeDirection.NORTH.ordinal) } override def createTileEntity(world: World) = Some(new tileentity.Charger()) override def canConnectToRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true + override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = + world.getBlockTileEntity(x, y, z) match { + case charger: tileentity.Charger if BuildCraft.holdsApplicableWrench(player, x, y, z) => + if (!world.isRemote) { + charger.invertSignal = !charger.invertSignal + charger.chargeSpeed = 1.0 - charger.chargeSpeed + PacketSender.sendChargerState(charger) + BuildCraft.wrenchUsed(player, x, y, z) + } + true + case _ => super.rightClick(world, x, y, z, player, side, hitX, hitY, hitZ) + } + override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, blockId: Int) { world.getBlockTileEntity(x, y, z) match { case charger: tileentity.Charger => charger.onNeighborChanged() diff --git a/li/cil/oc/common/block/Screen.scala b/li/cil/oc/common/block/Screen.scala index a7b5c5fa8..e998b4d94 100644 --- a/li/cil/oc/common/block/Screen.scala +++ b/li/cil/oc/common/block/Screen.scala @@ -15,6 +15,7 @@ import net.minecraft.world.IBlockAccess import net.minecraft.world.World import net.minecraftforge.common.ForgeDirection import scala.Array +import li.cil.oc.util.mods.BuildCraft abstract class Screen(val parent: SimpleDelegator) extends SimpleDelegate { val unlocalizedName = "Screen" + tier @@ -284,7 +285,7 @@ abstract class Screen(val parent: SimpleDelegator) extends SimpleDelegate { override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = - if (!player.isSneaking) { + if (!player.isSneaking && !BuildCraft.holdsApplicableWrench(player, x, y, z)) { world.getBlockTileEntity(x, y, z) match { case screen: tileentity.Screen if screen.hasKeyboard => // Yep, this GUI is actually purely client side. We could skip this diff --git a/li/cil/oc/common/tileentity/Charger.scala b/li/cil/oc/common/tileentity/Charger.scala index 8246708c9..1fc1f4c72 100644 --- a/li/cil/oc/common/tileentity/Charger.scala +++ b/li/cil/oc/common/tileentity/Charger.scala @@ -17,6 +17,8 @@ class Charger extends Environment with RedstoneAware with Analyzable { var chargeSpeed = 0.0 + var invertSignal = false + def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = null override def updateEntity() { @@ -76,7 +78,10 @@ class Charger extends Environment with RedstoneAware with Analyzable { override protected def onRedstoneInputChanged(side: ForgeDirection) { super.onRedstoneInputChanged(side) - chargeSpeed = math.max(0, math.min(ForgeDirection.VALID_DIRECTIONS.map(input).max, 15) / 15.0) + val signal = math.max(0, math.min(15, ForgeDirection.VALID_DIRECTIONS.map(input).max)) + + if (invertSignal) chargeSpeed = (15 - signal) / 15.0 + else chargeSpeed = signal / 15.0 if (isServer) { ServerPacketSender.sendChargerState(this) } diff --git a/li/cil/oc/common/tileentity/PowerConverter.scala b/li/cil/oc/common/tileentity/PowerConverter.scala index a43896803..dbcf5cb08 100644 --- a/li/cil/oc/common/tileentity/PowerConverter.scala +++ b/li/cil/oc/common/tileentity/PowerConverter.scala @@ -2,7 +2,7 @@ package li.cil.oc.common.tileentity import buildcraft.api.power.{PowerHandler, IPowerReceptor} import cofh.api.energy.IEnergyHandler -import cpw.mods.fml.common.{Loader, Optional} +import cpw.mods.fml.common.{ModAPIManager, Loader, Optional} import ic2.api.energy.event.{EnergyTileLoadEvent, EnergyTileUnloadEvent} import ic2.api.energy.tile.IEnergySink import li.cil.oc.api.network._ @@ -16,7 +16,7 @@ import universalelectricity.core.electricity.ElectricityPack @Optional.InterfaceList(Array( new Optional.Interface(iface = "ic2.api.energy.tile.IEnergySink", modid = "IC2"), - new Optional.Interface(iface = "buildcraft.api.power.IPowerReceptor", modid = "BuildCraft|Energy"), + new Optional.Interface(iface = "buildcraft.api.power.IPowerReceptor", modid = "BuildCraftAPI|power"), new Optional.Interface(iface = "cofh.api.energy.IEnergyHandler", modid = "ThermalExpansion") )) class PowerConverter extends Environment with Analyzable with IEnergySink with IPowerReceptor with IElectrical with IEnergyHandler { @@ -26,7 +26,7 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I private lazy val isIndustrialCraftAvailable = Loader.isModLoaded("IC2") - private lazy val isBuildCraftAvailable = Loader.isModLoaded("BuildCraft|Energy") + private lazy val isBuildCraftAvailable = ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|power") private def demand = if (Settings.get.ignorePower) 0.0 else node.globalBufferSize - node.globalBuffer @@ -66,14 +66,14 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I override def readFromNBT(nbt: NBTTagCompound) { super.readFromNBT(nbt) - if (Loader.isModLoaded("BuildCraft|Energy")) { + if (ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|power")) { getPowerProvider.readFromNBT(nbt.getCompoundTag(Settings.namespace + "bc")) } } override def writeToNBT(nbt: NBTTagCompound) { super.writeToNBT(nbt) - if (Loader.isModLoaded("BuildCraft|Energy")) { + if (ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|power")) { nbt.setNewCompoundTag(Settings.namespace + "bc", getPowerProvider.writeToNBT) } } @@ -133,7 +133,7 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I private var powerHandler: Option[AnyRef] = None - @Optional.Method(modid = "BuildCraft|Energy") + @Optional.Method(modid = "BuildCraftAPI|power") def getPowerProvider = { if (node != null && powerHandler.isEmpty) { val handler = new PowerHandler(this, PowerHandler.Type.MACHINE) @@ -147,16 +147,16 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I else null } - @Optional.Method(modid = "BuildCraft|Energy") + @Optional.Method(modid = "BuildCraftAPI|power") def getPowerReceiver(side: ForgeDirection) = if (node != null) getPowerProvider.getPowerReceiver else null - @Optional.Method(modid = "BuildCraft|Energy") + @Optional.Method(modid = "BuildCraftAPI|power") def getWorld = worldObj - @Optional.Method(modid = "BuildCraft|Energy") + @Optional.Method(modid = "BuildCraftAPI|power") def doWork(workProvider: PowerHandler) {} // ----------------------------------------------------------------------- // diff --git a/li/cil/oc/util/mods/BuildCraft.scala b/li/cil/oc/util/mods/BuildCraft.scala new file mode 100644 index 000000000..6584d4825 --- /dev/null +++ b/li/cil/oc/util/mods/BuildCraft.scala @@ -0,0 +1,25 @@ +package li.cil.oc.util.mods + +import buildcraft.api.tools.IToolWrench +import cpw.mods.fml.common.ModAPIManager +import net.minecraft.entity.player.EntityPlayer + +object BuildCraft { + def holdsApplicableWrench(player: EntityPlayer, x: Int, y: Int, z: Int) = + ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|core") && + player.getCurrentEquippedItem != null && + (player.getCurrentEquippedItem.getItem match { + case wrench: IToolWrench => wrench.canWrench(player, x, y, z) + case _ => false + }) + + def wrenchUsed(player: EntityPlayer, x: Int, y: Int, z: Int) = + ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|core") && + player.getCurrentEquippedItem != null && + (player.getCurrentEquippedItem.getItem match { + case wrench: IToolWrench if wrench.canWrench(player, x, y, z) => + wrench.wrenchUsed(player, x, y, z) + true + case _ => false + }) +}