mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-12 16:57:32 -04:00
added setting to emulate CC turtle placing behavior (allow placing blocks in thin air, without any reference point - and no, the bot itself doesn't count!); properly ensuring placement is only possible on existing blocks for robot.place() (if the setting is false); robot Lua library wrapping the low level callbacks a bit
This commit is contained in:
parent
358328deb1
commit
ba1f66e989
@ -234,6 +234,7 @@ sandbox = {
|
||||
-- Start of non-standard stuff.
|
||||
|
||||
address = os.address,
|
||||
isRobot = os.isRobot,
|
||||
freeMemory = os.freeMemory,
|
||||
totalMemory = os.totalMemory,
|
||||
uptime = os.uptime,
|
||||
|
160
assets/opencomputers/lua/rom/lib/robot.lua
Normal file
160
assets/opencomputers/lua/rom/lib/robot.lua
Normal file
@ -0,0 +1,160 @@
|
||||
if not os.isRobot() then
|
||||
return
|
||||
end
|
||||
local function proxy()
|
||||
return component.computer
|
||||
end
|
||||
local robot = {}
|
||||
|
||||
|
||||
function robot.select(index)
|
||||
return proxy().select(index)
|
||||
end
|
||||
|
||||
function robot.count()
|
||||
return proxy().count()
|
||||
end
|
||||
|
||||
function robot.space()
|
||||
return proxy().select()
|
||||
end
|
||||
|
||||
function robot.compareTo(index)
|
||||
return proxy().compareTo(index)
|
||||
end
|
||||
|
||||
function robot.transferTo(index, count)
|
||||
return proxy().transferTo(index, count)
|
||||
end
|
||||
|
||||
function robot.compare()
|
||||
return proxy().compare(sides.front)
|
||||
end
|
||||
|
||||
function robot.compareUp()
|
||||
return proxy().compare(sides.up)
|
||||
end
|
||||
|
||||
function robot.compareDown()
|
||||
return proxy().compare(sides.down)
|
||||
end
|
||||
|
||||
function robot.drop(count)
|
||||
checkArg(1, count, "nil", "number")
|
||||
return proxy().drop(sides.front, count)
|
||||
end
|
||||
|
||||
function robot.dropUp(count)
|
||||
checkArg(1, count, "nil", "number")
|
||||
return proxy().drop(sides.up, count)
|
||||
end
|
||||
|
||||
function robot.dropDown(count)
|
||||
checkArg(1, count, "nil", "number")
|
||||
return proxy().drop(sides.down, count)
|
||||
end
|
||||
|
||||
function robot.place(side, sneaky)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().place(sides.front, side, sneaky ~= nil and sneaky ~= false)
|
||||
end
|
||||
|
||||
function robot.placeUp(side, sneaky)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().place(sides.up, side, sneaky ~= nil and sneaky ~= false)
|
||||
end
|
||||
|
||||
function robot.placeDown(side, sneaky)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().place(sides.down, side, sneaky ~= nil and sneaky ~= false)
|
||||
end
|
||||
|
||||
function robot.suck(count)
|
||||
checkArg(1, count, "nil", "number")
|
||||
return proxy().suck(sides.front, count)
|
||||
end
|
||||
|
||||
function robot.suckUp(count)
|
||||
checkArg(1, count, "nil", "number")
|
||||
return proxy().suck(sides.up, count)
|
||||
end
|
||||
|
||||
function robot.suckDown(count)
|
||||
checkArg(1, count, "nil", "number")
|
||||
return proxy().suck(sides.down, count)
|
||||
end
|
||||
|
||||
|
||||
function robot.detect()
|
||||
return proxy().detect(sides.front)
|
||||
end
|
||||
|
||||
function robot.detectUp()
|
||||
return proxy().detect(sides.up)
|
||||
end
|
||||
|
||||
function robot.detectDown()
|
||||
return proxy().detect(sides.down)
|
||||
end
|
||||
|
||||
|
||||
function robot.swing(side)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().swing(sides.front, side)
|
||||
end
|
||||
|
||||
function robot.swingUp(side)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().swing(sides.up, side)
|
||||
end
|
||||
|
||||
function robot.swingDown(side)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().swing(sides.down, side)
|
||||
end
|
||||
|
||||
function robot.use(side, sneaky)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().use(sides.front, side, sneaky ~= nil and sneaky ~= false)
|
||||
end
|
||||
|
||||
function robot.useUp(side, sneaky)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().use(sides.up, side, sneaky ~= nil and sneaky ~= false)
|
||||
end
|
||||
|
||||
function robot.useDown(side, sneaky)
|
||||
checkArg(1, side, "nil", "number")
|
||||
return proxy().use(sides.down, side, sneaky ~= nil and sneaky ~= false)
|
||||
end
|
||||
|
||||
function robot.durability()
|
||||
return proxy().durability()
|
||||
end
|
||||
|
||||
|
||||
function robot.forward()
|
||||
return proxy().move(sides.front)
|
||||
end
|
||||
|
||||
function robot.back()
|
||||
return proxy().move(sides.back)
|
||||
end
|
||||
|
||||
function robot.up()
|
||||
return proxy().move(sides.up)
|
||||
end
|
||||
|
||||
function robot.down()
|
||||
return proxy().move(sides.down)
|
||||
end
|
||||
|
||||
function robot.turnLeft()
|
||||
return proxy().turn(false)
|
||||
end
|
||||
|
||||
function robot.turnRight()
|
||||
return proxy().turn(true)
|
||||
end
|
||||
|
||||
_G.robot = robot
|
@ -82,6 +82,7 @@ object Config {
|
||||
|
||||
var allowActivateBlocks = true
|
||||
var canAttackPlayers = false
|
||||
var canPlaceInAir = false
|
||||
var itemDamageRate = 0.05
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -386,6 +387,16 @@ object Config {
|
||||
"players in the game.").
|
||||
getBoolean(canAttackPlayers)
|
||||
|
||||
canPlaceInAir = config.get("robot", "canPlaceInAir", canPlaceInAir, "" +
|
||||
"Whether robots may place blocks in thin air, i.e. without a reference\n" +
|
||||
"point (as is required for real players). Set this to true to emulate\n" +
|
||||
"ComputerCraft's Turtles' behavior. When left false robots have to\n" +
|
||||
"target an existing block face to place another block. For example,\n" +
|
||||
"if the robots stands on a perfect plain, you have to call\n" +
|
||||
"`robot.place(sides.down)` to place a block, instead of just\n" +
|
||||
"`robot.place()`, which will default to `robot.place(sides.front)`.").
|
||||
getBoolean(canPlaceInAir)
|
||||
|
||||
itemDamageRate = config.get("robot", "itemDamageRate", itemDamageRate, "" +
|
||||
"The rate at which items used as tools by robots take damage. A value\n" +
|
||||
"of one means that items lose durability as quickly as when they are\n" +
|
||||
|
@ -81,6 +81,8 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
|
||||
def lastError = message
|
||||
|
||||
def isRobot = false
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def isRunning = state.synchronized(state.top != Computer.State.Stopped)
|
||||
@ -168,10 +170,6 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
def isRunning(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(Boolean.box(isRunning))
|
||||
|
||||
@LuaCallback(value = "isRobot", direct = true)
|
||||
def isRobot(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(java.lang.Boolean.FALSE)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def update() {
|
||||
@ -734,27 +732,6 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
})
|
||||
lua.setField(-2, "uptime")
|
||||
|
||||
// Allow the system to read how much memory it uses and has available.
|
||||
lua.pushScalaFunction(lua => {
|
||||
lua.pushInteger(lua.getTotalMemory - kernelMemory)
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "totalMemory")
|
||||
|
||||
lua.pushScalaFunction(lua => {
|
||||
// This is *very* unlikely, but still: avoid this getting larger than
|
||||
// what we report as the total memory.
|
||||
lua.pushInteger(lua.getFreeMemory min (lua.getTotalMemory - kernelMemory))
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "freeMemory")
|
||||
|
||||
lua.pushScalaFunction(lua => {
|
||||
lua.pushBoolean(signal(lua.checkString(1), parseArguments(lua, 2): _*))
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "pushSignal")
|
||||
|
||||
// Allow the computer to figure out its own id in the component network.
|
||||
lua.pushScalaFunction(lua => {
|
||||
Option(node.address) match {
|
||||
@ -765,6 +742,34 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
|
||||
})
|
||||
lua.setField(-2, "address")
|
||||
|
||||
// Are we a robot? (No this is not a CAPTCHA.)
|
||||
lua.pushScalaFunction(lua => {
|
||||
lua.pushBoolean(isRobot)
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "isRobot")
|
||||
|
||||
lua.pushScalaFunction(lua => {
|
||||
// This is *very* unlikely, but still: avoid this getting larger than
|
||||
// what we report as the total memory.
|
||||
lua.pushInteger(lua.getFreeMemory min (lua.getTotalMemory - kernelMemory))
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "freeMemory")
|
||||
|
||||
// Allow the system to read how much memory it uses and has available.
|
||||
lua.pushScalaFunction(lua => {
|
||||
lua.pushInteger(lua.getTotalMemory - kernelMemory)
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "totalMemory")
|
||||
|
||||
lua.pushScalaFunction(lua => {
|
||||
lua.pushBoolean(signal(lua.checkString(1), parseArguments(lua, 2): _*))
|
||||
1
|
||||
})
|
||||
lua.setField(-2, "pushSignal")
|
||||
|
||||
// And it's ROM address.
|
||||
lua.pushScalaFunction(lua => {
|
||||
rom.foreach(rom => Option(rom.node.address) match {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package li.cil.oc.server.component
|
||||
|
||||
import li.cil.oc.Config
|
||||
import li.cil.oc.api.network.{LuaCallback, Arguments, Context}
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
@ -7,7 +8,7 @@ import li.cil.oc.util.ActivationType
|
||||
import net.minecraft.block.{BlockFluid, Block}
|
||||
import net.minecraft.entity.item.EntityItem
|
||||
import net.minecraft.item.{ItemStack, ItemBlock}
|
||||
import net.minecraft.util.{EnumMovingObjectType, Vec3}
|
||||
import net.minecraft.util.{MovingObjectPosition, EnumMovingObjectType, Vec3}
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import net.minecraftforge.fluids.FluidRegistry
|
||||
import scala.Some
|
||||
@ -28,8 +29,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def isRobot(context: Context, args: Arguments): Array[AnyRef] =
|
||||
Array(java.lang.Boolean.TRUE)
|
||||
override def isRobot = true
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@ -104,59 +104,6 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
})
|
||||
}
|
||||
|
||||
@LuaCallback("drop")
|
||||
def drop(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
||||
val count = checkOptionalItemCount(args, 1)
|
||||
// TODO inventory, if available
|
||||
|
||||
result(robot.dropSlot(actualSlot(selectedSlot), count, side))
|
||||
// This also works, but throws the items a little too far.
|
||||
// result(robot.player().dropPlayerItemWithRandomChoice(robot.decrStackSize(actualSlot(selectedSlot), count), false) != null)
|
||||
}
|
||||
|
||||
@LuaCallback("place")
|
||||
def place(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val lookSide = checkSideForAction(args, 0)
|
||||
val side = if (args.isInteger(1)) checkSide(args, 1) else lookSide
|
||||
if (side.getOpposite == lookSide) {
|
||||
throw new IllegalArgumentException("invalid side")
|
||||
}
|
||||
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
|
||||
val player = robot.player(lookSide)
|
||||
val stack = player.robotInventory.selectedItemStack
|
||||
if (stack == null || stack.stackSize == 0) {
|
||||
result(false)
|
||||
}
|
||||
else {
|
||||
player.setSneaking(sneaky)
|
||||
val (bx, by, bz) = (x + lookSide.offsetX, y + lookSide.offsetY, z + lookSide.offsetZ)
|
||||
val (hx, hy, hz) = (0.5f + side.offsetX * 0.5f, 0.5f + side.offsetY * 0.5f, 0.5f + side.offsetZ * 0.5f)
|
||||
val ok = player.placeBlock(player.robotInventory.selectedItemStack, bx, by, bz, side.getOpposite.ordinal, hx, hy, hz)
|
||||
player.setSneaking(false)
|
||||
if (stack.stackSize <= 0) {
|
||||
robot.setInventorySlotContents(player.robotInventory.selectedSlot, null)
|
||||
}
|
||||
result(ok)
|
||||
}
|
||||
}
|
||||
|
||||
@LuaCallback("suck")
|
||||
def suck(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
||||
val count = checkOptionalItemCount(args, 1)
|
||||
// TODO inventory, if available
|
||||
for (entity <- robot.player().entitiesOnSide[EntityItem](side) if !entity.isDead && entity.delayBeforeCanPickup <= 0) {
|
||||
val stack = entity.getEntityItem
|
||||
val size = stack.stackSize
|
||||
entity.onCollideWithPlayer(robot.player())
|
||||
if (stack.stackSize < size || entity.isDead) return result(true)
|
||||
}
|
||||
result(false)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("compare")
|
||||
def compare(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
||||
@ -174,6 +121,65 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
result(false)
|
||||
}
|
||||
|
||||
@LuaCallback("drop")
|
||||
def drop(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
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)
|
||||
}
|
||||
|
||||
@LuaCallback("place")
|
||||
def place(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val side = if (args.isInteger(1)) checkSide(args, 1) else facing
|
||||
if (side.getOpposite == facing) {
|
||||
throw new IllegalArgumentException("invalid side")
|
||||
}
|
||||
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
|
||||
val player = robot.player(facing)
|
||||
val stack = player.robotInventory.selectedItemStack
|
||||
if (stack == null || stack.stackSize == 0) {
|
||||
result(false, "nothing selected")
|
||||
}
|
||||
else {
|
||||
player.setSneaking(sneaky)
|
||||
val what = Option(pick(facing, side, 0.51)) match {
|
||||
case Some(hit) if hit.typeOfHit == EnumMovingObjectType.TILE =>
|
||||
val (bx, by, bz, hx, hy, hz) = clickParamsFromHit(hit)
|
||||
player.placeBlock(stack, bx, by, bz, hit.sideHit, hx, hy, hz)
|
||||
case None if Config.canPlaceInAir && player.closestLivingEntity(facing).isEmpty =>
|
||||
val (bx, by, bz, hx, hy, hz) = clickParamsFromFacing(facing, side)
|
||||
player.placeBlock(stack, bx, by, bz, side.getOpposite.ordinal, hx, hy, hz)
|
||||
case _ => false
|
||||
}
|
||||
player.setSneaking(false)
|
||||
if (stack.stackSize <= 0) {
|
||||
robot.setInventorySlotContents(player.robotInventory.selectedSlot, null)
|
||||
}
|
||||
result(what)
|
||||
}
|
||||
}
|
||||
|
||||
@LuaCallback("suck")
|
||||
def suck(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = checkOptionalItemCount(args, 1)
|
||||
// TODO inventory, if available
|
||||
for (entity <- robot.player().entitiesOnSide[EntityItem](facing) if !entity.isDead && entity.delayBeforeCanPickup <= 0) {
|
||||
val stack = entity.getEntityItem
|
||||
val size = stack.stackSize
|
||||
entity.onCollideWithPlayer(robot.player())
|
||||
if (stack.stackSize < size || entity.isDead) return result(true)
|
||||
}
|
||||
result(false)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("detect")
|
||||
def detect(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val side = checkSideForAction(args, 0)
|
||||
@ -207,11 +213,9 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
if (side.getOpposite == facing) {
|
||||
throw new IllegalArgumentException("invalid side")
|
||||
}
|
||||
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
|
||||
val player = robot.player(facing)
|
||||
Option(simulateClick(facing, side, 0.49)) match {
|
||||
Option(pick(facing, side, 0.49)) match {
|
||||
case Some(hit) =>
|
||||
player.setSneaking(sneaky)
|
||||
val what = hit.typeOfHit match {
|
||||
case EnumMovingObjectType.ENTITY =>
|
||||
player.attackTargetEntityWithCurrentItem(hit.entityHit)
|
||||
@ -220,7 +224,6 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
val broke = player.clickBlock(hit.blockX, hit.blockY, hit.blockZ, hit.sideHit)
|
||||
result(broke, "block")
|
||||
}
|
||||
player.setSneaking(false)
|
||||
what
|
||||
case _ =>
|
||||
player.closestLivingEntity(facing) match {
|
||||
@ -242,31 +245,37 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
}
|
||||
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
|
||||
val player = robot.player(facing)
|
||||
Option(simulateClick(facing, side, 0.51)) match {
|
||||
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 _ => result(false)
|
||||
}
|
||||
player.setSneaking(sneaky)
|
||||
val what = Option(pick(facing, side, 0.51)) match {
|
||||
case Some(hit) =>
|
||||
player.setSneaking(sneaky)
|
||||
val what = hit.typeOfHit match {
|
||||
hit.typeOfHit match {
|
||||
case EnumMovingObjectType.ENTITY =>
|
||||
// TODO Is there any practical use for this? Most of the stuff related to this is still 'obfuscated'...
|
||||
result(false, "entity")
|
||||
case EnumMovingObjectType.TILE =>
|
||||
val (hx, hy, hz) = (
|
||||
(hit.hitVec.xCoord - hit.blockX).toFloat,
|
||||
(hit.hitVec.yCoord - hit.blockY).toFloat,
|
||||
(hit.hitVec.zCoord - hit.blockZ).toFloat)
|
||||
player.activateBlockOrUseItem(hit.blockX, hit.blockY, hit.blockZ, hit.sideHit, hx, hy, hz) match {
|
||||
case ActivationType.BlockActivated => result(true, "block_activated")
|
||||
case ActivationType.ItemPlaced => result(true, "item_placed")
|
||||
case ActivationType.ItemUsed => result(true, "item_used")
|
||||
case _ => result(false)
|
||||
}
|
||||
val (bx, by, bz, hx, hy, hz) = clickParamsFromHit(hit)
|
||||
activationResult(player.activateBlockOrUseItem(bx, by, bz, hit.sideHit, hx, hy, hz))
|
||||
}
|
||||
player.setSneaking(false)
|
||||
what
|
||||
case _ =>
|
||||
if (player.useEquippedItem()) result(true, "item_used")
|
||||
else result(false)
|
||||
(if (Config.canPlaceInAir) {
|
||||
val (bx, by, bz, hx, hy, hz) = clickParamsFromFacing(facing, side)
|
||||
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")
|
||||
else result(false)
|
||||
case activationType => activationResult(activationType)
|
||||
}
|
||||
}
|
||||
player.setSneaking(false)
|
||||
what
|
||||
}
|
||||
|
||||
@LuaCallback("durability")
|
||||
@ -281,7 +290,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
}
|
||||
}
|
||||
|
||||
def simulateClick(facing: ForgeDirection, side: ForgeDirection, range: Double) = {
|
||||
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)
|
||||
@ -314,6 +323,22 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
|
||||
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 clickParamsFromFacing(facing: ForgeDirection, side: ForgeDirection) = {
|
||||
(x + facing.offsetX + side.offsetX,
|
||||
y + facing.offsetY + side.offsetY,
|
||||
z + facing.offsetZ + side.offsetZ,
|
||||
0.5f - side.offsetX * 0.5f,
|
||||
0.5f - side.offsetY * 0.5f,
|
||||
0.5f - side.offsetZ * 0.5f)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def checkOptionalItemCount(args: Arguments, n: Int) =
|
||||
|
@ -160,9 +160,7 @@ class RobotPlayer(val robot: Robot) extends FakePlayer(robot.world, "OpenCompute
|
||||
}
|
||||
|
||||
event.useBlock == Event.Result.DENY || {
|
||||
val direction = ForgeDirection.getOrientation(side).getOpposite
|
||||
val (onX, onY, onZ) = (x + direction.offsetX, y + direction.offsetY, z + direction.offsetZ)
|
||||
val result = stack.tryPlaceItemIntoWorld(this, world, onX, onY, onZ, side, hitX, hitY, hitZ)
|
||||
val result = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
if (stack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(this, stack)
|
||||
result
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user