added 'drop' signal that is triggered when a mouse button is released after a previous drag signal (and only then!), closes #173

cleaned up power traits a little
This commit is contained in:
Florian Nücke 2014-03-24 20:55:59 +01:00
parent 75f661696f
commit 231f78c674
11 changed files with 270 additions and 207 deletions

View File

@ -109,6 +109,24 @@ object PacketSender {
pb.sendToServer() pb.sendToServer()
} }
def sendMouseUp(b: component.Buffer, x: Int, y: Int, button: Int) {
val pb = new PacketBuilder(PacketType.MouseUp)
b.owner match {
case t: TextBuffer if t.tier > 0 =>
pb.writeTileEntity(t)
case t: component.Terminal =>
pb.writeTileEntity(t.rack)
pb.writeInt(t.number)
case _ => return
}
pb.writeInt(x)
pb.writeInt(y)
pb.writeByte(button.toByte)
pb.sendToServer()
}
def sendMultiPlace() { def sendMultiPlace() {
val pb = new PacketBuilder(PacketType.MultiPartPlace) val pb = new PacketBuilder(PacketType.MultiPartPlace)
pb.sendToServer() pb.sendToServer()

View File

@ -11,6 +11,8 @@ import org.lwjgl.opengl.GL11
class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val hasPower: () => Boolean) extends Buffer { class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val hasPower: () => Boolean) extends Buffer {
private val bufferMargin = BufferRenderer.margin + BufferRenderer.innerMargin private val bufferMargin = BufferRenderer.margin + BufferRenderer.innerMargin
private var didDrag = false
private var x, y = 0 private var x, y = 0
private var mx, my = 0 private var mx, my = 0
@ -48,9 +50,21 @@ class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val has
} }
} }
protected override def mouseMovedOrUp(mouseX: Int, mouseY: Int, which: Int) { protected override def mouseMovedOrUp(mouseX: Int, mouseY: Int, button: Int) {
super.mouseMovedOrUp(mouseX, mouseY, which) super.mouseMovedOrUp(mouseX, mouseY, button)
if (which == 0) { if (button >= 0) {
if (didDrag) {
val bx = ((mouseX - x - bufferMargin) / scale / MonospaceFontRenderer.fontWidth).toInt + 1
val by = ((mouseY - y - bufferMargin) / scale / MonospaceFontRenderer.fontHeight).toInt + 1
val (bw, bh) = buffer.resolution
if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
PacketSender.sendMouseUp(buffer, bx, by, button)
}
else {
PacketSender.sendMouseUp(buffer, -1, -1, button)
}
}
didDrag = false
mx = 0 mx = 0
my = 0 my = 0
} }
@ -63,6 +77,7 @@ class Screen(val buffer: common.component.Buffer, val hasMouse: Boolean, val has
if (bx > 0 && by > 0 && bx <= bw && by <= bh) { if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
if (bx != mx || by != my) { if (bx != mx || by != my) {
PacketSender.sendMouseClick(buffer, bx, by, mx > 0 && my > 0, button) PacketSender.sendMouseClick(buffer, bx, by, mx > 0 && my > 0, button)
didDrag = mx > 0 && my > 0
mx = bx mx = bx
my = by my = by
} }

View File

@ -38,6 +38,7 @@ object PacketType extends Enumeration {
Clipboard, Clipboard,
MouseClickOrDrag, MouseClickOrDrag,
MouseScroll, MouseScroll,
MouseUp,
MultiPartPlace, MultiPartPlace,
RobotStateRequest, RobotStateRequest,
ServerSide, ServerSide,

View File

@ -1,9 +0,0 @@
package li.cil.oc.common.tileentity.traits
import ic2.api.energy.tile.IEnergySink
import cpw.mods.fml.common.Optional
@Optional.Interface(iface = "ic2.api.energy.tile.IEnergySink", modid = "IC2")
trait IC2PowerGridAware extends IEnergySink {
var addedToPowerGrid = false
}

View File

@ -1,194 +1,7 @@
package li.cil.oc.common.tileentity.traits package li.cil.oc.common.tileentity.traits
import buildcraft.api.power.{PowerHandler, IPowerReceptor} trait PowerAcceptor
import cofh.api.energy.IEnergyHandler extends power.UniversalElectricity
import cpw.mods.fml.common.{ModAPIManager, Loader, Optional} with power.BuildCraft
import cpw.mods.fml.relauncher.{Side, SideOnly} with power.IndustrialCraft2
import li.cil.oc.api.network.Connector with power.ThermalExpansion
import li.cil.oc.server.TickHandler
import li.cil.oc.Settings
import net.minecraftforge.common.ForgeDirection
import universalelectricity.api.energy.{IEnergyContainer, IEnergyInterface}
@Optional.InterfaceList(Array(
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 = "universalelectricity.api.energy.IEnergyInterface", modid = "UniversalElectricity"),
new Optional.Interface(iface = "universalelectricity.api.energy.IEnergyContainer", modid = "UniversalElectricity")
))
trait PowerAcceptor extends TileEntity with IPowerReceptor with IC2PowerGridAware with IEnergyHandler with IEnergyInterface with IEnergyContainer {
@SideOnly(Side.CLIENT)
protected def hasConnector(side: ForgeDirection) = false
protected def connector(side: ForgeDirection): Option[Connector] = None
// ----------------------------------------------------------------------- //
private lazy val isIndustrialCraftAvailable = Loader.isModLoaded("IC2")
private lazy val isBuildCraftAvailable = ModAPIManager.INSTANCE.hasAPI("BuildCraftAPI|power")
// ----------------------------------------------------------------------- //
override def updateEntity() {
super.updateEntity()
if (isServer && !Settings.get.ignorePower) {
if (isBuildCraftAvailable && world.getWorldTime % Settings.get.tickFrequency == 0) {
for (side <- ForgeDirection.VALID_DIRECTIONS) connector(side) match {
case Some(node) =>
val demand = node.globalBufferSize - node.globalBuffer
if (demand > 1) {
node.changeBuffer(getPowerProvider.useEnergy(1, demand.toFloat, true))
}
case _ =>
}
}
if (isIndustrialCraftAvailable) {
loadIC2()
}
}
}
override def invalidate() {
super.invalidate()
if (isIndustrialCraftAvailable) {
unloadIC2()
}
}
override def onChunkUnload() {
super.onChunkUnload()
if (isIndustrialCraftAvailable) {
unloadIC2()
}
}
// ----------------------------------------------------------------------- //
// BuildCraft
private var powerHandler: Option[AnyRef] = None
@Optional.Method(modid = "BuildCraftAPI|power")
def getPowerProvider = {
if (powerHandler.isEmpty) {
val handler = new PowerHandler(this, PowerHandler.Type.MACHINE)
if (handler != null) {
handler.configure(1, 320, Float.MaxValue, 640)
handler.configurePowerPerdition(0, 0)
powerHandler = Some(handler)
}
}
if (powerHandler.isDefined) powerHandler.get.asInstanceOf[PowerHandler]
else null
}
@Optional.Method(modid = "BuildCraftAPI|power")
def getPowerReceiver(side: ForgeDirection) =
if (!Settings.get.ignorePower && (if (isClient) hasConnector(side) else connector(side).isDefined))
getPowerProvider.getPowerReceiver
else null
// Don't strip, also defined by AbstractBusAware trait.
def getWorld = worldObj
@Optional.Method(modid = "BuildCraftAPI|power")
def doWork(workProvider: PowerHandler) {}
// ----------------------------------------------------------------------- //
// IndustrialCraft2
@Optional.Method(modid = "IC2")
def loadIC2() {
if (!addedToPowerGrid) TickHandler.scheduleIC2Add(this)
}
@Optional.Method(modid = "IC2")
def unloadIC2() {
if (addedToPowerGrid) TickHandler.scheduleIC2Remove(this)
}
@Optional.Method(modid = "IC2")
def getMaxSafeInput = Integer.MAX_VALUE
@Optional.Method(modid = "IC2")
def acceptsEnergyFrom(emitter: net.minecraft.tileentity.TileEntity, direction: ForgeDirection) = canConnect(direction, null)
@Optional.Method(modid = "IC2")
def demandedEnergyUnits = {
if (Settings.get.ignorePower || isClient) 0
else {
var maxDemand = 0.0
for (side <- ForgeDirection.VALID_DIRECTIONS) connector(side) match {
case Some(node) =>
maxDemand = math.max(maxDemand, node.globalBufferSize - node.globalBuffer)
case _ =>
}
maxDemand * Settings.ratioBC / Settings.ratioIC2
}
}
@Optional.Method(modid = "IC2")
def injectEnergyUnits(directionFrom: ForgeDirection, amount: Double) =
amount - onReceiveEnergy(directionFrom, (amount * Settings.ratioIC2).toLong, doReceive = true) / Settings.ratioIC2
// ----------------------------------------------------------------------- //
// Thermal Expansion
@Optional.Method(modid = "ThermalExpansion")
def receiveEnergy(from: ForgeDirection, maxReceive: Int, simulate: Boolean) =
(onReceiveEnergy(from, (maxReceive * Settings.ratioTE).toLong, !simulate) / Settings.ratioTE).toInt
@Optional.Method(modid = "ThermalExpansion")
def extractEnergy(from: ForgeDirection, maxExtract: Int, simulate: Boolean) =
(onExtractEnergy(from, (maxExtract * Settings.ratioTE).toLong, !simulate) / Settings.ratioTE).toInt
@Optional.Method(modid = "ThermalExpansion")
def canInterface(from: ForgeDirection) = canConnect(from, this)
@Optional.Method(modid = "ThermalExpansion")
def getEnergyStored(from: ForgeDirection) = (getEnergy(from) / Settings.ratioTE).toInt
@Optional.Method(modid = "ThermalExpansion")
def getMaxEnergyStored(from: ForgeDirection) = (getEnergyCapacity(from) / Settings.ratioTE).toInt
// ----------------------------------------------------------------------- //
// Universal Electricity
override def canConnect(direction: ForgeDirection, source: AnyRef) =
!Settings.get.ignorePower && direction != null && direction != ForgeDirection.UNKNOWN &&
(if (isClient) hasConnector(direction) else connector(direction).isDefined)
override def onReceiveEnergy(from: ForgeDirection, receive: Long, doReceive: Boolean) =
if (isClient || Settings.get.ignorePower) 0
else connector(from) match {
case Some(node) =>
val energy = receive / Settings.ratioBC
if (doReceive) {
val surplus = node.changeBuffer(energy)
(receive - surplus * Settings.ratioBC).toLong
}
else {
val space = node.globalBufferSize - node.globalBuffer
math.min(receive, space * Settings.ratioBC).toLong
}
case _ => 0
}
override def onExtractEnergy(from: ForgeDirection, extract: Long, doExtract: Boolean) = 0
override def setEnergy(from: ForgeDirection, energy: Long) {}
override def getEnergy(from: ForgeDirection) =
if (isClient) 0
else connector(from) match {
case Some(node) => (node.globalBuffer * Settings.ratioBC).toLong
case _ => 0
}
override def getEnergyCapacity(from: ForgeDirection) =
if (isClient) 0
else connector(from) match {
case Some(node) => (node.globalBufferSize * Settings.ratioBC).toLong
case _ => 0
}
}

View File

@ -0,0 +1,58 @@
package li.cil.oc.common.tileentity.traits.power
import buildcraft.api.power.{PowerHandler, IPowerReceptor}
import cpw.mods.fml.common.Optional
import net.minecraftforge.common.ForgeDirection
import li.cil.oc.Settings
@Optional.Interface(iface = "buildcraft.api.power.IPowerReceptor", modid = "BuildCraftAPI|power")
trait BuildCraft extends UniversalElectricity with IPowerReceptor {
private var powerHandler: Option[AnyRef] = None
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "BuildCraftAPI|power")
override def updateEntity() {
super.updateEntity()
if (isServer && !Settings.get.ignorePower) {
if (world.getWorldTime % Settings.get.tickFrequency == 0) {
for (side <- ForgeDirection.VALID_DIRECTIONS) connector(side) match {
case Some(node) =>
val demand = node.globalBufferSize - node.globalBuffer
if (demand > 1) {
node.changeBuffer(getPowerProvider.useEnergy(1, demand.toFloat, true))
}
case _ =>
}
}
}
}
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "BuildCraftAPI|power")
def getPowerProvider = {
if (powerHandler.isEmpty) {
val handler = new PowerHandler(this, PowerHandler.Type.MACHINE)
if (handler != null) {
handler.configure(1, 320, Float.MaxValue, 640)
handler.configurePowerPerdition(0, 0)
powerHandler = Some(handler)
}
}
if (powerHandler.isDefined) powerHandler.get.asInstanceOf[PowerHandler]
else null
}
@Optional.Method(modid = "BuildCraftAPI|power")
def getPowerReceiver(side: ForgeDirection) =
if (!Settings.get.ignorePower && (if (isClient) hasConnector(side) else connector(side).isDefined))
getPowerProvider.getPowerReceiver
else null
// Don't strip, also defined by AbstractBusAware trait.
def getWorld = getWorldObj
@Optional.Method(modid = "BuildCraftAPI|power")
def doWork(workProvider: PowerHandler) {}
}

View File

@ -0,0 +1,58 @@
package li.cil.oc.common.tileentity.traits.power
import cpw.mods.fml.common.Optional
import ic2.api.energy.tile.IEnergySink
import li.cil.oc.server.TickHandler
import net.minecraftforge.common.ForgeDirection
import li.cil.oc.Settings
@Optional.Interface(iface = "ic2.api.energy.tile.IEnergySink", modid = "IC2")
trait IndustrialCraft2 extends UniversalElectricity with IEnergySink {
var addedToPowerGrid = false
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "IC2")
override def validate() {
super.validate()
if (!addedToPowerGrid) TickHandler.scheduleIC2Add(this)
}
@Optional.Method(modid = "IC2")
override def invalidate() {
super.invalidate()
if (addedToPowerGrid) TickHandler.scheduleIC2Remove(this)
}
@Optional.Method(modid = "IC2")
override def onChunkUnload() {
super.onChunkUnload()
if (addedToPowerGrid) TickHandler.scheduleIC2Remove(this)
}
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "IC2")
def getMaxSafeInput = Integer.MAX_VALUE
@Optional.Method(modid = "IC2")
def acceptsEnergyFrom(emitter: net.minecraft.tileentity.TileEntity, direction: ForgeDirection) = canConnect(direction, null)
@Optional.Method(modid = "IC2")
def demandedEnergyUnits = {
if (Settings.get.ignorePower || isClient) 0
else {
var maxDemand = 0.0
for (side <- ForgeDirection.VALID_DIRECTIONS) connector(side) match {
case Some(node) =>
maxDemand = math.max(maxDemand, node.globalBufferSize - node.globalBuffer)
case _ =>
}
maxDemand * Settings.ratioBC / Settings.ratioIC2
}
}
@Optional.Method(modid = "IC2")
def injectEnergyUnits(directionFrom: ForgeDirection, amount: Double) =
amount - onReceiveEnergy(directionFrom, (amount * Settings.ratioIC2).toLong, doReceive = true) / Settings.ratioIC2
}

