blob: 40f6628035f784f793fc81cdd0910f1333ebc28a [file] [log] [blame] [raw]
package li.cil.oc.server.component
import java.util
import li.cil.oc.Constants
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
import li.cil.oc.api.driver.DeviceInfo.DeviceClass
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.DeviceInfo
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._
import li.cil.oc.api.prefab
import li.cil.oc.common.ToolDurabilityProviders
import li.cil.oc.common.tileentity
import li.cil.oc.server.PacketSender
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedArguments._
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.ForgeDirection
import scala.collection.convert.WrapAsJava._
class Robot(val agent: tileentity.Robot) extends prefab.ManagedEnvironment with Agent with DeviceInfo {
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("robot").
withConnector(Settings.get.bufferRobot).
create()
val romRobot = Option(api.FileSystem.asManagedEnvironment(api.FileSystem.
fromClass(OpenComputers.getClass, Settings.resourceDomain, "lua/component/robot"), "robot"))
private final lazy val deviceInfo = Map(
DeviceAttribute.Class -> DeviceClass.System,
DeviceAttribute.Description -> "Robot",
DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor,
DeviceAttribute.Product -> "Caterpillar",
DeviceAttribute.Capacity -> agent.getSizeInventory.toString
)
override def getDeviceInfo: util.Map[String, String] = deviceInfo
// ----------------------------------------------------------------------- //
override protected def checkSideForAction(args: Arguments, n: Int) = agent.toGlobal(args.checkSideForAction(n))
override def onWorldInteraction(context: Context, duration: Double): Unit = {
super.onWorldInteraction(context, duration)
agent.animateSwing(duration)
}
// ----------------------------------------------------------------------- //
@Callback(doc = "function():number -- Get the current color of the activity light as an integer encoded RGB value (0xRRGGBB).")
def getLightColor(context: Context, args: Arguments): Array[AnyRef] = result(agent.info.lightColor)
@Callback(doc = "function(value:number):number -- Set the color of the activity light to the specified integer encoded RGB value (0xRRGGBB).")
def setLightColor(context: Context, args: Arguments): Array[AnyRef] = {
agent.setLightColor(args.checkInteger(0))
context.pause(0.1)
result(agent.info.lightColor)
}
// ----------------------------------------------------------------------- //
@Callback(doc = "function():number -- Get the durability of the currently equipped tool.")
def durability(context: Context, args: Arguments): Array[AnyRef] = {
Option(agent.equipmentInventory.getStackInSlot(0)) match {
case Some(item) =>
ToolDurabilityProviders.getDurability(item) match {
case Some(durability) => result(durability)
case _ => result(Unit, "tool cannot be damaged")
}
case _ => result(Unit, "no tool equipped")
}
}
// ----------------------------------------------------------------------- //
@Callback(doc = "function(direction:number):boolean -- Move in the specified direction.")
def move(context: Context, args: Arguments): Array[AnyRef] = {
val direction = agent.toGlobal(args.checkSideForMovement(0))
if (agent.isAnimatingMove) {
// This shouldn't really happen due to delays being enforced, but just to
// be on the safe side...
result(Unit, "already moving")
}
else {
val (something, what) = blockContent(direction)
if (something) {
context.pause(0.4)
PacketSender.sendParticleEffect(BlockPosition(agent), "crit", 8, 0.25, Some(direction))
result(Unit, what)
}
else {
if (!node.tryChangeBuffer(-Settings.get.robotMoveCost)) {
result(Unit, "not enough energy")
}
else if (agent.move(direction)) {
context.pause(Settings.get.moveDelay)
result(true)
}
else {
node.changeBuffer(Settings.get.robotMoveCost)
context.pause(0.4)
PacketSender.sendParticleEffect(BlockPosition(agent), "crit", 8, 0.25, Some(direction))
result(Unit, "impossible move")
}
}
}
}
@Callback(doc = "function(clockwise:boolean):boolean -- Rotate in the specified direction.")
def turn(context: Context, args: Arguments): Array[AnyRef] = {
val clockwise = args.checkBoolean(0)
if (node.tryChangeBuffer(-Settings.get.robotTurnCost)) {
if (clockwise) agent.rotate(ForgeDirection.UP)
else agent.rotate(ForgeDirection.DOWN)
agent.animateTurn(clockwise, Settings.get.turnDelay)
context.pause(Settings.get.turnDelay)
result(true)
}
else {
result(Unit, "not enough energy")
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
romRobot.foreach(fs => {
fs.node.asInstanceOf[Component].setVisibility(Visibility.Network)
node.connect(fs.node)
})
}
}
override def onMessage(message: Message) {
super.onMessage(message)
if (message.name == "network.message" && message.source != agent.node) message.data match {
case Array(packet: Packet) => agent.proxy.node.sendToReachable(message.name, packet)
case _ =>
}
}
// ----------------------------------------------------------------------- //
override def load(nbt: NBTTagCompound) {
super.load(nbt)
romRobot.foreach(_.load(nbt.getCompoundTag("romRobot")))
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
romRobot.foreach(fs => nbt.setNewCompoundTag("romRobot", fs.save))
}
}