chargers now indicate whether they're on or off by showing a different texture; ability to toggle the way chargers interpret signals using wrenches (inverse: on when no signal, off when max signal); checking if player holds a wrench when activating screens and computer cases; using BuildCraft API entry to check for availability instead of BuildCraft|Energy, to allow working with BC compatible systems even if BC is not available

This commit is contained in:
Florian Nücke 2013-12-16 17:39:09 +01:00
parent 5a617f5ab6
commit 8c14b0f637
10 changed files with 111 additions and 13 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 761 B

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

View File

@ -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);
}

View File

@ -64,7 +64,9 @@ class PacketHandler extends CommonPacketHandler {
def onChargerState(p: PacketParser) = def onChargerState(p: PacketParser) =
p.readTileEntity[Charger]() match { 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. case _ => // Invalid packet.
} }

View File

@ -3,6 +3,7 @@ package li.cil.oc.common.block
import java.util import java.util
import li.cil.oc.common.{GuiType, tileentity} import li.cil.oc.common.{GuiType, tileentity}
import li.cil.oc.util.Tooltip import li.cil.oc.util.Tooltip
import li.cil.oc.util.mods.BuildCraft
import li.cil.oc.{OpenComputers, Settings} import li.cil.oc.{OpenComputers, Settings}
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer 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, override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = { side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
if (!player.isSneaking) { if (!player.isSneaking && !BuildCraft.holdsApplicableWrench(player, x, y, z)) {
if (!world.isRemote) { if (!world.isRemote) {
player.openGui(OpenComputers, GuiType.Case.id, world, x, y, z) player.openGui(OpenComputers, GuiType.Case.id, world, x, y, z)
} }

View File

@ -1,9 +1,12 @@
package li.cil.oc.common.block package li.cil.oc.common.block
import cpw.mods.fml.relauncher.{Side, SideOnly}
import java.util import java.util
import li.cil.oc.Settings import li.cil.oc.Settings
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.server.PacketSender
import li.cil.oc.util.Tooltip import li.cil.oc.util.Tooltip
import li.cil.oc.util.mods.BuildCraft
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
@ -15,6 +18,7 @@ class Charger(val parent: SimpleDelegator) extends RedstoneAware with SimpleDele
val unlocalizedName = "Charger" val unlocalizedName = "Charger"
private val icons = Array.fill[Icon](6)(null) 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) { override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
tooltip.addAll(Tooltip.get(unlocalizedName)) 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())) 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) = { override def registerIcons(iconRegister: IconRegister) = {
icons(ForgeDirection.DOWN.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":generic_top") icons(ForgeDirection.DOWN.ordinal) = iconRegister.registerIcon(Settings.resourceDomain + ":generic_top")
icons(ForgeDirection.UP.ordinal) = icons(ForgeDirection.DOWN.ordinal) 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.SOUTH.ordinal) = icons(ForgeDirection.NORTH.ordinal)
icons(ForgeDirection.WEST.ordinal) = icons(ForgeDirection.NORTH.ordinal) icons(ForgeDirection.WEST.ordinal) = icons(ForgeDirection.NORTH.ordinal)
icons(ForgeDirection.EAST.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 createTileEntity(world: World) = Some(new tileentity.Charger())
override def canConnectToRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true 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) { override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, blockId: Int) {
world.getBlockTileEntity(x, y, z) match { world.getBlockTileEntity(x, y, z) match {
case charger: tileentity.Charger => charger.onNeighborChanged() case charger: tileentity.Charger => charger.onNeighborChanged()

View File

@ -15,6 +15,7 @@ import net.minecraft.world.IBlockAccess
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import scala.Array import scala.Array
import li.cil.oc.util.mods.BuildCraft
abstract class Screen(val parent: SimpleDelegator) extends SimpleDelegate { abstract class Screen(val parent: SimpleDelegator) extends SimpleDelegate {
val unlocalizedName = "Screen" + tier 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, override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = 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 { world.getBlockTileEntity(x, y, z) match {
case screen: tileentity.Screen if screen.hasKeyboard => case screen: tileentity.Screen if screen.hasKeyboard =>
// Yep, this GUI is actually purely client side. We could skip this // Yep, this GUI is actually purely client side. We could skip this

View File

@ -17,6 +17,8 @@ class Charger extends Environment with RedstoneAware with Analyzable {
var chargeSpeed = 0.0 var chargeSpeed = 0.0
var invertSignal = false
def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = null def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = null
override def updateEntity() { override def updateEntity() {
@ -76,7 +78,10 @@ class Charger extends Environment with RedstoneAware with Analyzable {
override protected def onRedstoneInputChanged(side: ForgeDirection) { override protected def onRedstoneInputChanged(side: ForgeDirection) {
super.onRedstoneInputChanged(side) 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) { if (isServer) {
ServerPacketSender.sendChargerState(this) ServerPacketSender.sendChargerState(this)
} }

View File

@ -2,7 +2,7 @@ package li.cil.oc.common.tileentity
import buildcraft.api.power.{PowerHandler, IPowerReceptor} import buildcraft.api.power.{PowerHandler, IPowerReceptor}
import cofh.api.energy.IEnergyHandler 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.event.{EnergyTileLoadEvent, EnergyTileUnloadEvent}
import ic2.api.energy.tile.IEnergySink import ic2.api.energy.tile.IEnergySink
import li.cil.oc.api.network._ import li.cil.oc.api.network._
@ -16,7 +16,7 @@ import universalelectricity.core.electricity.ElectricityPack
@Optional.InterfaceList(Array( @Optional.InterfaceList(Array(
new Optional.Interface(iface = "ic2.api.energy.tile.IEnergySink", modid = "IC2"), 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") new Optional.Interface(iface = "cofh.api.energy.IEnergyHandler", modid = "ThermalExpansion")
)) ))
class PowerConverter extends Environment with Analyzable with IEnergySink with IPowerReceptor with IElectrical with IEnergyHandler { 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 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 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) { override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt) super.readFromNBT(nbt)
if (Loader.isModLoaded("BuildCraft|Energy")) { if (ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|power")) {
getPowerProvider.readFromNBT(nbt.getCompoundTag(Settings.namespace + "bc")) getPowerProvider.readFromNBT(nbt.getCompoundTag(Settings.namespace + "bc"))
} }
} }
override def writeToNBT(nbt: NBTTagCompound) { override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt) super.writeToNBT(nbt)
if (Loader.isModLoaded("BuildCraft|Energy")) { if (ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|power")) {
nbt.setNewCompoundTag(Settings.namespace + "bc", getPowerProvider.writeToNBT) 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 private var powerHandler: Option[AnyRef] = None
@Optional.Method(modid = "BuildCraft|Energy") @Optional.Method(modid = "BuildCraftAPI|power")
def getPowerProvider = { def getPowerProvider = {
if (node != null && powerHandler.isEmpty) { if (node != null && powerHandler.isEmpty) {
val handler = new PowerHandler(this, PowerHandler.Type.MACHINE) val handler = new PowerHandler(this, PowerHandler.Type.MACHINE)
@ -147,16 +147,16 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I
else null else null
} }
@Optional.Method(modid = "BuildCraft|Energy") @Optional.Method(modid = "BuildCraftAPI|power")
def getPowerReceiver(side: ForgeDirection) = def getPowerReceiver(side: ForgeDirection) =
if (node != null) if (node != null)
getPowerProvider.getPowerReceiver getPowerProvider.getPowerReceiver
else null else null
@Optional.Method(modid = "BuildCraft|Energy") @Optional.Method(modid = "BuildCraftAPI|power")
def getWorld = worldObj def getWorld = worldObj
@Optional.Method(modid = "BuildCraft|Energy") @Optional.Method(modid = "BuildCraftAPI|power")
def doWork(workProvider: PowerHandler) {} def doWork(workProvider: PowerHandler) {}
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -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
})
}