View File

@ -0,0 +1,26 @@
package li.cil.oc.common.tileentity.traits.power
import cpw.mods.fml.common.Optional
import cofh.api.energy.IEnergyHandler
import net.minecraftforge.common.ForgeDirection
import li.cil.oc.Settings
@Optional.Interface(iface = "cofh.api.energy.IEnergyHandler", modid = "ThermalExpansion")
trait ThermalExpansion extends UniversalElectricity with IEnergyHandler {
@Optional.Method(modid = "ThermalExpansion")
def receiveEnergy(from: ForgeDirection, maxReceive: Int, simulate: Boolean) =
(onReceiveEnergy(from, (maxReceive * Settings.ratioTE).toLong, !simulate) / Settings.ratioTE).toInt
@Optional.Method(modid = "ThermalExpansion")
def extractEnergy(from: ForgeDirection, maxExtract: Int, simulate: Boolean) =
(onExtractEnergy(from, (maxExtract * Settings.ratioTE).toLong, !simulate) / Settings.ratioTE).toInt
@Optional.Method(modid = "ThermalExpansion")
def canInterface(from: ForgeDirection) = canConnect(from, this)
@Optional.Method(modid = "ThermalExpansion")
def getEnergyStored(from: ForgeDirection) = (getEnergy(from) / Settings.ratioTE).toInt
@Optional.Method(modid = "ThermalExpansion")
def getMaxEnergyStored(from: ForgeDirection) = (getEnergyCapacity(from) / Settings.ratioTE).toInt
}

