mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 09:18:05 -04:00
Added ability to copy lines from screens using the analyzer (shift-rightclicking the line with the analyzer), then paste it on a screen by simply rightclicking it with the analyzer. Closes #644.
This commit is contained in:
parent
16170e31ee
commit
f69250b565
@ -110,6 +110,15 @@ object PacketSender {
|
||||
pb.sendToServer()
|
||||
}
|
||||
|
||||
def sendCopyToAnalyzer(address: String, line: Int): Unit = {
|
||||
val pb = new SimplePacketBuilder(PacketType.CopyToAnalyzer)
|
||||
|
||||
pb.writeUTF(address)
|
||||
pb.writeInt(line)
|
||||
|
||||
pb.sendToServer()
|
||||
}
|
||||
|
||||
def sendMultiPlace() {
|
||||
val pb = new SimplePacketBuilder(PacketType.MultiPartPlace)
|
||||
pb.sendToServer()
|
||||
|
@ -52,6 +52,7 @@ object PacketType extends Enumeration {
|
||||
|
||||
// Client -> Server
|
||||
ComputerPower,
|
||||
CopyToAnalyzer,
|
||||
DronePower,
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
|
@ -6,10 +6,12 @@ import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.common.GuiType
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.integration.util.Wrench
|
||||
import li.cil.oc.util._
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
@ -332,6 +334,7 @@ class Screen(val tier: Int) extends RedstoneAware {
|
||||
def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
|
||||
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float, force: Boolean) = {
|
||||
if (Wrench.holdsApplicableWrench(player, BlockPosition(x, y, z)) && getValidRotations(world, x, y, z).contains(side) && !force) false
|
||||
else if (api.Items.get(player.getHeldItem) == api.Items.get("analyzer")) false
|
||||
else world.getTileEntity(x, y, z) match {
|
||||
case screen: tileentity.Screen if screen.hasKeyboard && (force || player.isSneaking == screen.invertTouchMode) =>
|
||||
// Yep, this GUI is actually purely client side. We could skip this
|
||||
@ -342,7 +345,10 @@ class Screen(val tier: Int) extends RedstoneAware {
|
||||
}
|
||||
true
|
||||
case screen: tileentity.Screen if screen.tier > 0 && side == screen.facing =>
|
||||
screen.click(player, hitX, hitY, hitZ)
|
||||
if (world.isRemote && player == Minecraft.getMinecraft.thePlayer) {
|
||||
screen.click(hitX, hitY, hitZ)
|
||||
}
|
||||
else true
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
@ -429,6 +429,10 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
|
||||
override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) =
|
||||
mouseScroll(x, y, delta, player)
|
||||
|
||||
def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
|
||||
proxy.copyToAnalyzer(line, player)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onConnect(node: Node) {
|
||||
@ -602,6 +606,8 @@ object TextBuffer {
|
||||
def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
|
||||
|
||||
def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer): Unit
|
||||
|
||||
def copyToAnalyzer(line: Int, player: EntityPlayer): Unit
|
||||
}
|
||||
|
||||
class ClientProxy(val owner: TextBuffer) extends Proxy {
|
||||
@ -686,6 +692,10 @@ object TextBuffer {
|
||||
ClientPacketSender.sendMouseScroll(nodeAddress, x, y, delta)
|
||||
}
|
||||
|
||||
override def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
|
||||
ClientPacketSender.sendCopyToAnalyzer(nodeAddress, line)
|
||||
}
|
||||
|
||||
private lazy val Debugger = api.Items.get("debugger")
|
||||
|
||||
private def debug(message: String) {
|
||||
@ -789,6 +799,27 @@ object TextBuffer {
|
||||
sendMouseEvent(player, "scroll", x, y, delta)
|
||||
}
|
||||
|
||||
override def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
|
||||
val stack = player.getHeldItem
|
||||
if (stack != null) {
|
||||
if (!stack.hasTagCompound) {
|
||||
stack.setTagCompound(new NBTTagCompound())
|
||||
}
|
||||
stack.getTagCompound.removeTag(Settings.namespace + "clipboard")
|
||||
|
||||
if (line >= 0 && line < owner.data.height) {
|
||||
val text = new String(owner.data.buffer(line)).trim
|
||||
if (!Strings.isNullOrEmpty(text)) {
|
||||
stack.getTagCompound.setString(Settings.namespace + "clipboard", text)
|
||||
}
|
||||
}
|
||||
|
||||
if (stack.getTagCompound.hasNoTags) {
|
||||
stack.setTagCompound(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def sendMouseEvent(player: EntityPlayer, name: String, x: Double, y: Double, data: Int) = {
|
||||
val args = mutable.ArrayBuffer.empty[AnyRef]
|
||||
|
||||
|
@ -2,15 +2,18 @@ package li.cil.oc.common.item
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import li.cil.oc.Localization
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.network.Analyzable
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.server.PacketSender
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import net.minecraftforge.event.entity.player.EntityInteractEvent
|
||||
|
||||
@ -79,7 +82,31 @@ object Analyzer {
|
||||
}
|
||||
|
||||
class Analyzer(val parent: Delegator) extends Delegate {
|
||||
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
|
||||
if (player.isSneaking && stack.hasTagCompound) {
|
||||
stack.getTagCompound.removeTag(Settings.namespace + "clipboard")
|
||||
if (stack.getTagCompound.hasNoTags) {
|
||||
stack.setTagCompound(null)
|
||||
}
|
||||
}
|
||||
super.onItemRightClick(stack, world, player)
|
||||
}
|
||||
|
||||
override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||
Analyzer.analyze(position.world.get.getTileEntity(position), player, side, hitX, hitY, hitZ)
|
||||
val world = player.getEntityWorld
|
||||
world.getTileEntity(position) match {
|
||||
case screen: tileentity.Screen if ForgeDirection.getOrientation(side) == screen.facing =>
|
||||
if (player.isSneaking) {
|
||||
screen.copyToAnalyzer(hitX, hitY, hitZ)
|
||||
}
|
||||
else if (stack.hasTagCompound && stack.getTagCompound.hasKey(Settings.namespace + "clipboard")) {
|
||||
if (!world.isRemote) {
|
||||
screen.origin.buffer.clipboard(stack.getTagCompound.getString(Settings.namespace + "clipboard"), player)
|
||||
}
|
||||
true
|
||||
}
|
||||
else false
|
||||
case _ => Analyzer.analyze(position.world.get.getTileEntity(position), player, side, hitX, hitY, hitZ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cpw.mods.fml.relauncher.SideOnly
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.network.Analyzable
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.common.component.TextBuffer
|
||||
import li.cil.oc.util.Color
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.entity.Entity
|
||||
@ -93,7 +94,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
||||
invertTouchMode = false
|
||||
}
|
||||
|
||||
def click(player: EntityPlayer, hitX: Double, hitY: Double, hitZ: Double): Boolean = {
|
||||
def toScreenCoordinates(hitX: Double, hitY: Double, hitZ: Double): (Boolean, Option[(Double, Double)]) = {
|
||||
// Compute absolute position of the click on the face, measured in blocks.
|
||||
def dot(f: ForgeDirection) = f.offsetX * hitX + f.offsetY * hitY + f.offsetZ * hitZ
|
||||
val (hx, hy) = (dot(toGlobal(ForgeDirection.EAST)), dot(toGlobal(ForgeDirection.UP)))
|
||||
@ -105,9 +106,9 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
||||
// Get the relative position in the *display area* of the face.
|
||||
val border = 2.25 / 16.0
|
||||
if (ax <= border || ay <= border || ax >= width - border || ay >= height - border) {
|
||||
return false
|
||||
return (false, None)
|
||||
}
|
||||
if (!world.isRemote) return true
|
||||
if (!world.isRemote) return (true, None)
|
||||
|
||||
val (iw, ih) = (width - border * 2, height - border * 2)
|
||||
val (rx, ry) = ((ax - border) / iw, (ay - border) / ih)
|
||||
@ -119,27 +120,43 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
||||
val (brx, bry) = if (bpw > bph) {
|
||||
val rh = bph.toDouble / bpw.toDouble
|
||||
val bry = (ry - (1 - rh) * 0.5) / rh
|
||||
if (bry <= 0 || bry >= 1) {
|
||||
return true
|
||||
}
|
||||
(rx, bry)
|
||||
}
|
||||
else if (bph > bpw) {
|
||||
val rw = bpw.toDouble / bph.toDouble
|
||||
val brx = (rx - (1 - rw) * 0.5) / rw
|
||||
if (brx <= 0 || brx >= 1) {
|
||||
return true
|
||||
}
|
||||
(brx, ry)
|
||||
}
|
||||
else {
|
||||
(rx, ry)
|
||||
}
|
||||
|
||||
// Convert to absolute coordinates and send the packet to the server.
|
||||
origin.buffer.mouseDown(brx * bw, bry * bh, 0, null)
|
||||
val inBounds = bry >= 0 && bry <= 1 && brx >= 0 || brx <= 1
|
||||
(inBounds, Some((brx * bw, bry * bh)))
|
||||
}
|
||||
|
||||
true
|
||||
def copyToAnalyzer(hitX: Double, hitY: Double, hitZ: Double): Boolean = {
|
||||
val (inBounds, coordinates) = toScreenCoordinates(hitX, hitY, hitZ)
|
||||
coordinates match {
|
||||
case Some((x, y)) => origin.buffer match {
|
||||
case buffer: TextBuffer =>
|
||||
buffer.copyToAnalyzer(y.toInt, null)
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
case _ => inBounds
|
||||
}
|
||||
}
|
||||
|
||||
def click(hitX: Double, hitY: Double, hitZ: Double): Boolean = {
|
||||
val (inBounds, coordinates) = toScreenCoordinates(hitX, hitY, hitZ)
|
||||
coordinates match {
|
||||
case Some((x, y)) =>
|
||||
// Send the packet to the server (manually, for accuracy).
|
||||
origin.buffer.mouseDown(x, y, 0, null)
|
||||
true
|
||||
case _ => inBounds
|
||||
}
|
||||
}
|
||||
|
||||
def walk(entity: Entity) {
|
||||
@ -236,7 +253,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
||||
hitXInner && !hitYInner && hitZInner ||
|
||||
!hitXInner && hitYInner && hitZInner) {
|
||||
arrow.shootingEntity match {
|
||||
case player: EntityPlayer if player == Minecraft.getMinecraft.thePlayer => click(player, hitX, hitY, hitZ)
|
||||
case player: EntityPlayer if player == Minecraft.getMinecraft.thePlayer => click(hitX, hitY, hitZ)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ object PacketHandler extends CommonPacketHandler {
|
||||
override def dispatch(p: PacketParser) {
|
||||
p.packetType match {
|
||||
case PacketType.ComputerPower => onComputerPower(p)
|
||||
case PacketType.CopyToAnalyzer => onCopyToAnalyzer(p)
|
||||
case PacketType.DronePower => onDronePower(p)
|
||||
case PacketType.KeyDown => onKeyDown(p)
|
||||
case PacketType.KeyUp => onKeyUp(p)
|
||||
@ -67,6 +68,13 @@ object PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onCopyToAnalyzer(p: PacketParser) {
|
||||
ComponentTracker.get(p.player.worldObj, p.readUTF()) match {
|
||||
case Some(buffer: TextBuffer) => buffer.copyToAnalyzer(p.readInt(), p.player.asInstanceOf[EntityPlayer])
|
||||
case _ => // Invalid Packet
|
||||
}
|
||||
}
|
||||
|
||||
def onDronePower(p: PacketParser) =
|
||||
p.readEntity[Drone]() match {
|
||||
case Some(drone) => p.player match {
|
||||
|
Loading…
x
Reference in New Issue
Block a user