mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 19:25:20 -04:00
Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8
Conflicts: src/main/scala/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala src/main/scala/li/cil/oc/common/EventHandler.scala src/main/scala/li/cil/oc/common/block/Case.scala src/main/scala/li/cil/oc/common/block/Screen.scala src/main/scala/li/cil/oc/common/component/Terminal.scala src/main/scala/li/cil/oc/common/component/TextBuffer.scala src/main/scala/li/cil/oc/common/item/Analyzer.scala src/main/scala/li/cil/oc/common/tileentity/Screen.scala src/main/scala/li/cil/oc/server/component/DebugCard.scala src/main/scala/li/cil/oc/server/component/Geolyzer.scala
This commit is contained in:
commit
57b8968060
@ -153,6 +153,7 @@ public interface Context {
|
||||
* <li>Strings.</li>
|
||||
* <li>Byte arrays (which appear as strings on the Lua side, e.g.).</li>
|
||||
* <li>Maps if and only if both keys and values are strings.</li>
|
||||
* <li>NBTTagCompounds.</li>
|
||||
* </ul>
|
||||
* If an unsupported type is specified the method will enqueue nothing
|
||||
* instead, resulting in a <tt>nil</tt> on the Lua side, e.g., and log a
|
||||
|
@ -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()
|
||||
|
@ -284,7 +284,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
|
||||
val timeJitter = robot.hashCode ^ 0xFF
|
||||
val hover =
|
||||
if (robot.isRunning) (Math.sin(timeJitter + (worldTime + f) / 20.0) * 0.03).toFloat
|
||||
if (robot.isRunning) (Math.sin(timeJitter + worldTime / 20.0) * 0.03).toFloat
|
||||
else -0.03f
|
||||
GL11.glTranslatef(0, hover, 0)
|
||||
|
||||
|
@ -19,6 +19,7 @@ import net.minecraft.item.ItemStack
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraftforge.common.util.FakePlayer
|
||||
import net.minecraftforge.event.world.BlockEvent
|
||||
import net.minecraftforge.event.world.WorldEvent
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent._
|
||||
@ -114,6 +115,22 @@ object EventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def onBlockBreak(e: BlockEvent.BreakEvent): Unit = {
|
||||
e.world.getTileEntity(e.pos) match {
|
||||
case c: tileentity.Case =>
|
||||
if (c.isCreative && (!e.getPlayer.capabilities.isCreativeMode || !c.canInteract(e.getPlayer.getName))) {
|
||||
e.setCanceled(true)
|
||||
}
|
||||
case r: tileentity.RobotProxy =>
|
||||
val robot = r.robot
|
||||
if (robot.isCreative && (!e.getPlayer.capabilities.isCreativeMode || !robot.canInteract(e.getPlayer.getName))) {
|
||||
e.setCanceled(true)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
lazy val drone = api.Items.get("drone")
|
||||
lazy val eeprom = api.Items.get("eeprom")
|
||||
lazy val mcu = api.Items.get("microcontroller")
|
||||
|
@ -51,6 +51,7 @@ object PacketType extends Enumeration {
|
||||
|
||||
// Client -> Server
|
||||
ComputerPower,
|
||||
CopyToAnalyzer,
|
||||
DronePower,
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
|
@ -86,7 +86,9 @@ class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with t
|
||||
|
||||
override def removedByPlayer(world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean) =
|
||||
world.getTileEntity(pos) match {
|
||||
case c: tileentity.Case => c.canInteract(player.getName) && super.removedByPlayer(world, pos, player, willHarvest)
|
||||
case c: tileentity.Case =>
|
||||
if (c.isCreative && (!player.capabilities.isCreativeMode || !c.canInteract(player.getName))) false
|
||||
else c.canInteract(player.getName) && super.removedByPlayer(world, pos, player, willHarvest)
|
||||
case _ => super.removedByPlayer(world, pos, player, willHarvest)
|
||||
}
|
||||
}
|
||||
|
@ -230,6 +230,11 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
|
||||
world.getTileEntity(pos) match {
|
||||
case proxy: tileentity.RobotProxy =>
|
||||
val robot = proxy.robot
|
||||
// Only allow breaking creative tier robots by allowed users.
|
||||
// Unlike normal robots, griefing isn't really a valid concern
|
||||
// here, because to get a creative robot you need creative
|
||||
// mode in the first place.
|
||||
if (robot.isCreative && (!player.capabilities.isCreativeMode || !robot.canInteract(player.getName))) return false
|
||||
if (!world.isRemote) {
|
||||
if (robot.player == player) return false
|
||||
robot.node.remove()
|
||||
|
@ -4,6 +4,7 @@ import java.util
|
||||
|
||||
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
|
||||
@ -13,6 +14,7 @@ import li.cil.oc.util.Rarity
|
||||
import li.cil.oc.util.Tooltip
|
||||
import net.minecraft.block.properties.IProperty
|
||||
import net.minecraft.block.state.IBlockState
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
@ -88,6 +90,7 @@ class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
|
||||
def rightClick(world: World, pos: BlockPos, player: EntityPlayer,
|
||||
side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, force: Boolean) = {
|
||||
if (Wrench.holdsApplicableWrench(player, pos) && getValidRotations(world, pos).contains(side) && !force) false
|
||||
else if (api.Items.get(player.getHeldItem) == api.Items.get("analyzer")) false
|
||||
else world.getTileEntity(pos) 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
|
||||
@ -98,7 +101,10 @@ class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import li.cil.oc.api.component.Keyboard.UsabilityChecker
|
||||
import li.cil.oc.api.network.Component
|
||||
import li.cil.oc.api.network.Node
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.common.Tier
|
||||
import li.cil.oc.common.item
|
||||
import li.cil.oc.common.item.Delegator
|
||||
import li.cil.oc.common.tileentity
|
||||
@ -23,9 +24,9 @@ class Terminal(val rack: tileentity.ServerRack, val number: Int) {
|
||||
val buffer = {
|
||||
val screenItem = api.Items.get("screen1").createItemStack(1)
|
||||
val buffer = api.Driver.driverFor(screenItem, rack.getClass).createEnvironment(screenItem, rack).asInstanceOf[api.component.TextBuffer]
|
||||
val (maxWidth, maxHeight) = Settings.screenResolutionsByTier(1)
|
||||
val (maxWidth, maxHeight) = Settings.screenResolutionsByTier(Tier.Three)
|
||||
buffer.setMaximumResolution(maxWidth, maxHeight)
|
||||
buffer.setMaximumColorDepth(Settings.screenDepthsByTier(1))
|
||||
buffer.setMaximumColorDepth(Settings.screenDepthsByTier(Tier.Three))
|
||||
buffer
|
||||
}
|
||||
|
||||
|
@ -415,6 +415,10 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
|
||||
override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer) =
|
||||
proxy.mouseScroll(x, y, delta, player)
|
||||
|
||||
def copyToAnalyzer(line: Int, player: EntityPlayer): Unit = {
|
||||
proxy.copyToAnalyzer(line, player)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onConnect(node: Node) {
|
||||
@ -588,6 +592,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 {
|
||||
@ -672,6 +678,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) {
|
||||
@ -775,6 +785,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]
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
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._
|
||||
@ -11,6 +13,7 @@ import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.event.entity.player.EntityInteractEvent
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
|
||||
|
||||
@ -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: EnumFacing, 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 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import li.cil.oc.common.inventory.ComponentInventory
|
||||
import li.cil.oc.common.item.data.TabletData
|
||||
import li.cil.oc.integration.opencomputers.DriverScreen
|
||||
import li.cil.oc.server.component
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.util.Rarity
|
||||
import li.cil.oc.util.RotationHelper
|
||||
@ -93,6 +94,24 @@ class Tablet(val parent: Delegator) extends Delegate {
|
||||
case _ =>
|
||||
}
|
||||
|
||||
override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
|
||||
val world = player.getEntityWorld
|
||||
if (!world.isRemote) try {
|
||||
val computer = Tablet.get(stack, player).machine
|
||||
if (computer.isRunning) {
|
||||
val data = new NBTTagCompound()
|
||||
computer.node.sendToReachable("tablet.use", data, stack, player, position, side, float2Float(hitX), float2Float(hitY), float2Float(hitZ))
|
||||
if (!data.hasNoTags) {
|
||||
computer.signal("tablet_use", data)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case t: Throwable => OpenComputers.log.warn("Block analysis on tablet right click failed gloriously!", t)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer) = {
|
||||
if (!player.isSneaking) {
|
||||
if (world.isRemote) {
|
||||
|
@ -35,7 +35,7 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
|
||||
|
||||
var maxComponents = 0
|
||||
|
||||
private def isCreativeCase = tier == Tier.Four
|
||||
def isCreative = tier == Tier.Four
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -74,7 +74,7 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
|
||||
override def canUpdate = isServer
|
||||
|
||||
override def updateEntity() {
|
||||
if (isServer && isCreativeCase && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
|
||||
if (isServer && isCreative && world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
|
||||
// Creative case, make it generate power.
|
||||
node.asInstanceOf[Connector].changeBuffer(Double.PositiveInfinity)
|
||||
}
|
||||
@ -135,7 +135,7 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
|
||||
override def getSizeInventory = if (tier < 0 || tier >= InventorySlots.computer.length) 0 else InventorySlots.computer(tier).length
|
||||
|
||||
override def isUseableByPlayer(player: EntityPlayer) =
|
||||
super.isUseableByPlayer(player) && (!isCreativeCase || player.capabilities.isCreativeMode)
|
||||
super.isUseableByPlayer(player) && (!isCreative || player.capabilities.isCreativeMode)
|
||||
|
||||
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
|
||||
Option(Driver.driverFor(stack, getClass)).fold(false)(driver => {
|
||||
|
@ -70,6 +70,8 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
|
||||
|
||||
override def tier = info.tier
|
||||
|
||||
def isCreative = tier == Tier.Four
|
||||
|
||||
// Wrapper for the part of the inventory that is mutable.
|
||||
val dynamicInventory = new IInventory {
|
||||
override def getSizeInventory = Robot.this.inventorySize
|
||||
@ -749,6 +751,9 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
|
||||
else if (stack != null && stack.stackSize > 0) spawnStackInWorld(stack, Option(EnumFacing.UP))
|
||||
}
|
||||
|
||||
override def isUseableByPlayer(player: EntityPlayer) =
|
||||
super.isUseableByPlayer(player) && (!isCreative || player.capabilities.isCreativeMode)
|
||||
|
||||
override def isItemValidForSlot(slot: Int, stack: ItemStack) = (slot, Option(Driver.driverFor(stack, getClass))) match {
|
||||
case (0, _) => true // Allow anything in the tool slot.
|
||||
case (i, Some(driver)) if isContainerSlot(i) =>
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.common.tileentity
|
||||
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.BlockPosition
|
||||
import li.cil.oc.util.Color
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
@ -95,7 +96,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: EnumFacing) = f.getFrontOffsetX * hitX + f.getFrontOffsetY * hitY + f.getFrontOffsetZ * hitZ
|
||||
val (hx, hy) = (dot(toGlobal(EnumFacing.EAST)), dot(toGlobal(EnumFacing.UP)))
|
||||
@ -107,9 +108,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)
|
||||
@ -121,27 +122,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) {
|
||||
@ -238,7 +255,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 _ =>
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package li.cil.oc.integration.vanilla
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.api
|
||||
import net.minecraft.nbt._
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
object ConverterNBT extends api.driver.Converter {
|
||||
override def convert(value: AnyRef, output: util.Map[AnyRef, AnyRef]) =
|
||||
value match {
|
||||
case nbt: NBTTagCompound => output += "oc:flatten" -> convert(nbt)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
private def convert(nbt: NBTBase): AnyRef = nbt match {
|
||||
case tag: NBTTagByte => byte2Byte(tag.getByte)
|
||||
case tag: NBTTagShort => short2Short(tag.getShort)
|
||||
case tag: NBTTagInt => int2Integer(tag.getInt)
|
||||
case tag: NBTTagLong => long2Long(tag.getLong)
|
||||
case tag: NBTTagFloat => float2Float(tag.getFloat)
|
||||
case tag: NBTTagDouble => double2Double(tag.getDouble)
|
||||
case tag: NBTTagByteArray => tag.getByteArray
|
||||
case tag: NBTTagString => tag.getString
|
||||
case tag: NBTTagList =>
|
||||
val copy = tag.copy().asInstanceOf[NBTTagList]
|
||||
(0 until copy.tagCount).map(_ => convert(copy.removeTag(0))).toArray
|
||||
case tag: NBTTagCompound =>
|
||||
tag.getKeySet.collect {
|
||||
case key: String => key -> convert(tag.getTag(key))
|
||||
}.toMap
|
||||
case tag: NBTTagIntArray => tag.getIntArray
|
||||
}
|
||||
}
|
@ -31,5 +31,6 @@ object ModVanilla extends ModProxy {
|
||||
Driver.add(ConverterFluidStack)
|
||||
Driver.add(ConverterFluidTankInfo)
|
||||
Driver.add(ConverterItemStack)
|
||||
Driver.add(ConverterNBT)
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,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)
|
||||
@ -73,6 +74,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 {
|
||||
|
@ -35,6 +35,9 @@ import net.minecraft.world.WorldServer
|
||||
import net.minecraft.world.WorldSettings.GameType
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
import net.minecraftforge.common.util.FakePlayerFactory
|
||||
import net.minecraftforge.fluids.FluidRegistry
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.IFluidHandler
|
||||
|
||||
class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
||||
override val node = Network.newNode(this, Visibility.Neighbors).
|
||||
@ -426,6 +429,7 @@ object DebugCard {
|
||||
|
||||
@Callback(doc = """function(x:number, y:number, z:number, slot:number[, count:number]):number - Reduce the size of an item stack in the inventory at the specified location.""")
|
||||
def removeItem(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
checkEnabled()
|
||||
val position = BlockPosition(args.checkDouble(0), args.checkDouble(1), args.checkDouble(2), world)
|
||||
InventoryUtils.inventoryAt(position) match {
|
||||
case Some(inventory) =>
|
||||
@ -438,6 +442,34 @@ object DebugCard {
|
||||
}
|
||||
}
|
||||
|
||||
@Callback(doc = """function(id:string, amount:number, x:number, y:number, z:number, side:number):boolean - Insert some fluid into the tank at the specified location.""")
|
||||
def insertFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
checkEnabled()
|
||||
val fluid = FluidRegistry.getFluid(args.checkString(0))
|
||||
if (fluid == null) {
|
||||
throw new IllegalArgumentException("invalid fluid id")
|
||||
}
|
||||
val amount = args.checkInteger(1)
|
||||
val position = BlockPosition(args.checkDouble(2), args.checkDouble(3), args.checkDouble(4), world)
|
||||
val side = args.checkSide(5, EnumFacing.values: _*)
|
||||
world.getTileEntity(position) match {
|
||||
case handler: IFluidHandler => result(handler.fill(side, new FluidStack(fluid, amount), true))
|
||||
case _ => result(null, "no tank")
|
||||
}
|
||||
}
|
||||
|
||||
@Callback(doc = """function(amount:number, x:number, y:number, z:number, side:number):boolean - Remove some fluid from a tank at the specified location.""")
|
||||
def removeFluid(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
checkEnabled()
|
||||
val amount = args.checkInteger(0)
|
||||
val position = BlockPosition(args.checkDouble(1), args.checkDouble(2), args.checkDouble(3), world)
|
||||
val side = args.checkSide(4, EnumFacing.values: _*)
|
||||
world.getTileEntity(position) match {
|
||||
case handler: IFluidHandler => result(handler.drain(side, amount, true))
|
||||
case _ => result(null, "no tank")
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
|
@ -1,22 +1,27 @@
|
||||
package li.cil.oc.server.component
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import li.cil.oc.api.event.GeolyzerEvent
|
||||
import li.cil.oc.api.event.GeolyzerEvent.Analyze
|
||||
import li.cil.oc.api.internal.Rotatable
|
||||
import li.cil.oc.api.internal
|
||||
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.Message
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import li.cil.oc.util.DatabaseAccess
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
|
||||
@ -51,7 +56,7 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
||||
def analyze(computer: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
|
||||
val side = args.checkSide(0, EnumFacing.values: _*)
|
||||
val globalSide = host match {
|
||||
case rotatable: Rotatable => rotatable.toGlobal(side)
|
||||
case rotatable: internal.Rotatable => rotatable.toGlobal(side)
|
||||
case _ => side
|
||||
}
|
||||
val options = args.optTable(1, Map.empty[AnyRef, AnyRef])
|
||||
@ -70,7 +75,7 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
||||
def store(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = args.checkSide(0, EnumFacing.values: _*)
|
||||
val globalSide = host match {
|
||||
case rotatable: Rotatable => rotatable.toGlobal(side)
|
||||
case rotatable: internal.Rotatable => rotatable.toGlobal(side)
|
||||
case _ => side
|
||||
}
|
||||
|
||||
@ -93,4 +98,42 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override def onMessage(message: Message): Unit = {
|
||||
super.onMessage(message)
|
||||
if (message.name == "tablet.use") message.source.host match {
|
||||
case machine: api.machine.Machine => (machine.host, message.data) match {
|
||||
case (tablet: internal.Tablet, Array(nbt: NBTTagCompound, stack: ItemStack, player: EntityPlayer, blockPos: BlockPosition, side: EnumFacing, hitX: java.lang.Float, hitY: java.lang.Float, hitZ: java.lang.Float)) =>
|
||||
if (node.tryChangeBuffer(-Settings.get.geolyzerScanCost)) {
|
||||
// TODO 1.5 replace with event (change event to allow arbitrary coordinates)
|
||||
val world = player.getEntityWorld
|
||||
val block = world.getBlock(blockPos)
|
||||
|
||||
Block.blockRegistry.getNameForObject(block) match {
|
||||
case name: String if !Strings.isNullOrEmpty(name) => nbt.setString("name", name)
|
||||
case _ =>
|
||||
}
|
||||
nbt.setInteger("metadata", block.getMetaFromState(world.getBlockMetadata(blockPos)))
|
||||
nbt.setFloat("hardness", world.getBlockHardness(blockPos))
|
||||
nbt.setInteger("harvestLevel", world.getBlockHarvestLevel(blockPos))
|
||||
if (!Strings.isNullOrEmpty(world.getBlockHarvestTool(blockPos))) {
|
||||
nbt.setString("harvestTool", world.getBlockHarvestTool(blockPos))
|
||||
}
|
||||
nbt.setInteger("color", world.getBlockMapColor(blockPos).colorValue)
|
||||
|
||||
// val event = new Analyze(host, Map.empty[AnyRef, AnyRef], side)
|
||||
// MinecraftForge.EVENT_BUS.post(event)
|
||||
// if (!event.isCanceled) {
|
||||
// for ((key, value) <- event.data) value match {
|
||||
// case number: java.lang.Number => nbt.setDouble(key, number.doubleValue())
|
||||
// case string: String if !string.isEmpty => nbt.setString(key, string)
|
||||
// case _ => // Unsupported, ignore.
|
||||
// }
|
||||
// }
|
||||
}
|
||||
case _ => // Ignore.
|
||||
}
|
||||
case _ => // Ignore.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
package li.cil.oc.server.component
|
||||
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import li.cil.oc.api.internal
|
||||
import li.cil.oc.api.internal.Rotatable
|
||||
import li.cil.oc.api.machine.Arguments
|
||||
import li.cil.oc.api.machine.Callback
|
||||
@ -9,7 +11,11 @@ import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.common.item.data.NavigationUpgradeData
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.EnumFacing
|
||||
|
||||
class UpgradeNavigation(val host: EnvironmentHost with Rotatable) extends prefab.ManagedEnvironment {
|
||||
override val node = Network.newNode(this, Visibility.Network).
|
||||
@ -43,6 +49,21 @@ class UpgradeNavigation(val host: EnvironmentHost with Rotatable) extends prefab
|
||||
result(size / 2)
|
||||
}
|
||||
|
||||
override def onMessage(message: Message): Unit = {
|
||||
super.onMessage(message)
|
||||
if (message.name == "tablet.use") message.source.host match {
|
||||
case machine: api.machine.Machine => (machine.host, message.data) match {
|
||||
case (tablet: internal.Tablet, Array(nbt: NBTTagCompound, stack: ItemStack, player: EntityPlayer, blockPos: BlockPosition, side: EnumFacing, hitX: java.lang.Float, hitY: java.lang.Float, hitZ: java.lang.Float)) =>
|
||||
val info = data.mapData(host.world)
|
||||
nbt.setInteger("posX", blockPos.x - info.xCenter)
|
||||
nbt.setInteger("posY", blockPos.y)
|
||||
nbt.setInteger("posZ", blockPos.z - info.zCenter)
|
||||
case _ => // Ignore.
|
||||
}
|
||||
case _ => // Ignore.
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
|
@ -7,7 +7,6 @@ import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.server.component.result
|
||||
import li.cil.oc.util.DatabaseAccess
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
trait InventoryAnalytics extends InventoryAware with NetworkAware {
|
||||
@Callback(doc = """function([slot:number]):table -- Get a description of the stack in the specified slot or the selected slot.""")
|
||||
@ -21,12 +20,24 @@ trait InventoryAnalytics extends InventoryAware with NetworkAware {
|
||||
def storeInternal(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val localSlot = args.checkSlot(inventory, 0)
|
||||
val dbAddress = args.checkString(1)
|
||||
def store(stack: ItemStack) = DatabaseAccess.withDatabase(node, dbAddress, database => {
|
||||
val localStack = inventory.getStackInSlot(localSlot)
|
||||
DatabaseAccess.withDatabase(node, dbAddress, database => {
|
||||
val dbSlot = args.checkSlot(database.data, 2)
|
||||
val nonEmpty = database.data.getStackInSlot(dbSlot) != null
|
||||
database.data.setInventorySlotContents(dbSlot, stack.copy())
|
||||
database.data.setInventorySlotContents(dbSlot, localStack.copy())
|
||||
result(nonEmpty)
|
||||
})
|
||||
store(inventory.getStackInSlot(localSlot))
|
||||
}
|
||||
|
||||
@Callback(doc = """function(slot:number, dbAddress:string, dbSlot:number):boolean -- Compare an item in the specified slot with one in the database with the specified address.""")
|
||||
def compareToDatabase(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val localSlot = args.checkSlot(inventory, 0)
|
||||
val dbAddress = args.checkString(1)
|
||||
val localStack = inventory.getStackInSlot(localSlot)
|
||||
DatabaseAccess.withDatabase(node, dbAddress, database => {
|
||||
val dbSlot = args.checkSlot(database.data, 2)
|
||||
val dbStack = database.data.getStackInSlot(dbSlot)
|
||||
result(haveSameItemType(localStack, dbStack))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ trait InventoryAware {
|
||||
protected def stackInSlot(slot: Int) = Option(inventory.getStackInSlot(slot))
|
||||
|
||||
protected def haveSameItemType(stackA: ItemStack, stackB: ItemStack) =
|
||||
stackA.getItem == stackB.getItem &&
|
||||
stackA != null && stackB != null &&
|
||||
stackA.getItem == stackB.getItem &&
|
||||
(!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage)
|
||||
}
|
||||
|
@ -238,6 +238,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
case arg: java.lang.String => arg
|
||||
case arg: Array[Byte] => arg
|
||||
case arg: Map[_, _] if arg.isEmpty || arg.head._1.isInstanceOf[String] && arg.head._2.isInstanceOf[String] => arg
|
||||
case arg: NBTTagCompound => arg
|
||||
case arg =>
|
||||
OpenComputers.log.warn("Trying to push signal with an unsupported argument of type " + arg.getClass.getName)
|
||||
null
|
||||
@ -247,7 +248,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
}
|
||||
})
|
||||
|
||||
override def popSignal(): Machine.Signal = signals.synchronized(if (signals.isEmpty) null else signals.dequeue())
|
||||
override def popSignal(): Machine.Signal = signals.synchronized(if (signals.isEmpty) null else signals.dequeue().convert())
|
||||
|
||||
override def methods(value: scala.AnyRef) = Callbacks(value).map(entry => {
|
||||
val (name, callback) = entry
|
||||
@ -628,6 +629,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
data += tag.getStringTagAt(i) -> tag.getStringTagAt(i + 1)
|
||||
}
|
||||
data
|
||||
case tag: NBTTagCompound => tag
|
||||
case _ => null
|
||||
}.toArray[AnyRef])
|
||||
})
|
||||
@ -705,6 +707,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
list.append(value.toString)
|
||||
}
|
||||
args.setTag("arg" + i, list)
|
||||
case (arg: NBTTagCompound, i) => args.setTag("arg" + i, arg)
|
||||
case (_, i) => args.setByte("arg" + i, -1)
|
||||
}
|
||||
})
|
||||
@ -936,7 +939,9 @@ object Machine extends MachineAPI {
|
||||
}
|
||||
|
||||
/** Signals are messages sent to the Lua state from Java asynchronously. */
|
||||
private[machine] class Signal(val name: String, val args: Array[AnyRef]) extends machine.Signal
|
||||
private[machine] class Signal(val name: String, val args: Array[AnyRef]) extends machine.Signal {
|
||||
def convert() = new Signal(name, Registry.convert(args))
|
||||
}
|
||||
|
||||
private val threadPool = ThreadPoolFactory.create("Computer", Settings.get.threads)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user