View File

@ -0,0 +1,60 @@
package li.cil.oc.common.tileentity.traits.power
import cpw.mods.fml.common.Optional
import cpw.mods.fml.relauncher.{Side, SideOnly}
import li.cil.oc.api.network.Connector
import li.cil.oc.Settings
import net.minecraftforge.common.ForgeDirection
import universalelectricity.api.energy.{IEnergyInterface, IEnergyContainer}
import li.cil.oc.common.tileentity.traits.TileEntity
@Optional.InterfaceList(Array(
new Optional.Interface(iface = "universalelectricity.api.energy.IEnergyInterface", modid = "UniversalElectricity"),
new Optional.Interface(iface = "universalelectricity.api.energy.IEnergyContainer", modid = "UniversalElectricity")
))
trait UniversalElectricity extends TileEntity with IEnergyInterface with IEnergyContainer {
@SideOnly(Side.CLIENT)
protected def hasConnector(side: ForgeDirection) = false
protected def connector(side: ForgeDirection): Option[Connector] = None
// ----------------------------------------------------------------------- //
override def canConnect(direction: ForgeDirection, source: AnyRef) =
!Settings.get.ignorePower && direction != null && direction != ForgeDirection.UNKNOWN &&
(if (isClient) hasConnector(direction) else connector(direction).isDefined)
override def onReceiveEnergy(from: ForgeDirection, receive: Long, doReceive: Boolean) =
if (isClient || Settings.get.ignorePower) 0
else connector(from) match {
case Some(node) =>
val energy = receive / Settings.ratioBC
if (doReceive) {
val surplus = node.changeBuffer(energy)
(receive - surplus * Settings.ratioBC).toLong
}
else {
val space = node.globalBufferSize - node.globalBuffer
math.min(receive, space * Settings.ratioBC).toLong
}
case _ => 0
}
override def onExtractEnergy(from: ForgeDirection, extract: Long, doExtract: Boolean) = 0
override def setEnergy(from: ForgeDirection, energy: Long) {}
override def getEnergy(from: ForgeDirection) =
if (isClient) 0
else connector(from) match {
case Some(node) => (node.globalBuffer * Settings.ratioBC).toLong
case _ => 0
}
override def getEnergyCapacity(from: ForgeDirection) =
if (isClient) 0
else connector(from) match {
case Some(node) => (node.globalBufferSize * Settings.ratioBC).toLong
case _ => 0
}
}

