mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 02:12:42 -04:00
get a move on. robots can now move. there's no animation yet and accordingly collision bounds aren't interpolated either, but movement basically works. in a very... simple manner, I must say (re-uses existing tile entity, on both server and client); cleaned up delegate class a bit (the node.remove in block break should be redundant since we do this in the environment tile entity base class)
This commit is contained in:
parent
827344b543
commit
3324371ec6
@ -85,6 +85,18 @@ object Config {
|
||||
var canPlaceInAir = false
|
||||
var itemDamageRate = 0.05
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// robot.delays
|
||||
|
||||
var dropDelay = 0.1
|
||||
var moveDelay = 0.4
|
||||
var placeDelay = 0.3
|
||||
var suckDelay = 0.1
|
||||
var swingDelay = 0.4
|
||||
var turnDelay = 0.4
|
||||
var useDelay = 0.4
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def load(file: File) = {
|
||||
|
@ -27,6 +27,7 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case PacketType.ComputerStateResponse => onComputerStateResponse(p)
|
||||
case PacketType.PowerStateResponse => onPowerStateResponse(p)
|
||||
case PacketType.RedstoneStateResponse => onRedstoneStateResponse(p)
|
||||
case PacketType.RobotMove => onRobotMove(p)
|
||||
case PacketType.RobotSelectedSlotResponse => onRobotSelectedSlotResponse(p)
|
||||
case PacketType.RotatableStateResponse => onRotatableStateResponse(p)
|
||||
case PacketType.ScreenBufferResponse => onScreenBufferResponse(p)
|
||||
@ -78,6 +79,12 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotMove(p: PacketParser) =
|
||||
p.readTileEntity[Robot]() match {
|
||||
case Some(t) => t.move(p.readInt(), p.readInt(), p.readInt())
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotSelectedSlotResponse(p: PacketParser) =
|
||||
p.readTileEntity[Robot]() match {
|
||||
case Some(t) => t.selectedSlot = p.readInt()
|
||||
|
@ -10,6 +10,7 @@ object PacketType extends Enumeration {
|
||||
val RedstoneStateRequest = Value("RedstoneStateRequest")
|
||||
val RedstoneStateResponse = Value("RedstoneStateResponse")
|
||||
|
||||
val RobotMove = Value("RobotMove")
|
||||
val RobotSelectedSlotRequest = Value("RobotSelectedSlotRequest")
|
||||
val RobotSelectedSlotResponse = Value("RobotSelectedSlotResponse")
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package li.cil.oc.common.block
|
||||
|
||||
import li.cil.oc.common.tileentity
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.renderer.texture.IconRegister
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
|
@ -1,7 +1,6 @@
|
||||
package li.cil.oc.common.block
|
||||
|
||||
import java.util
|
||||
import li.cil.oc.api.network.Environment
|
||||
import li.cil.oc.common.tileentity.Rotatable
|
||||
import li.cil.oc.{Config, CreativeTab}
|
||||
import net.minecraft.block.Block
|
||||
@ -95,14 +94,7 @@ class Delegator[Child <: Delegate](id: Int, name: String) extends Block(id, Mate
|
||||
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int, metadata: Int) = {
|
||||
subBlock(metadata) match {
|
||||
case Some(subBlock) => {
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case environment: Environment if environment.node != null =>
|
||||
environment.node.remove()
|
||||
case _ => // Nothing special to do.
|
||||
}
|
||||
subBlock.breakBlock(world, x, y, z, blockId)
|
||||
}
|
||||
case Some(subBlock) => subBlock.breakBlock(world, x, y, z, blockId)
|
||||
case _ => // Invalid but avoid match error.
|
||||
}
|
||||
super.breakBlock(world, x, y, z, blockId, metadata)
|
||||
|
@ -10,7 +10,16 @@ import net.minecraftforge.common.ForgeDirection
|
||||
class Robot(val parent: SpecialDelegator) extends Computer with SpecialDelegate {
|
||||
val unlocalizedName = "Robot"
|
||||
|
||||
override def createTileEntity(world: World) = Some(new tileentity.Robot(world.isRemote))
|
||||
var moving = new ThreadLocal[Option[tileentity.Robot]] {
|
||||
override protected def initialValue = None
|
||||
}
|
||||
|
||||
override def createTileEntity(world: World) = {
|
||||
moving.get match {
|
||||
case Some(robot) => Some(robot)
|
||||
case _ => Some(new tileentity.Robot(world.isRemote))
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -47,4 +56,10 @@ class Robot(val parent: SpecialDelegator) extends Computer with SpecialDelegate
|
||||
}
|
||||
else false
|
||||
}
|
||||
|
||||
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int) {
|
||||
if (moving.get.isEmpty) {
|
||||
super.onBlockPreDestroy(world, x, y, z)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,21 @@
|
||||
package li.cil.oc.common.tileentity
|
||||
|
||||
import cpw.mods.fml.relauncher.{SideOnly, Side}
|
||||
import li.cil.oc.Config
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.driver.Slot
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||
import li.cil.oc.common
|
||||
import li.cil.oc.server.component
|
||||
import li.cil.oc.server.component.GraphicsCard
|
||||
import li.cil.oc.server.component.robot.Player
|
||||
import li.cil.oc.server.driver.Registry
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender, component}
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.{Blocks, Config, api, common}
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import scala.Some
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with PowerInformation {
|
||||
def this() = this(false)
|
||||
@ -42,43 +41,83 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
}
|
||||
else (null, null, null, null)
|
||||
|
||||
var selectedSlot = 0
|
||||
|
||||
private lazy val player_ = new Player(this)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def player(facing: ForgeDirection = facing, side: ForgeDirection = facing) = {
|
||||
assert(isServer)
|
||||
player_.updatePositionAndRotation(facing, side)
|
||||
player_
|
||||
}
|
||||
|
||||
var selectedSlot = 0
|
||||
def actualSlot(n: Int) = n + 3
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
def move(nx: Int, ny: Int, nz: Int) = {
|
||||
val (ox, oy, oz) = (x, y, z)
|
||||
// Setting this will make the tile entity created via the following call
|
||||
// to setBlock to re-use our "real" instance as the inner object, instead
|
||||
// of creating a new one.
|
||||
Blocks.robot.moving.set(Some(this))
|
||||
// Do *not* immediately send the change to clients to allow checking if it
|
||||
// worked before the client is notified so that we can use the same trick on
|
||||
// the client by sending a corresponding packet. This also saves us from
|
||||
// having to send the complete state again (e.g. screen buffer) each move.
|
||||
val blockId = world.getBlockId(nx, ny, nz)
|
||||
val metadata = world.getBlockMetadata(nx, ny, nz)
|
||||
val created = world.setBlock(nx, ny, nz, getBlockType.blockID, getBlockMetadata, 1)
|
||||
if (created) {
|
||||
assert(world.getBlockTileEntity(nx, ny, nz) == this)
|
||||
assert(x == nx && y == ny && z == nz)
|
||||
if (isServer) {
|
||||
ServerPacketSender.sendRobotMove(this, ox, oy, oz)
|
||||
world.setBlock(ox, oy, oz, 0, 0, 1)
|
||||
for (neighbor <- node.neighbors) {
|
||||
node.disconnect(neighbor)
|
||||
}
|
||||
api.Network.joinOrCreateNetwork(world, nx, ny, nz)
|
||||
}
|
||||
else {
|
||||
if (blockId > 0) {
|
||||
world.playAuxSFX(2001, nx, ny, nz, blockId + (metadata << 12))
|
||||
}
|
||||
world.markBlockForUpdate(x, y, z)
|
||||
world.setBlockToAir(ox, oy, oz)
|
||||
}
|
||||
assert(!isInvalid)
|
||||
}
|
||||
Blocks.robot.moving.set(None)
|
||||
if (created) {
|
||||
checkRedstoneInputChanged()
|
||||
}
|
||||
created
|
||||
}
|
||||
|
||||
def animateMove(direction: ForgeDirection, duration: Double) {}
|
||||
|
||||
def animateTurn(oldFacing: ForgeDirection, duration: Double) {}
|
||||
|
||||
override def installedMemory = 64 * 1024
|
||||
|
||||
def tier = 0
|
||||
|
||||
//def bounds =
|
||||
|
||||
override def installedMemory = 64 * 1024
|
||||
|
||||
def actualSlot(n: Int) = n + 3
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("start")
|
||||
def start(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(Boolean.box(computer.start()))
|
||||
result(computer.start())
|
||||
|
||||
@LuaCallback("stop")
|
||||
def stop(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(Boolean.box(computer.stop()))
|
||||
result(computer.stop())
|
||||
|
||||
@LuaCallback(value = "isRunning", direct = true)
|
||||
def isRunning(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(Boolean.box(computer.isRunning))
|
||||
|
||||
@LuaCallback(value = "isRobot", direct = true)
|
||||
def isRobot(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(java.lang.Boolean.TRUE)
|
||||
result(computer.isRunning)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -92,24 +131,27 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
}
|
||||
|
||||
override def validate() {
|
||||
super.validate()
|
||||
if (isServer) {
|
||||
items(0) match {
|
||||
case Some(item) => player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||
case _ =>
|
||||
if (Blocks.robot.moving.get.isEmpty) {
|
||||
super.validate()
|
||||
if (isServer) {
|
||||
items(0) match {
|
||||
case Some(item) => player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
else {
|
||||
ClientPacketSender.sendScreenBufferRequest(this)
|
||||
ClientPacketSender.sendRobotSelectedSlotRequest(this)
|
||||
}
|
||||
}
|
||||
else {
|
||||
ClientPacketSender.sendRotatableStateRequest(this)
|
||||
ClientPacketSender.sendScreenBufferRequest(this)
|
||||
ClientPacketSender.sendRobotSelectedSlotRequest(this)
|
||||
}
|
||||
}
|
||||
|
||||
override def invalidate() {
|
||||
super.invalidate()
|
||||
if (currentGui.isDefined) {
|
||||
Minecraft.getMinecraft.displayGuiScreen(null)
|
||||
if (Blocks.robot.moving.get.isEmpty) {
|
||||
super.invalidate()
|
||||
if (currentGui.isDefined) {
|
||||
Minecraft.getMinecraft.displayGuiScreen(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,16 +183,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onMessage(message: Message) {
|
||||
if (message.source.network == node.network) {
|
||||
//computer.node.network.sendToReachable(message.source, message.name, message.data: _*)
|
||||
}
|
||||
else {
|
||||
assert(message.source.network == computer.node.network)
|
||||
//node.network.sendToReachable(message.source, message.name, message.data: _*)
|
||||
}
|
||||
}
|
||||
|
||||
override def onConnect(node: Node) {
|
||||
if (node == this.node) {
|
||||
api.Network.joinNewNetwork(computer.node)
|
||||
|
@ -59,6 +59,22 @@ object PacketSender {
|
||||
}
|
||||
}
|
||||
|
||||
def sendRobotMove(t: Robot, ox: Int, oy: Int, oz: Int) {
|
||||
val pb = new PacketBuilder(PacketType.RobotMove)
|
||||
|
||||
// Custom pb.writeTileEntity() with fake coordinates (valid for the client).
|
||||
pb.writeInt(t.world.provider.dimensionId)
|
||||
pb.writeInt(ox)
|
||||
pb.writeInt(oy)
|
||||
pb.writeInt(oz)
|
||||
|
||||
pb.writeInt(t.x)
|
||||
pb.writeInt(t.y)
|
||||
pb.writeInt(t.z)
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendRobotSelectedSlotState(t: Robot, player: Option[Player] = None) {
|
||||
val pb = new PacketBuilder(PacketType.RobotSelectedSlotResponse)
|
||||
|
||||
|
@ -127,9 +127,12 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
val count = checkOptionalItemCount(args, 1)
|
||||
// TODO inventory, if available
|
||||
|
||||
result(robot.dropSlot(actualSlot(selectedSlot), count, facing))
|
||||
// This also works, but throws the items a little too far.
|
||||
// result(robot.player().dropPlayerItemWithRandomChoice(robot.decrStackSize(actualSlot(selectedSlot), count), false) != null)
|
||||
// Don't drop using the fake player because he throws too far.
|
||||
if (robot.dropSlot(actualSlot(selectedSlot), count, facing)) {
|
||||
context.pause(Config.dropDelay)
|
||||
result(true)
|
||||
}
|
||||
else result(false)
|
||||
}
|
||||
|
||||
@LuaCallback("place")
|
||||
@ -160,6 +163,9 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
if (stack.stackSize <= 0) {
|
||||
robot.setInventorySlotContents(player.robotInventory.selectedSlot, null)
|
||||
}
|
||||
if (what) {
|
||||
context.pause(Config.placeDelay)
|
||||
}
|
||||
result(what)
|
||||
}
|
||||
}
|
||||
@ -173,7 +179,10 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
val stack = entity.getEntityItem
|
||||
val size = stack.stackSize
|
||||
entity.onCollideWithPlayer(robot.player())
|
||||
if (stack.stackSize < size || entity.isDead) return result(true)
|
||||
if (stack.stackSize < size || entity.isDead) {
|
||||
context.pause(Config.suckDelay)
|
||||
return result(true)
|
||||
}
|
||||
}
|
||||
result(false)
|
||||
}
|
||||
@ -183,24 +192,8 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
@LuaCallback("detect")
|
||||
def detect(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
||||
val (bx, by, bz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ)
|
||||
val id = world.getBlockId(bx, by, bz)
|
||||
val block = Block.blocksList(id)
|
||||
if (id == 0 || block == null || block.isAirBlock(world, bx, by, bz)) {
|
||||
robot.player().closestLivingEntity(side) match {
|
||||
case Some(entity) => result(true, "entity")
|
||||
case _ => result(false, "air")
|
||||
}
|
||||
}
|
||||
else if (FluidRegistry.lookupFluidForBlock(block) != null || block.isInstanceOf[BlockFluid]) {
|
||||
result(false, "liquid")
|
||||
}
|
||||
else if (block.isBlockReplaceable(world, bx, by, bz)) {
|
||||
result(false, "replaceable")
|
||||
}
|
||||
else {
|
||||
result(true, "solid")
|
||||
}
|
||||
val (something, what) = blockContent(side)
|
||||
result(something, what)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -219,9 +212,13 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
val what = hit.typeOfHit match {
|
||||
case EnumMovingObjectType.ENTITY =>
|
||||
player.attackTargetEntityWithCurrentItem(hit.entityHit)
|
||||
context.pause(Config.swingDelay)
|
||||
result(true, "entity")
|
||||
case EnumMovingObjectType.TILE =>
|
||||
val broke = player.clickBlock(hit.blockX, hit.blockY, hit.blockZ, hit.sideHit)
|
||||
if (broke) {
|
||||
context.pause(Config.swingDelay)
|
||||
}
|
||||
result(broke, "block")
|
||||
}
|
||||
what
|
||||
@ -229,6 +226,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
player.closestLivingEntity(facing) match {
|
||||
case Some(entity) =>
|
||||
player.attackTargetEntityWithCurrentItem(entity)
|
||||
context.pause(Config.swingDelay)
|
||||
result(true, "entity")
|
||||
case _ =>
|
||||
result(false)
|
||||
@ -247,9 +245,15 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
val player = robot.player(facing, side)
|
||||
def activationResult(activationType: ActivationType.Value): Array[AnyRef] =
|
||||
activationType match {
|
||||
case ActivationType.BlockActivated => result(true, "block_activated")
|
||||
case ActivationType.ItemPlaced => result(true, "item_placed")
|
||||
case ActivationType.ItemUsed => result(true, "item_used")
|
||||
case ActivationType.BlockActivated =>
|
||||
context.pause(Config.useDelay)
|
||||
result(true, "block_activated")
|
||||
case ActivationType.ItemPlaced =>
|
||||
context.pause(Config.useDelay)
|
||||
result(true, "item_placed")
|
||||
case ActivationType.ItemUsed =>
|
||||
context.pause(Config.useDelay)
|
||||
result(true, "item_used")
|
||||
case _ => result(false)
|
||||
}
|
||||
player.setSneaking(sneaky)
|
||||
@ -269,7 +273,10 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
player.activateBlockOrUseItem(bx, by, bz, side.getOpposite.ordinal, hx, hy, hz)
|
||||
} else ActivationType.None) match {
|
||||
case ActivationType.None =>
|
||||
if (player.useEquippedItem()) result(true, "item_used")
|
||||
if (player.useEquippedItem()) {
|
||||
context.pause(Config.useDelay)
|
||||
result(true, "item_used")
|
||||
}
|
||||
else result(false)
|
||||
case activationType => activationResult(activationType)
|
||||
}
|
||||
@ -290,44 +297,60 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
}
|
||||
}
|
||||
|
||||
def pick(facing: ForgeDirection, side: ForgeDirection, range: Double) = {
|
||||
val (bx, by, bz) = (x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ)
|
||||
val (hx, hy, hz) = (0.5 + side.offsetX * range, 0.5 + side.offsetY * range, 0.5 + side.offsetZ * range)
|
||||
val origin = Vec3.createVectorHelper(x + 0.5, y + 0.5, z + 0.5)
|
||||
val target = Vec3.createVectorHelper(bx + hx, by + hy, bz + hz)
|
||||
world.clip(origin, target)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("move")
|
||||
def move(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
// Try to move in the specified direction.
|
||||
val side = checkSideForMovement(args, 0)
|
||||
null
|
||||
val direction = checkSideForMovement(args, 0)
|
||||
val (something, what) = blockContent(direction)
|
||||
if (something) {
|
||||
result(false, what)
|
||||
}
|
||||
else {
|
||||
val (nx, ny, nz) = (x + direction.offsetX, y + direction.offsetY, z + direction.offsetZ)
|
||||
if (robot.move(nx, ny, nz)) {
|
||||
robot.animateMove(direction, Config.moveDelay)
|
||||
context.pause(Config.moveDelay)
|
||||
result(true)
|
||||
}
|
||||
else {
|
||||
result(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@LuaCallback("turn")
|
||||
def turn(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val clockwise = args.checkBoolean(0)
|
||||
val oldFacing = robot.facing
|
||||
if (clockwise) robot.rotate(ForgeDirection.UP)
|
||||
else robot.rotate(ForgeDirection.DOWN)
|
||||
robot.animateTurn(oldFacing, 0.4)
|
||||
context.pause(Config.turnDelay)
|
||||
result(true)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def haveSameItemType(stackA: ItemStack, stackB: ItemStack) =
|
||||
stackA.itemID == stackB.itemID &&
|
||||
(!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage)
|
||||
|
||||
private def stackInSlot(slot: Int) = Option(robot.getStackInSlot(actualSlot(slot)))
|
||||
|
||||
private def clickParamsFromHit(hit: MovingObjectPosition) = {
|
||||
(hit.blockX, hit.blockY, hit.blockZ,
|
||||
(hit.hitVec.xCoord - hit.blockX).toFloat,
|
||||
(hit.hitVec.yCoord - hit.blockY).toFloat,
|
||||
(hit.hitVec.zCoord - hit.blockZ).toFloat)
|
||||
private def blockContent(side: ForgeDirection) = {
|
||||
val (bx, by, bz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ)
|
||||
val id = world.getBlockId(bx, by, bz)
|
||||
val block = Block.blocksList(id)
|
||||
if (id == 0 || block == null || block.isAirBlock(world, bx, by, bz)) {
|
||||
robot.player().closestLivingEntity(side) match {
|
||||
case Some(entity) => (true, "entity")
|
||||
case _ => (false, "air")
|
||||
}
|
||||
}
|
||||
else if (FluidRegistry.lookupFluidForBlock(block) != null || block.isInstanceOf[BlockFluid]) {
|
||||
(false, "liquid")
|
||||
}
|
||||
else if (block.isBlockReplaceable(world, bx, by, bz)) {
|
||||
(false, "replaceable")
|
||||
}
|
||||
else {
|
||||
(true, "solid")
|
||||
}
|
||||
}
|
||||
|
||||
private def clickParamsFromFacing(facing: ForgeDirection, side: ForgeDirection) = {
|
||||
@ -339,6 +362,29 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
0.5f - side.offsetZ * 0.5f)
|
||||
}
|
||||
|
||||
private def pick(facing: ForgeDirection, side: ForgeDirection, range: Double) = {
|
||||
val (bx, by, bz) = (x + facing.offsetX, y + facing.offsetY, z + facing.offsetZ)
|
||||
val (hx, hy, hz) = (0.5 + side.offsetX * range, 0.5 + side.offsetY * range, 0.5 + side.offsetZ * range)
|
||||
val origin = Vec3.createVectorHelper(x + 0.5, y + 0.5, z + 0.5)
|
||||
val target = Vec3.createVectorHelper(bx + hx, by + hy, bz + hz)
|
||||
world.clip(origin, target)
|
||||
}
|
||||
|
||||
private def clickParamsFromHit(hit: MovingObjectPosition) = {
|
||||
(hit.blockX, hit.blockY, hit.blockZ,
|
||||
(hit.hitVec.xCoord - hit.blockX).toFloat,
|
||||
(hit.hitVec.yCoord - hit.blockY).toFloat,
|
||||
(hit.hitVec.zCoord - hit.blockZ).toFloat)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def haveSameItemType(stackA: ItemStack, stackB: ItemStack) =
|
||||
stackA.itemID == stackB.itemID &&
|
||||
(!stackA.getHasSubtypes || stackA.getItemDamage == stackB.getItemDamage)
|
||||
|
||||
private def stackInSlot(slot: Int) = Option(robot.getStackInSlot(actualSlot(slot)))
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def checkOptionalItemCount(args: Arguments, n: Int) =
|
||||
@ -357,7 +403,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
|
||||
private def checkSideForAction(args: Arguments, n: Int) = checkSide(args, n, ForgeDirection.SOUTH, ForgeDirection.UP, ForgeDirection.DOWN)
|
||||
|
||||
private def checkSideForMovement(args: Arguments, n: Int) = checkSide(args, n, ForgeDirection.SOUTH, ForgeDirection.NORTH)
|
||||
private def checkSideForMovement(args: Arguments, n: Int) = checkSide(args, n, ForgeDirection.SOUTH, ForgeDirection.NORTH, ForgeDirection.UP, ForgeDirection.DOWN)
|
||||
|
||||
private def checkSide(args: Arguments, n: Int, allowed: ForgeDirection*) = {
|
||||
val side = args.checkInteger(n)
|
||||
|
@ -247,7 +247,7 @@ object Network extends api.detail.NetworkAPI {
|
||||
case Some(node: MutableNode) => {
|
||||
for (side <- ForgeDirection.VALID_DIRECTIONS) {
|
||||
getNetworkNode(world, x + side.offsetX, y + side.offsetY, z + side.offsetZ) match {
|
||||
case Some(neighbor) =>
|
||||
case Some(neighbor: MutableNode) if neighbor != node =>
|
||||
if (neighbor.network != null) {
|
||||
neighbor.connect(node)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user