View File

@ -24,6 +24,7 @@ class PacketHandler extends CommonPacketHandler {
case PacketType.Clipboard => onClipboard(p) case PacketType.Clipboard => onClipboard(p)
case PacketType.MouseClickOrDrag => onMouseClick(p) case PacketType.MouseClickOrDrag => onMouseClick(p)
case PacketType.MouseScroll => onMouseScroll(p) case PacketType.MouseScroll => onMouseScroll(p)
case PacketType.MouseUp => onMouseUp(p)
case PacketType.MultiPartPlace => onMultiPartPlace(p) case PacketType.MultiPartPlace => onMultiPartPlace(p)
case PacketType.RobotStateRequest => onRobotStateRequest(p) case PacketType.RobotStateRequest => onRobotStateRequest(p)
case PacketType.ServerRange => onServerRange(p) case PacketType.ServerRange => onServerRange(p)
@ -137,6 +138,28 @@ class PacketHandler extends CommonPacketHandler {
} }
} }
def onMouseUp(p: PacketParser) {
p.player match {
case player: EntityPlayerMP =>
val node = p.readTileEntity[TileEntity]() match {
case Some(t: Screen) => t.origin.node
case Some(t: Rack) => t.terminals(p.readInt()).buffer.node
case _ => return // Invalid packet.
}
val x = p.readInt()
val y = p.readInt()
val what = "drop"
val button = p.readByte()
if (Settings.get.inputUsername) {
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), Int.box(button), player.getCommandSenderName)
}
else {
node.sendToReachable("computer.checked_signal", player, what, Int.box(x), Int.box(y), Int.box(button))
}
case _ => // Invalid packet.
}
}
def onMultiPartPlace(p: PacketParser) { def onMultiPartPlace(p: PacketParser) {
p.player match { p.player match {
case player: EntityPlayerMP => EventHandler.place(player) case player: EntityPlayerMP => EventHandler.place(player)

View File

@ -5,7 +5,7 @@ import cpw.mods.fml.common.{FMLCommonHandler, Optional, TickType, ITickHandler}
import ic2.api.energy.event.{EnergyTileUnloadEvent, EnergyTileLoadEvent} import ic2.api.energy.event.{EnergyTileUnloadEvent, EnergyTileLoadEvent}
import java.util import java.util
import li.cil.oc.api.Network import li.cil.oc.api.Network
import li.cil.oc.common.tileentity.traits.IC2PowerGridAware import li.cil.oc.common.tileentity.traits.power
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import scala.collection.mutable import scala.collection.mutable
@ -27,7 +27,7 @@ object TickHandler extends ITickHandler {
} }
@Optional.Method(modid = "IC2") @Optional.Method(modid = "IC2")
def scheduleIC2Add(tileEntity: TileEntity with IC2PowerGridAware) = pending.synchronized { def scheduleIC2Add(tileEntity: power.IndustrialCraft2) = pending.synchronized {
pending += (() => if (!tileEntity.addedToPowerGrid && !tileEntity.isInvalid) { pending += (() => if (!tileEntity.addedToPowerGrid && !tileEntity.isInvalid) {
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(tileEntity)) MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(tileEntity))
tileEntity.addedToPowerGrid = true tileEntity.addedToPowerGrid = true
@ -35,7 +35,7 @@ object TickHandler extends ITickHandler {
} }
@Optional.Method(modid = "IC2") @Optional.Method(modid = "IC2")
def scheduleIC2Remove(tileEntity: TileEntity with IC2PowerGridAware) = pending.synchronized { def scheduleIC2Remove(tileEntity: power.IndustrialCraft2) = pending.synchronized {
pending += (() => if (tileEntity.addedToPowerGrid) { pending += (() => if (tileEntity.addedToPowerGrid) {
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(tileEntity)) MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(tileEntity))
tileEntity.addedToPowerGrid = false tileEntity.addedToPowerGrid = false