mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 17:28:52 -04:00
wrapped robot tile entity in a proxy that gets placed into the world instead, which allows more natural cleanup in minecraft (meaning we don't have to use cheap tricks like manipulating the tile entity list directly); robot rendering and animations
This commit is contained in:
parent
920d485f18
commit
ca606686d3
BIN
assets/opencomputers/textures/blocks/robot.png
Normal file
BIN
assets/opencomputers/textures/blocks/robot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 648 B |
@ -16,7 +16,7 @@ object Blocks {
|
||||
var keyboard: Keyboard = null
|
||||
var powerDistributor: PowerDistributor = null
|
||||
var powerSupply: PowerConverter = null
|
||||
var robot: Robot = null
|
||||
var robotProxy: RobotProxy = null
|
||||
var robotAfterimage: RobotAfterimage = null
|
||||
var screen1, screen2, screen3: Screen = null
|
||||
|
||||
@ -35,7 +35,7 @@ object Blocks {
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Keyboard], Config.namespace + "keyboard")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Config.namespace + "power_converter")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Config.namespace + "power_distributor")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Robot], Config.namespace + "robot")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Config.namespace + "robot")
|
||||
GameRegistry.registerTileEntity(classOf[tileentity.Screen], Config.namespace + "screen")
|
||||
|
||||
// IMPORTANT: the multi block must come first, since the sub blocks will
|
||||
@ -53,7 +53,7 @@ object Blocks {
|
||||
screen3 = new Screen.Tier3(blockSimple)
|
||||
|
||||
capacitor = new Capacitor(blockSimple)
|
||||
robot = new Robot(blockSpecial)
|
||||
robotProxy = new RobotProxy(blockSpecial)
|
||||
robotAfterimage = new RobotAfterimage(blockSpecial)
|
||||
}
|
||||
}
|
@ -12,8 +12,8 @@ object GuiHandler extends CommonGuiHandler {
|
||||
new gui.Case(player.inventory, computer)
|
||||
case drive: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
||||
new gui.DiskDrive(player.inventory, drive)
|
||||
case robot: tileentity.Robot if id == GuiType.Robot.id =>
|
||||
new gui.Robot(player.inventory, robot)
|
||||
case proxy: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
||||
new gui.Robot(player.inventory, proxy.robot)
|
||||
case screen: tileentity.Screen if id == GuiType.Screen.id =>
|
||||
new gui.Screen(screen)
|
||||
case _ => null
|
||||
|
@ -27,6 +27,9 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case PacketType.ComputerStateResponse => onComputerStateResponse(p)
|
||||
case PacketType.PowerStateResponse => onPowerStateResponse(p)
|
||||
case PacketType.RedstoneStateResponse => onRedstoneStateResponse(p)
|
||||
case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p)
|
||||
case PacketType.RobotAnimateTurn => onRobotAnimateTurn(p)
|
||||
case PacketType.RobotEquippedItemChange => onRobotEquippedItemChange(p)
|
||||
case PacketType.RobotMove => onRobotMove(p)
|
||||
case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p)
|
||||
case PacketType.RobotStateResponse => onRobotStateResponse(p)
|
||||
@ -80,26 +83,46 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotAnimateSwing(p: PacketParser) =
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) => t.robot.setAnimateSwing(p.readInt())
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotAnimateTurn(p: PacketParser) =
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) => t.robot.setAnimateTurn(p.readByte(), p.readInt())
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotEquippedItemChange(p: PacketParser) =
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) => t.robot.equippedItem = Option(p.readItemStack())
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotMove(p: PacketParser) =
|
||||
p.readTileEntity[Robot]() match {
|
||||
case Some(t) => t.move(p.readDirection())
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) => t.robot.move(p.readDirection())
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotSelectedSlotChange(p: PacketParser) =
|
||||
p.readTileEntity[Robot]() match {
|
||||
case Some(t) => t.selectedSlot = p.readInt()
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) => t.robot.selectedSlot = p.readInt()
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotStateResponse(p: PacketParser) =
|
||||
p.readTileEntity[Robot]() match {
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) =>
|
||||
t.selectedSlot = p.readInt()
|
||||
t.animationTicksTotal = p.readInt()
|
||||
t.animationTicksLeft = p.readInt()
|
||||
t.moveDirection = p.readDirection()
|
||||
t.turnOldFacing = p.readDirection()
|
||||
t.robot.selectedSlot = p.readInt()
|
||||
t.robot.equippedItem = Option(p.readItemStack())
|
||||
t.robot.animationTicksTotal = p.readInt()
|
||||
t.robot.animationTicksLeft = p.readInt()
|
||||
t.robot.moveDirection = p.readDirection()
|
||||
t.robot.swingingTool = p.readBoolean()
|
||||
t.robot.turnAxis = p.readByte()
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import cpw.mods.fml.common.network.NetworkRegistry
|
||||
import cpw.mods.fml.common.registry.TickRegistry
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.client.renderer.tileentity.{CableRenderer, PowerDistributorRenderer, ScreenRenderer, CaseRenderer}
|
||||
import li.cil.oc.client.renderer.tileentity._
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.common.{Proxy => CommonProxy}
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
@ -20,6 +20,7 @@ private[oc] class Proxy extends CommonProxy {
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Cable], CableRenderer)
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Case], CaseRenderer)
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer)
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.RobotProxy], RobotRenderer)
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer)
|
||||
|
||||
TickRegistry.registerTickHandler(ScreenRenderer, Side.CLIENT)
|
||||
|
@ -125,7 +125,7 @@ object CableRenderer extends TileEntitySpecialRenderer {
|
||||
def renderTileEntityAt(t: TileEntity, x: Double, y: Double, z: Double, f: Float) {
|
||||
val cable = t.asInstanceOf[Cable]
|
||||
|
||||
val l = t.getWorldObj.getLightBrightnessForSkyBlocks(t.xCoord, t.yCoord, t.zCoord, 0)
|
||||
val l = t.getWorldObj.getLightBrightnessForSkyBlocks(cable.x, cable.y, cable.z, 0)
|
||||
val l1 = l % 65536
|
||||
val l2 = l / 65536
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2)
|
||||
|
180
li/cil/oc/client/renderer/tileentity/RobotRenderer.scala
Normal file
180
li/cil/oc/client/renderer/tileentity/RobotRenderer.scala
Normal file
@ -0,0 +1,180 @@
|
||||
package li.cil.oc.client.renderer.tileentity
|
||||
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.{OpenComputers, Config}
|
||||
import net.minecraft.client.renderer.entity.RenderManager
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||
import net.minecraft.client.renderer.{OpenGlHelper, Tessellator, GLAllocation}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import org.lwjgl.opengl.GL11
|
||||
import li.cil.oc.util.RenderState
|
||||
|
||||
object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
private val texture = new ResourceLocation(Config.resourceDomain, "textures/blocks/robot.png")
|
||||
|
||||
private val displayList = GLAllocation.generateDisplayLists(1)
|
||||
|
||||
private val gap = 1.0 / 28.0
|
||||
private val gt = 0.5 + gap
|
||||
private val gb = 0.5 - gap
|
||||
|
||||
def compileList() {
|
||||
val t = Tessellator.instance
|
||||
|
||||
val size = 0.4
|
||||
val l = 0.5 - size
|
||||
val h = 0.5 + size
|
||||
|
||||
GL11.glNewList(displayList, GL11.GL_COMPILE)
|
||||
|
||||
t.startDrawing(GL11.GL_TRIANGLE_FAN)
|
||||
t.addVertexWithUV(0.5, 1, 0.5, 0.25, 0.25)
|
||||
t.addVertexWithUV(l, gt, h, 0, 0.5)
|
||||
t.addVertexWithUV(h, gt, h, 0.5, 0.5)
|
||||
t.addVertexWithUV(h, gt, l, 0.5, 0)
|
||||
t.addVertexWithUV(l, gt, l, 0, 0)
|
||||
t.addVertexWithUV(l, gt, h, 0, 0.5)
|
||||
t.draw()
|
||||
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(l, gt, h, 0, 1)
|
||||
t.addVertexWithUV(l, gt, l, 0, 0.5)
|
||||
t.addVertexWithUV(h, gt, l, 0.5, 0.5)
|
||||
t.addVertexWithUV(h, gt, h, 0.5, 1)
|
||||
t.draw()
|
||||
|
||||
t.startDrawing(GL11.GL_TRIANGLE_FAN)
|
||||
t.addVertexWithUV(0.5, 0.03, 0.5, 0.75, 0.25)
|
||||
t.addVertexWithUV(l, gb, l, 0.5, 0)
|
||||
t.addVertexWithUV(h, gb, l, 1, 0)
|
||||
t.addVertexWithUV(h, gb, h, 1, 0.5)
|
||||
t.addVertexWithUV(l, gb, h, 0.5, 0.5)
|
||||
t.addVertexWithUV(l, gb, l, 0.5, 0)
|
||||
t.draw()
|
||||
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(l, gb, l, 0, 0.5)
|
||||
t.addVertexWithUV(l, gb, h, 0, 1)
|
||||
t.addVertexWithUV(h, gb, h, 0.5, 1)
|
||||
t.addVertexWithUV(h, gb, l, 0.5, 0.5)
|
||||
t.draw()
|
||||
|
||||
GL11.glEndList()
|
||||
}
|
||||
|
||||
compileList()
|
||||
|
||||
def renderTileEntityAt(entity: TileEntity, x: Double, y: Double, z: Double, f: Float) {
|
||||
val proxy = entity.asInstanceOf[tileentity.RobotProxy]
|
||||
val robot = proxy.robot
|
||||
val worldTime = entity.getWorldObj.getTotalWorldTime + f
|
||||
|
||||
{
|
||||
val l = robot.world.getLightBrightnessForSkyBlocks(robot.x, robot.y, robot.z, 0)
|
||||
val l1 = l % 65536
|
||||
val l2 = l / 65536
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2)
|
||||
}
|
||||
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
|
||||
|
||||
if (robot.isAnimatingMove) {
|
||||
val remaining = (robot.animationTicksLeft - f) / robot.animationTicksTotal.toDouble
|
||||
GL11.glTranslated(
|
||||
-robot.moveDirection.offsetX * remaining,
|
||||
-robot.moveDirection.offsetY * remaining,
|
||||
-robot.moveDirection.offsetZ * remaining)
|
||||
}
|
||||
|
||||
if (robot.isAnimatingTurn) {
|
||||
val remaining = (robot.animationTicksLeft - f) / robot.animationTicksTotal.toDouble
|
||||
GL11.glRotated(90 * remaining, 0, robot.turnAxis, 0)
|
||||
}
|
||||
|
||||
robot.yaw match {
|
||||
case ForgeDirection.WEST => GL11.glRotatef(-90, 0, 1, 0)
|
||||
case ForgeDirection.NORTH => GL11.glRotatef(180, 0, 1, 0)
|
||||
case ForgeDirection.EAST => GL11.glRotatef(90, 0, 1, 0)
|
||||
case _ => // No yaw.
|
||||
}
|
||||
|
||||
GL11.glTranslated(-0.5, -0.5, -0.5)
|
||||
|
||||
val timeJitter = robot.hashCode
|
||||
val hover =
|
||||
if (robot.isOn) Math.sin(timeJitter + worldTime / 20.0) * 0.03
|
||||
else -0.03
|
||||
GL11.glTranslated(0, hover, 0)
|
||||
|
||||
bindTexture(texture)
|
||||
GL11.glCallList(displayList)
|
||||
|
||||
val size = 0.3
|
||||
val l = 0.5 - size
|
||||
val h = 0.5 + size
|
||||
val vStep = 1.0 / 32.0
|
||||
|
||||
val strip = timeJitter + worldTime / 20.0
|
||||
val offsetV = ((strip - strip.toInt) * 16).toInt * vStep
|
||||
val (u0, u1, v0, v1) = {
|
||||
if (robot.isOn)
|
||||
(0.5, 1.0, 0.5 + offsetV, 0.5 + vStep + offsetV)
|
||||
else
|
||||
(0.25 - vStep, 0.25 + vStep, 0.75 - vStep, 0.75 + vStep)
|
||||
}
|
||||
|
||||
RenderState.disableLighting()
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(l, gt, l, u0, v0)
|
||||
t.addVertexWithUV(l, gb, l, u0, v1)
|
||||
t.addVertexWithUV(l, gb, h, u1, v1)
|
||||
t.addVertexWithUV(l, gt, h, u1, v0)
|
||||
|
||||
t.addVertexWithUV(l, gt, h, u0, v0)
|
||||
t.addVertexWithUV(l, gb, h, u0, v1)
|
||||
t.addVertexWithUV(h, gb, h, u1, v1)
|
||||
t.addVertexWithUV(h, gt, h, u1, v0)
|
||||
|
||||
t.addVertexWithUV(h, gt, h, u0, v0)
|
||||
t.addVertexWithUV(h, gb, h, u0, v1)
|
||||
t.addVertexWithUV(h, gb, l, u1, v1)
|
||||
t.addVertexWithUV(h, gt, l, u1, v0)
|
||||
|
||||
t.addVertexWithUV(h, gt, l, u0, v0)
|
||||
t.addVertexWithUV(h, gb, l, u0, v1)
|
||||
t.addVertexWithUV(l, gb, l, u1, v1)
|
||||
t.addVertexWithUV(l, gt, l, u1, v0)
|
||||
t.draw()
|
||||
RenderState.enableLighting()
|
||||
|
||||
robot.equippedItem match {
|
||||
case Some(stack) =>
|
||||
GL11.glDisable(GL11.GL_CULL_FACE)
|
||||
GL11.glTranslated(0.1, 0.25, 0.75)
|
||||
GL11.glScaled(0.4, 0.4, -0.4)
|
||||
if (robot.isAnimatingSwing) {
|
||||
val remaining = (robot.animationTicksLeft - f) / robot.animationTicksTotal.toDouble
|
||||
GL11.glRotated(Math.sin(remaining * Math.PI) * 45, -1, 0, 0)
|
||||
}
|
||||
GL11.glRotatef(-30, 1, 0, 0)
|
||||
GL11.glRotatef(40, 0, 1, 0)
|
||||
try {
|
||||
RenderManager.instance.itemRenderer.renderItem(robot.player(), stack, 0)
|
||||
}
|
||||
catch {
|
||||
case e: Throwable =>
|
||||
OpenComputers.log.log(Level.WARNING, "Failed rendering equipped item.", e)
|
||||
robot.equippedItem = None
|
||||
}
|
||||
GL11.glEnable(GL11.GL_CULL_FACE)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
}
|
@ -11,8 +11,8 @@ abstract class GuiHandler extends IGuiHandler {
|
||||
new container.Case(player.inventory, computer)
|
||||
case drive: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
||||
new container.DiskDrive(player.inventory, drive)
|
||||
case robot: tileentity.Robot if id == GuiType.Robot.id =>
|
||||
new container.Robot(player.inventory, robot)
|
||||
case proxy: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
||||
new container.Robot(player.inventory, proxy.robot)
|
||||
case _ => null
|
||||
}
|
||||
}
|
@ -5,7 +5,8 @@ import cpw.mods.fml.common.network.Player
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.DataOutputStream
|
||||
import li.cil.oc.common.tileentity.TileEntity
|
||||
import net.minecraft.nbt.NBTBase
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.{NBTTagCompound, NBTBase}
|
||||
import net.minecraft.network.packet.Packet250CustomPayload
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
@ -22,10 +23,14 @@ class PacketBuilder(packetType: PacketType.Value, private val stream: ByteArrayO
|
||||
|
||||
def writeDirection(d: ForgeDirection) = writeInt(d.ordinal)
|
||||
|
||||
def writeItemStack(stack: ItemStack) = writeNBT(stack.writeToNBT(new NBTTagCompound()))
|
||||
|
||||
def writeNBT(nbt: NBTBase) = NBTBase.writeNamedTag(nbt, this)
|
||||
|
||||
def sendToAllPlayers() = PacketDispatcher.sendPacketToAllPlayers(packet)
|
||||
|
||||
def sendToNearbyPlayers(t: TileEntity, range: Double = 64) = PacketDispatcher.sendPacketToAllAround(t.x, t.y, t.z, range, t.world.provider.dimensionId, packet)
|
||||
|
||||
def sendToPlayer(player: Player) = PacketDispatcher.sendPacketToPlayer(packet, player)
|
||||
|
||||
def sendToServer() = PacketDispatcher.sendPacketToServer(packet)
|
||||
|
@ -6,7 +6,8 @@ import java.io.ByteArrayInputStream
|
||||
import java.io.DataInputStream
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.OpenComputers
|
||||
import net.minecraft.nbt.NBTBase
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.{NBTTagCompound, NBTBase}
|
||||
import net.minecraft.network.INetworkManager
|
||||
import net.minecraft.network.packet.Packet250CustomPayload
|
||||
import net.minecraft.world.World
|
||||
@ -62,6 +63,8 @@ abstract class PacketHandler extends IPacketHandler {
|
||||
|
||||
def readDirection() = ForgeDirection.getOrientation(readInt())
|
||||
|
||||
def readItemStack() = ItemStack.loadItemStackFromNBT(readNBT().asInstanceOf[NBTTagCompound])
|
||||
|
||||
def readNBT() = NBTBase.readNamedTag(this)
|
||||
}
|
||||
|
||||
|
@ -1,37 +1,40 @@
|
||||
package li.cil.oc.common
|
||||
|
||||
object PacketType extends Enumeration {
|
||||
val ComputerStateRequest = Value("ComputerStateRequest")
|
||||
val ComputerStateResponse = Value("ComputerStateResponse")
|
||||
val ComputerStateRequest,
|
||||
ComputerStateResponse,
|
||||
|
||||
val PowerStateRequest = Value("PowerStateRequest")
|
||||
val PowerStateResponse = Value("PowerStateResponse")
|
||||
PowerStateRequest,
|
||||
PowerStateResponse,
|
||||
|
||||
val RedstoneStateRequest = Value("RedstoneStateRequest")
|
||||
val RedstoneStateResponse = Value("RedstoneStateResponse")
|
||||
RedstoneStateRequest,
|
||||
RedstoneStateResponse,
|
||||
|
||||
val RobotMove = Value("RobotMove")
|
||||
val RobotSelectedSlotChange = Value("RobotSelectedSlotChange")
|
||||
val RobotStateRequest = Value("RobotSelectedSlotRequest")
|
||||
val RobotStateResponse = Value("RobotStateResponse")
|
||||
RobotAnimateSwing,
|
||||
RobotAnimateTurn,
|
||||
RobotEquippedItemChange,
|
||||
RobotMove,
|
||||
RobotSelectedSlotChange,
|
||||
RobotStateRequest,
|
||||
RobotStateResponse,
|
||||
|
||||
val RotatableStateRequest = Value("RotatableStateRequest")
|
||||
val RotatableStateResponse = Value("RotatableStateResponse")
|
||||
RotatableStateRequest,
|
||||
RotatableStateResponse,
|
||||
|
||||
val ScreenBufferRequest = Value("ScreenBufferRequest")
|
||||
val ScreenBufferResponse = Value("ScreenBufferResponse")
|
||||
ScreenBufferRequest,
|
||||
ScreenBufferResponse,
|
||||
|
||||
val ScreenColorChange = Value("ScreenColorChange")
|
||||
val ScreenCopy = Value("ScreenCopy")
|
||||
val ScreenDepthChange = Value("ScreenDepthChange")
|
||||
val ScreenFill = Value("ScreenFill")
|
||||
val ScreenPowerChange = Value("ScreenPowerChange")
|
||||
val ScreenResolutionChange = Value("ScreenResolutionChange")
|
||||
val ScreenSet = Value("ScreenSet")
|
||||
ScreenColorChange,
|
||||
ScreenCopy,
|
||||
ScreenDepthChange,
|
||||
ScreenFill,
|
||||
ScreenPowerChange,
|
||||
ScreenResolutionChange,
|
||||
ScreenSet,
|
||||
|
||||
val KeyDown = Value("KeyDown")
|
||||
val KeyUp = Value("KeyUp")
|
||||
val Clipboard = Value("Clipboard")
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
Clipboard,
|
||||
|
||||
val Analyze = Value("Analyze")
|
||||
Analyze = Value
|
||||
}
|
@ -17,14 +17,6 @@ abstract class Computer extends Delegate {
|
||||
override def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) =
|
||||
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.Computer].output(side)
|
||||
|
||||
override def onBlockPreDestroy(world: World, x: Int, y: Int, z: Int) = {
|
||||
if (!world.isRemote) world.getBlockTileEntity(x, y, z) match {
|
||||
case computer: tileentity.Computer => computer.computer.stop()
|
||||
case _ => // Ignore.
|
||||
}
|
||||
super.onBlockPreDestroy(world, x, y, z)
|
||||
}
|
||||
|
||||
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer,
|
||||
side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||
if (!player.isSneaking) {
|
||||
|
@ -53,7 +53,7 @@ class RobotAfterimage(val parent: SpecialDelegator) extends SpecialDelegate {
|
||||
for (side <- ForgeDirection.VALID_DIRECTIONS) {
|
||||
val (rx, ry, rz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ)
|
||||
world.getBlockTileEntity(rx, ry, rz) match {
|
||||
case robot: tileentity.Robot if robot.isAnimatingMove && robot.moveDirection == side => return Some(robot)
|
||||
case proxy: tileentity.RobotProxy if proxy.robot.isAnimatingMove && proxy.robot.moveDirection == side => return Some(proxy.robot)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import net.minecraft.util.{AxisAlignedBB, Vec3}
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
class Robot(val parent: SpecialDelegator) extends Computer with SpecialDelegate {
|
||||
class RobotProxy(val parent: SpecialDelegator) extends Computer with SpecialDelegate {
|
||||
val unlocalizedName = "Robot"
|
||||
|
||||
var moving = new ThreadLocal[Option[tileentity.Robot]] {
|
||||
@ -16,8 +16,8 @@ class Robot(val parent: SpecialDelegator) extends Computer with SpecialDelegate
|
||||
|
||||
override def createTileEntity(world: World) = {
|
||||
moving.get match {
|
||||
case Some(robot) => Some(robot)
|
||||
case _ => Some(new tileentity.Robot(world.isRemote))
|
||||
case Some(robot) => Some(new tileentity.RobotProxy(robot))
|
||||
case _ => Some(new tileentity.RobotProxy(new tileentity.Robot(world.isRemote)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,14 +35,14 @@ class Robot(val parent: SpecialDelegator) extends Computer with SpecialDelegate
|
||||
|
||||
override def collisionRayTrace(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) = {
|
||||
val bounds = parent.getCollisionBoundingBoxFromPool(world, x, y, z)
|
||||
bounds.offset(x, y, z)
|
||||
if (bounds.isVecInside(origin)) null
|
||||
else super.collisionRayTrace(world, x, y, z, origin, direction)
|
||||
}
|
||||
|
||||
override def setBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int) {
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case robot: tileentity.Robot =>
|
||||
case proxy: tileentity.RobotProxy =>
|
||||
val robot = proxy.robot
|
||||
val bounds = AxisAlignedBB.getBoundingBox(0.1, 0.1, 0.1, 0.9, 0.9, 0.9)
|
||||
if (robot.isAnimatingMove) {
|
||||
val remaining = robot.animationTicksLeft.toDouble / robot.animationTicksTotal.toDouble
|
@ -9,11 +9,21 @@ import li.cil.oc.util.{PackedColor, Persistable}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
trait Buffer extends Environment with Persistable {
|
||||
val buffer = new component.Buffer(this)
|
||||
protected val buffer_ = new component.Buffer(this)
|
||||
|
||||
var bufferIsDirty = false
|
||||
protected var bufferIsDirty_ = false
|
||||
|
||||
var currentGui: Option[gui.Buffer] = None
|
||||
protected var currentGui_ = None: Option[gui.Buffer]
|
||||
|
||||
def buffer = buffer_
|
||||
|
||||
def bufferIsDirty = bufferIsDirty_
|
||||
|
||||
def bufferIsDirty_=(value: Boolean) = bufferIsDirty_ = value
|
||||
|
||||
def currentGui = currentGui_
|
||||
|
||||
def currentGui_=(value: Option[gui.Buffer]) = currentGui_ = value
|
||||
|
||||
def node: Node = buffer.node
|
||||
|
||||
|
@ -11,7 +11,9 @@ import net.minecraftforge.common.ForgeDirection
|
||||
import scala.Some
|
||||
|
||||
abstract class Computer(isRemote: Boolean) extends Environment with ComponentInventory with Rotatable with Redstone with Analyzable {
|
||||
val computer = if (isRemote) null else new component.Computer(this)
|
||||
protected val computer_ = if (isRemote) null else new component.Computer(this)
|
||||
|
||||
def computer = computer_
|
||||
|
||||
def node = if (isClient) null else computer.node
|
||||
|
||||
@ -52,7 +54,7 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
|
||||
|
||||
if (hasChanged) {
|
||||
hasChanged = false
|
||||
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this)
|
||||
world.markTileEntityChunkModified(x, y, z, this)
|
||||
}
|
||||
|
||||
if (isRunning != computer.isRunning) {
|
||||
|
@ -23,7 +23,7 @@ abstract class Environment extends net.minecraft.tileentity.TileEntity with Tile
|
||||
override def updateEntity() {
|
||||
super.updateEntity()
|
||||
if (node != null && node.network == null) {
|
||||
Network.joinOrCreateNetwork(worldObj, xCoord, yCoord, zCoord)
|
||||
Network.joinOrCreateNetwork(world, x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,39 +11,43 @@ 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.entity.player.EntityPlayer
|
||||
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)
|
||||
|
||||
var proxy: RobotProxy = _
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override val node = api.Network.newNode(this, Visibility.Network).
|
||||
withComponent("computer", Visibility.Neighbors).
|
||||
create()
|
||||
override def node = if (isClient) null else computer.node
|
||||
|
||||
override val buffer = new common.component.Buffer(this) {
|
||||
override val buffer_ = new common.component.Buffer(this) {
|
||||
override def maxResolution = (48, 14)
|
||||
}
|
||||
override val computer = if (isRemote) null else new component.Robot(this)
|
||||
override val computer_ = if (isRemote) null else new component.Robot(this)
|
||||
val (battery, distributor, gpu, keyboard) = if (isServer) {
|
||||
val battery = api.Network.newNode(this, Visibility.Network).withConnector(10000).create()
|
||||
val distributor = new component.PowerDistributor(this)
|
||||
val gpu = new GraphicsCard.Tier1 {
|
||||
override val maxResolution = (48, 14)
|
||||
}
|
||||
val keyboard = new component.Keyboard(this)
|
||||
val keyboard = new component.Keyboard(this) {
|
||||
override def isUseableByPlayer(p: EntityPlayer) =
|
||||
world.getBlockTileEntity(x, y, z) == proxy &&
|
||||
p.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
|
||||
}
|
||||
(battery, distributor, gpu, keyboard)
|
||||
}
|
||||
else (null, null, null, null)
|
||||
|
||||
var selectedSlot = 0
|
||||
|
||||
private lazy val player_ = new Player(this)
|
||||
var equippedItem: Option[ItemStack] = None
|
||||
|
||||
var animationTicksLeft = 0
|
||||
|
||||
@ -51,12 +55,15 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
|
||||
var moveDirection = ForgeDirection.UNKNOWN
|
||||
|
||||
var turnOldFacing = ForgeDirection.UNKNOWN
|
||||
var swingingTool = false
|
||||
|
||||
var turnAxis = 0
|
||||
|
||||
private lazy val player_ = new Player(this)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def player(facing: ForgeDirection = facing, side: ForgeDirection = facing) = {
|
||||
assert(isServer)
|
||||
player_.updatePositionAndRotation(facing, side)
|
||||
player_
|
||||
}
|
||||
@ -66,92 +73,107 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
def move(direction: ForgeDirection) = {
|
||||
val (ox, oy, oz) = (x, y, z)
|
||||
val (nx, ny, nz) = (x + direction.offsetX, y + direction.offsetY, z + direction.offsetZ)
|
||||
// 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)
|
||||
world.setBlock(ox, oy, oz, Blocks.robotAfterimage.parent.blockID, Blocks.robotAfterimage.blockId, 1)
|
||||
assert(Blocks.blockSpecial.subBlock(world, ox, oy, oz).exists(_ == Blocks.robotAfterimage))
|
||||
if (isServer) {
|
||||
ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction)
|
||||
for (neighbor <- node.neighbors) {
|
||||
node.disconnect(neighbor)
|
||||
try {
|
||||
// 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.robotProxy.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 created = world.setBlock(nx, ny, nz, Blocks.robotProxy.parent.blockID, Blocks.robotProxy.blockId, 1)
|
||||
if (created) {
|
||||
assert(world.getBlockTileEntity(nx, ny, nz) == proxy)
|
||||
assert(x == nx && y == ny && z == nz)
|
||||
world.setBlock(ox, oy, oz, Blocks.robotAfterimage.parent.blockID, Blocks.robotAfterimage.blockId, 1)
|
||||
assert(Blocks.blockSpecial.subBlock(world, ox, oy, oz).exists(_ == Blocks.robotAfterimage))
|
||||
if (isServer) {
|
||||
ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction)
|
||||
}
|
||||
api.Network.joinOrCreateNetwork(world, nx, ny, nz)
|
||||
}
|
||||
else {
|
||||
// On the client this is called from the packet handler code, leading
|
||||
// to the entity being added directly to the list of loaded tile
|
||||
// entities, without any additional checks - so we get a duplicate.
|
||||
val duplicate = world.loadedTileEntityList.remove(world.loadedTileEntityList.size - 1)
|
||||
assert(duplicate == this)
|
||||
if (blockId > 0) {
|
||||
world.playAuxSFX(2001, nx, ny, nz, blockId + (metadata << 12))
|
||||
else {
|
||||
// If we broke some replaceable block (like grass) play its break sound.
|
||||
if (blockId > 0) {
|
||||
world.playAuxSFX(2001, nx, ny, nz, blockId + (metadata << 12))
|
||||
}
|
||||
world.markBlockForRenderUpdate(ox, oy, oz)
|
||||
world.markBlockForRenderUpdate(nx, ny, nz)
|
||||
}
|
||||
world.markBlockForUpdate(ox, oy, oz)
|
||||
world.markBlockForUpdate(nx, ny, nz)
|
||||
assert(!isInvalid)
|
||||
}
|
||||
assert(!isInvalid)
|
||||
if (created) {
|
||||
// Here instead of Lua callback so that it gets triggered on client.
|
||||
animateMove(direction, Config.moveDelay)
|
||||
checkRedstoneInputChanged()
|
||||
}
|
||||
created
|
||||
}
|
||||
Blocks.robot.moving.set(None)
|
||||
if (created) {
|
||||
animateMove(direction, Config.moveDelay)
|
||||
checkRedstoneInputChanged()
|
||||
finally {
|
||||
Blocks.robotProxy.moving.set(None)
|
||||
}
|
||||
created
|
||||
}
|
||||
|
||||
def isAnimatingMove = animationTicksLeft > 0 && moveDirection != ForgeDirection.UNKNOWN
|
||||
|
||||
def isAnimatingTurn = animationTicksLeft > 0 && turnOldFacing != ForgeDirection.UNKNOWN
|
||||
def isAnimatingSwing = animationTicksLeft > 0 && swingingTool
|
||||
|
||||
def animateMove(direction: ForgeDirection, duration: Double) {
|
||||
animationTicksTotal = (duration * 20).toInt
|
||||
animationTicksLeft = animationTicksTotal
|
||||
moveDirection = direction
|
||||
turnOldFacing = ForgeDirection.UNKNOWN
|
||||
def isAnimatingTurn = animationTicksLeft > 0 && turnAxis != 0
|
||||
|
||||
def animateMove(direction: ForgeDirection, duration: Double) =
|
||||
setAnimateMove(direction, (duration * 20).toInt)
|
||||
|
||||
def animateSwing(duration: Double) = {
|
||||
setAnimateSwing((duration * 20).toInt)
|
||||
ServerPacketSender.sendRobotAnimateSwing(this)
|
||||
}
|
||||
|
||||
def animateTurn(oldFacing: ForgeDirection, duration: Double) {
|
||||
animationTicksTotal = (duration * 20).toInt
|
||||
def animateTurn(clockwise: Boolean, duration: Double) = {
|
||||
setAnimateTurn(if (clockwise) 1 else -1, (duration * 20).toInt)
|
||||
ServerPacketSender.sendRobotAnimateTurn(this)
|
||||
}
|
||||
|
||||
def setAnimateMove(direction: ForgeDirection, ticks: Int) {
|
||||
animationTicksTotal = ticks
|
||||
prepareForAnimation()
|
||||
moveDirection = direction
|
||||
}
|
||||
|
||||
def setAnimateSwing(ticks: Int) {
|
||||
animationTicksTotal = ticks
|
||||
prepareForAnimation()
|
||||
swingingTool = true
|
||||
}
|
||||
|
||||
def setAnimateTurn(axis: Int, ticks: Int) {
|
||||
animationTicksTotal = ticks
|
||||
prepareForAnimation()
|
||||
turnAxis = axis
|
||||
}
|
||||
|
||||
private def prepareForAnimation() {
|
||||
animationTicksLeft = animationTicksTotal
|
||||
moveDirection = ForgeDirection.UNKNOWN
|
||||
turnOldFacing = oldFacing
|
||||
swingingTool = false
|
||||
turnAxis = 0
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def getRenderBoundingBox =
|
||||
getBlockType.getCollisionBoundingBoxFromPool(world, x, y, z).expand(0.5, 0.5, 0.5)
|
||||
|
||||
override def installedMemory = 64 * 1024
|
||||
|
||||
def tier = 0
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("start")
|
||||
def start(context: Context, args: Arguments): Array[AnyRef] =
|
||||
result(computer.start())
|
||||
|
||||
@LuaCallback("stop")
|
||||
def stop(context: Context, args: Arguments): Array[AnyRef] =
|
||||
result(computer.stop())
|
||||
|
||||
@LuaCallback(value = "isRunning", direct = true)
|
||||
def isRunning(context: Context, args: Arguments): Array[AnyRef] =
|
||||
result(computer.isRunning)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def updateEntity() {
|
||||
if (node != null && node.network == null) {
|
||||
api.Network.joinNewNetwork(computer.node)
|
||||
}
|
||||
if (animationTicksLeft > 0) {
|
||||
animationTicksLeft -= 1
|
||||
if (animationTicksLeft == 0) {
|
||||
@ -173,34 +195,29 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
}
|
||||
|
||||
override def validate() {
|
||||
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.sendRobotStateRequest(this)
|
||||
super.validate()
|
||||
if (isServer) {
|
||||
items(0) match {
|
||||
case Some(item) => player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
else {
|
||||
ClientPacketSender.sendScreenBufferRequest(this)
|
||||
ClientPacketSender.sendRobotStateRequest(this)
|
||||
}
|
||||
}
|
||||
|
||||
override def invalidate() {
|
||||
if (Blocks.robot.moving.get.isEmpty) {
|
||||
super.invalidate()
|
||||
if (currentGui.isDefined) {
|
||||
Minecraft.getMinecraft.displayGuiScreen(null)
|
||||
}
|
||||
super.invalidate()
|
||||
if (currentGui.isDefined) {
|
||||
Minecraft.getMinecraft.displayGuiScreen(null)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def readFromNBT(nbt: NBTTagCompound) {
|
||||
super.readFromNBT(nbt)
|
||||
if (isServer) {
|
||||
battery.load(nbt.getCompoundTag(Config.namespace + "battery"))
|
||||
buffer.load(nbt.getCompoundTag(Config.namespace + "buffer"))
|
||||
@ -211,12 +228,14 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
selectedSlot = nbt.getInteger(Config.namespace + "selectedSlot")
|
||||
animationTicksTotal = nbt.getInteger(Config.namespace + "animationTicksTotal")
|
||||
animationTicksLeft = nbt.getInteger(Config.namespace + "animationTicksLeft")
|
||||
moveDirection = ForgeDirection.getOrientation(nbt.getInteger(Config.namespace + "moveDirection"))
|
||||
turnOldFacing = ForgeDirection.getOrientation(nbt.getInteger(Config.namespace + "turnOldFacing"))
|
||||
if (animationTicksLeft > 0) {
|
||||
moveDirection = ForgeDirection.getOrientation(nbt.getByte(Config.namespace + "moveDirection"))
|
||||
swingingTool = nbt.getBoolean(Config.namespace + "swingingTool")
|
||||
turnAxis = nbt.getByte(Config.namespace + "turnAxis")
|
||||
}
|
||||
}
|
||||
|
||||
override def writeToNBT(nbt: NBTTagCompound) {
|
||||
super.writeToNBT(nbt)
|
||||
if (isServer) {
|
||||
nbt.setNewCompoundTag(Config.namespace + "battery", battery.save)
|
||||
nbt.setNewCompoundTag(Config.namespace + "buffer", buffer.save)
|
||||
@ -225,27 +244,26 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
nbt.setNewCompoundTag(Config.namespace + "keyboard", keyboard.save)
|
||||
}
|
||||
nbt.setInteger(Config.namespace + "selectedSlot", selectedSlot)
|
||||
if (isAnimatingMove || isAnimatingTurn) {
|
||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||
nbt.setInteger(Config.namespace + "animationTicksTotal", animationTicksTotal)
|
||||
nbt.setInteger(Config.namespace + "animationTicksLeft", animationTicksLeft)
|
||||
nbt.setInteger(Config.namespace + "moveDirection", moveDirection.ordinal)
|
||||
nbt.setInteger(Config.namespace + "turnOldFacing", turnOldFacing.ordinal)
|
||||
nbt.setByte(Config.namespace + "moveDirection", moveDirection.ordinal.toByte)
|
||||
nbt.setBoolean(Config.namespace + "swingingTool", swingingTool)
|
||||
nbt.setByte(Config.namespace + "turnAxis", turnAxis.toByte)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onConnect(node: Node) {
|
||||
super.onConnect(node)
|
||||
if (node == this.node) {
|
||||
api.Network.joinNewNetwork(computer.node)
|
||||
|
||||
computer.node.connect(buffer.node)
|
||||
computer.node.connect(distributor.node)
|
||||
computer.node.connect(gpu.node)
|
||||
distributor.node.connect(battery)
|
||||
buffer.node.connect(keyboard.node)
|
||||
}
|
||||
super.onConnect(node)
|
||||
}
|
||||
|
||||
override def onDisconnect(node: Node) {
|
||||
@ -280,6 +298,12 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
|
||||
override def getInventoryStackLimit = 64
|
||||
|
||||
override def isUseableByPlayer(player: EntityPlayer) =
|
||||
world.getBlockTileEntity(x, y, z) match {
|
||||
case t: RobotProxy if t == proxy => player.getDistanceSq(x + 0.5, y + 0.5, z + 0.5) <= 64
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def isItemValidForSlot(slot: Int, item: ItemStack) = (slot, Registry.driverFor(item)) match {
|
||||
case (0, _) => true // Allow anything in the tool slot.
|
||||
case (1, Some(driver)) => driver.slot(item) == Slot.Card
|
||||
@ -288,19 +312,38 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer with Power
|
||||
case _ => false // Invalid slot.
|
||||
}
|
||||
|
||||
override def onInventoryChanged() {
|
||||
super.onInventoryChanged()
|
||||
if (isServer) {
|
||||
computer.signal("inventory_changed")
|
||||
}
|
||||
}
|
||||
|
||||
override protected def onItemRemoved(slot: Int, item: ItemStack) {
|
||||
super.onItemRemoved(slot, item)
|
||||
if (slot == 0) {
|
||||
player_.getAttributeMap.removeAttributeModifiers(item.getAttributeModifiers)
|
||||
if (isServer) {
|
||||
if (slot == 0) {
|
||||
player_.getAttributeMap.removeAttributeModifiers(item.getAttributeModifiers)
|
||||
ServerPacketSender.sendRobotEquippedItemChange(this)
|
||||
}
|
||||
else if (slot >= actualSlot(0)) {
|
||||
computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override protected def onItemAdded(slot: Int, item: ItemStack) {
|
||||
if (slot == 0) {
|
||||
player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||
}
|
||||
else if (slot == 1 || slot == 2) {
|
||||
super.onItemAdded(slot, item)
|
||||
if (isServer) {
|
||||
if (slot == 0) {
|
||||
player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||
ServerPacketSender.sendRobotEquippedItemChange(this)
|
||||
}
|
||||
else if (slot == 1 || slot == 2) {
|
||||
super.onItemAdded(slot, item)
|
||||
}
|
||||
else if (slot >= actualSlot(0)) {
|
||||
computer.signal("inventory_changed", Int.box(slot - actualSlot(0) + 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
229
li/cil/oc/common/tileentity/RobotProxy.scala
Normal file
229
li/cil/oc/common/tileentity/RobotProxy.scala
Normal file
@ -0,0 +1,229 @@
|
||||
package li.cil.oc.common.tileentity
|
||||
|
||||
import cpw.mods.fml.common.Optional
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.client.gui
|
||||
import mods.immibis.redlogic.api.wiring.IWire
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
|
||||
class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with Buffer with PowerInformation {
|
||||
def this() = this(new Robot(false))
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@LuaCallback("start")
|
||||
def start(context: Context, args: Arguments): Array[AnyRef] =
|
||||
result(computer.start())
|
||||
|
||||
@LuaCallback("stop")
|
||||
def stop(context: Context, args: Arguments): Array[AnyRef] =
|
||||
result(computer.stop())
|
||||
|
||||
@LuaCallback(value = "isRunning", direct = true)
|
||||
def isRunning(context: Context, args: Arguments): Array[AnyRef] =
|
||||
result(computer.isRunning)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = robot.onAnalyze(stats, player, side, hitX, hitY, hitZ)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override val node = api.Network.newNode(this, Visibility.Network).
|
||||
withComponent("computer", Visibility.Neighbors).
|
||||
create()
|
||||
|
||||
override def isClient = robot.isClient
|
||||
|
||||
override def isServer = robot.isServer
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def isOutputEnabled = robot.isOutputEnabled
|
||||
|
||||
override def isOutputEnabled_=(value: Boolean) = robot.isOutputEnabled_=(value)
|
||||
|
||||
override def input(side: ForgeDirection) = robot.input(side)
|
||||
|
||||
override def output(side: ForgeDirection) = robot.output(side)
|
||||
|
||||
override def output(side: ForgeDirection, value: Short) = robot.output(side, value)
|
||||
|
||||
override def bundledInput(side: ForgeDirection, color: Int) = robot.bundledInput(side, color)
|
||||
|
||||
override def bundledOutput(side: ForgeDirection, color: Int) = robot.bundledOutput(side, color)
|
||||
|
||||
override def bundledOutput(side: ForgeDirection, color: Int, value: Short) = robot.bundledOutput(side, color, value)
|
||||
|
||||
override def checkRedstoneInputChanged() = robot.checkRedstoneInputChanged()
|
||||
|
||||
override def updateRedstoneInput() = robot.updateRedstoneInput()
|
||||
|
||||
@Optional.Method(modid = "RedLogic")
|
||||
override def connects(wire: IWire, blockFace: Int, fromDirection: Int) = robot.connects(wire, blockFace, fromDirection)
|
||||
|
||||
@Optional.Method(modid = "RedLogic")
|
||||
override def connectsAroundCorner(wire: IWire, blockFace: Int, fromDirection: Int) = robot.connectsAroundCorner(wire, blockFace, fromDirection)
|
||||
|
||||
@Optional.Method(modid = "RedLogic")
|
||||
override def getBundledCableStrength(blockFace: Int, toDirection: Int) = robot.getBundledCableStrength(blockFace, toDirection)
|
||||
|
||||
@Optional.Method(modid = "RedLogic")
|
||||
override def getEmittedSignalStrength(blockFace: Int, toDirection: Int) = robot.getEmittedSignalStrength(blockFace, toDirection)
|
||||
|
||||
@Optional.Method(modid = "RedLogic")
|
||||
override def onBundledInputChanged() = robot.onBundledInputChanged()
|
||||
|
||||
@Optional.Method(modid = "RedLogic")
|
||||
override def onRedstoneInputChanged() = robot.onRedstoneInputChanged()
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def pitch = robot.pitch
|
||||
|
||||
override def pitch_=(value: ForgeDirection) = robot.pitch_=(value)
|
||||
|
||||
override def yaw = robot.yaw
|
||||
|
||||
override def yaw_=(value: ForgeDirection) = robot.yaw_=(value)
|
||||
|
||||
override def setFromEntityPitchAndYaw(entity: Entity) = robot.setFromEntityPitchAndYaw(entity)
|
||||
|
||||
override def setFromFacing(value: ForgeDirection) = robot.setFromFacing(value)
|
||||
|
||||
override def invertRotation() = robot.invertRotation()
|
||||
|
||||
override def facing = robot.facing
|
||||
|
||||
override def rotate(axis: ForgeDirection) = robot.rotate(axis)
|
||||
|
||||
override def toLocal(value: ForgeDirection) = robot.toLocal(value)
|
||||
|
||||
override def toGlobal(value: ForgeDirection) = robot.toGlobal(value)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def getStackInSlot(i: Int) = robot.getStackInSlot(i)
|
||||
|
||||
override def decrStackSize(slot: Int, amount: Int) = robot.decrStackSize(slot, amount)
|
||||
|
||||
override def setInventorySlotContents(slot: Int, item: ItemStack) = robot.setInventorySlotContents(slot, item)
|
||||
|
||||
override def getStackInSlotOnClosing(slot: Int) = robot.getStackInSlotOnClosing(slot)
|
||||
|
||||
override def openChest() = robot.openChest()
|
||||
|
||||
override def closeChest() = robot.closeChest()
|
||||
|
||||
override def isInvNameLocalized = robot.isInvNameLocalized
|
||||
|
||||
override def isUseableByPlayer(player: EntityPlayer) = robot.isUseableByPlayer(player)
|
||||
|
||||
override def dropSlot(slot: Int, count: Int, direction: ForgeDirection) = robot.dropSlot(slot, count, direction)
|
||||
|
||||
override def dropAllSlots() = robot.dropAllSlots()
|
||||
|
||||
override def getInventoryStackLimit = robot.getInventoryStackLimit
|
||||
|
||||
override def installedMemory = robot.installedMemory
|
||||
|
||||
def getInvName = robot.getInvName
|
||||
|
||||
def getSizeInventory = robot.getSizeInventory
|
||||
|
||||
def isItemValidForSlot(slot: Int, stack: ItemStack) = robot.isItemValidForSlot(slot, stack)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def canUpdate = robot.canUpdate
|
||||
|
||||
override def updateEntity() = robot.updateEntity()
|
||||
|
||||
override def validate() {
|
||||
super.validate()
|
||||
val firstProxy = robot.proxy == null
|
||||
robot.proxy = this
|
||||
robot.worldObj = worldObj
|
||||
robot.xCoord = xCoord
|
||||
robot.yCoord = yCoord
|
||||
robot.zCoord = zCoord
|
||||
if (firstProxy) {
|
||||
robot.validate()
|
||||
}
|
||||
}
|
||||
|
||||
override def invalidate() {
|
||||
super.invalidate()
|
||||
if (robot.proxy == this) {
|
||||
robot.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
override def onChunkUnload() {
|
||||
super.onChunkUnload()
|
||||
if (robot.proxy == this) {
|
||||
robot.onChunkUnload()
|
||||
}
|
||||
}
|
||||
|
||||
override def readFromNBT(nbt: NBTTagCompound) {
|
||||
super.readFromNBT(nbt)
|
||||
robot.readFromNBT(nbt)
|
||||
}
|
||||
|
||||
override def writeToNBT(nbt: NBTTagCompound) {
|
||||
super.writeToNBT(nbt)
|
||||
robot.writeToNBT(nbt)
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) = robot.save(nbt)
|
||||
|
||||
override def load(nbt: NBTTagCompound) = robot.load(nbt)
|
||||
|
||||
override def getMaxRenderDistanceSquared = robot.getMaxRenderDistanceSquared
|
||||
|
||||
override def getRenderBoundingBox = robot.getRenderBoundingBox
|
||||
|
||||
override def shouldRenderInPass(pass: Int) = robot.shouldRenderInPass(pass)
|
||||
|
||||
override def onInventoryChanged() = robot.onInventoryChanged()
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onMessage(message: Message) = robot.onMessage(message)
|
||||
|
||||
override def onConnect(node: Node) = robot.onConnect(node)
|
||||
|
||||
override def onDisconnect(node: Node) = robot.onDisconnect(node)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def computer = robot.computer
|
||||
|
||||
override def isOn = robot.isOn
|
||||
|
||||
override def isOn_=(value: Boolean) = robot.isOn_=(value)
|
||||
|
||||
override def markAsChanged() = robot.markAsChanged()
|
||||
|
||||
override def hasRedstoneCard = robot.hasRedstoneCard
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def buffer = robot.buffer
|
||||
|
||||
override def bufferIsDirty = robot.bufferIsDirty
|
||||
|
||||
override def bufferIsDirty_=(value: Boolean) = robot.bufferIsDirty = value
|
||||
|
||||
override def currentGui = robot.currentGui
|
||||
|
||||
override def currentGui_=(value: Option[gui.Buffer]) = robot.currentGui = value
|
||||
|
||||
def tier = robot.tier
|
||||
}
|
@ -154,9 +154,9 @@ class Screen(var tier: Int) extends Buffer with Rotatable with Analyzable with O
|
||||
if ((width == 1 && height == 1) || !isOrigin) super.getRenderBoundingBox
|
||||
else {
|
||||
val (sx, sy, sz) = unproject(width, height, 1)
|
||||
val ox = xCoord + (if (sx < 0) 1 else 0)
|
||||
val oy = yCoord + (if (sy < 0) 1 else 0)
|
||||
val oz = zCoord + (if (sz < 0) 1 else 0)
|
||||
val ox = x + (if (sx < 0) 1 else 0)
|
||||
val oy = y + (if (sy < 0) 1 else 0)
|
||||
val oz = z + (if (sz < 0) 1 else 0)
|
||||
val b = AxisAlignedBB.getAABBPool.getAABB(ox, oy, oz, ox + sx, oy + sy, oz + sz)
|
||||
b.setBounds(b.minX min b.maxX, b.minY min b.maxY, b.minZ min b.maxZ,
|
||||
b.minX max b.maxX, b.minY max b.maxY, b.minZ max b.maxZ)
|
||||
@ -227,7 +227,7 @@ class Screen(var tier: Int) extends Buffer with Rotatable with Analyzable with O
|
||||
}
|
||||
|
||||
private def project(t: Screen) = {
|
||||
def dot(f: ForgeDirection, s: Screen) = f.offsetX * s.xCoord + f.offsetY * s.yCoord + f.offsetZ * s.zCoord
|
||||
def dot(f: ForgeDirection, s: Screen) = f.offsetX * s.x + f.offsetY * s.y + f.offsetZ * s.z
|
||||
(dot(toGlobal(ForgeDirection.EAST), t), dot(toGlobal(ForgeDirection.UP), t), dot(toGlobal(ForgeDirection.SOUTH), t))
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case PacketType.ComputerStateRequest => onComputerStateRequest(p)
|
||||
case PacketType.PowerStateRequest => onPowerStateRequest(p)
|
||||
case PacketType.RedstoneStateRequest => onRedstoneStateRequest(p)
|
||||
case PacketType.RobotStateRequest => onRobotSelectedSlotRequest(p)
|
||||
case PacketType.RobotStateRequest => onRobotStateRequest(p)
|
||||
case PacketType.RotatableStateRequest => onRotatableStateRequest(p)
|
||||
case PacketType.ScreenBufferRequest => onScreenBufferRequest(p)
|
||||
case PacketType.KeyDown => onKeyDown(p)
|
||||
@ -43,9 +43,9 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotSelectedSlotRequest(p: PacketParser) =
|
||||
p.readTileEntity[Robot]() match {
|
||||
case Some(t) => PacketSender.sendRobotSelectedSlotChange(t, Option(p.player))
|
||||
def onRobotStateRequest(p: PacketParser) =
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) => PacketSender.sendRobotState(t.robot, Option(p.player))
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.RobotMove)
|
||||
|
||||
// Custom pb.writeTileEntity() with fake coordinates (valid for the client).
|
||||
pb.writeInt(t.world.provider.dimensionId)
|
||||
pb.writeInt(t.proxy.world.provider.dimensionId)
|
||||
pb.writeInt(ox)
|
||||
pb.writeInt(oy)
|
||||
pb.writeInt(oz)
|
||||
@ -72,27 +72,54 @@ object PacketSender {
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendRobotSelectedSlotChange(t: Robot, player: Option[Player] = None) {
|
||||
def sendRobotAnimateSwing(t: Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotAnimateSwing)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeInt(t.animationTicksTotal)
|
||||
|
||||
pb.sendToNearbyPlayers(t.proxy)
|
||||
}
|
||||
|
||||
def sendRobotAnimateTurn(t: Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotAnimateTurn)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeByte(t.turnAxis)
|
||||
pb.writeInt(t.animationTicksTotal)
|
||||
|
||||
pb.sendToNearbyPlayers(t.proxy)
|
||||
}
|
||||
|
||||
def sendRobotEquippedItemChange(t: Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotEquippedItemChange)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeItemStack(t.getStackInSlot(0))
|
||||
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendRobotSelectedSlotChange(t: Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotSelectedSlotChange)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeInt(t.selectedSlot)
|
||||
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
case _ => pb.sendToAllPlayers()
|
||||
}
|
||||
pb.sendToAllPlayers()
|
||||
}
|
||||
|
||||
def sendRobotState(t: Robot, player: Option[Player] = None) {
|
||||
val pb = new PacketBuilder(PacketType.RobotStateResponse)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeTileEntity(t.proxy)
|
||||
pb.writeInt(t.selectedSlot)
|
||||
pb.writeItemStack(t.getStackInSlot(0))
|
||||
pb.writeInt(t.animationTicksTotal)
|
||||
pb.writeInt(t.animationTicksLeft)
|
||||
pb.writeDirection(t.moveDirection)
|
||||
pb.writeDirection(t.turnOldFacing)
|
||||
pb.writeBoolean(t.swingingTool)
|
||||
pb.writeByte(t.turnAxis)
|
||||
|
||||
player match {
|
||||
case Some(p) => pb.sendToPlayer(p)
|
||||
|
@ -69,7 +69,7 @@ class Keyboard(owner: Environment) extends ManagedComponent {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private def isUseableByPlayer(p: EntityPlayer) =
|
||||
def isUseableByPlayer(p: EntityPlayer) =
|
||||
owner.world.getBlockTileEntity(owner.x, owner.y, owner.z) == owner &&
|
||||
p.getDistanceSq(owner.x + 0.5, owner.y + 0.5, owner.z + 0.5) <= 64
|
||||
}
|
||||
|
@ -165,6 +165,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
}
|
||||
if (what) {
|
||||
context.pause(Config.placeDelay)
|
||||
robot.animateSwing(Config.placeDelay)
|
||||
}
|
||||
result(what)
|
||||
}
|
||||
@ -207,17 +208,21 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
throw new IllegalArgumentException("invalid side")
|
||||
}
|
||||
val player = robot.player(facing, side)
|
||||
def triggerDelay() = {
|
||||
context.pause(Config.swingDelay)
|
||||
robot.animateSwing(Config.swingDelay)
|
||||
}
|
||||
Option(pick(facing, side, Config.swingRange)) match {
|
||||
case Some(hit) =>
|
||||
val what = hit.typeOfHit match {
|
||||
case EnumMovingObjectType.ENTITY =>
|
||||
player.attackTargetEntityWithCurrentItem(hit.entityHit)
|
||||
context.pause(Config.swingDelay)
|
||||
triggerDelay()
|
||||
result(true, "entity")
|
||||
case EnumMovingObjectType.TILE =>
|
||||
val broke = player.clickBlock(hit.blockX, hit.blockY, hit.blockZ, hit.sideHit)
|
||||
if (broke) {
|
||||
context.pause(Config.swingDelay)
|
||||
triggerDelay()
|
||||
}
|
||||
result(broke, "block")
|
||||
}
|
||||
@ -226,7 +231,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
player.closestLivingEntity(facing) match {
|
||||
case Some(entity) =>
|
||||
player.attackTargetEntityWithCurrentItem(entity)
|
||||
context.pause(Config.swingDelay)
|
||||
triggerDelay()
|
||||
result(true, "entity")
|
||||
case _ =>
|
||||
result(false)
|
||||
@ -243,16 +248,20 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
}
|
||||
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
|
||||
val player = robot.player(facing, side)
|
||||
def triggerDelay() {
|
||||
context.pause(Config.useDelay)
|
||||
robot.animateSwing(Config.useDelay)
|
||||
}
|
||||
def activationResult(activationType: ActivationType.Value): Array[AnyRef] =
|
||||
activationType match {
|
||||
case ActivationType.BlockActivated =>
|
||||
context.pause(Config.useDelay)
|
||||
triggerDelay()
|
||||
result(true, "block_activated")
|
||||
case ActivationType.ItemPlaced =>
|
||||
context.pause(Config.useDelay)
|
||||
triggerDelay()
|
||||
result(true, "item_placed")
|
||||
case ActivationType.ItemUsed =>
|
||||
context.pause(Config.useDelay)
|
||||
triggerDelay()
|
||||
result(true, "item_used")
|
||||
case _ => result(false)
|
||||
}
|
||||
@ -275,7 +284,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
} else ActivationType.None) match {
|
||||
case ActivationType.None =>
|
||||
if (player.useEquippedItem()) {
|
||||
context.pause(Config.useDelay)
|
||||
triggerDelay()
|
||||
result(true, "item_used")
|
||||
}
|
||||
else result(false)
|
||||
@ -321,10 +330,9 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) {
|
||||
@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)
|
||||
robot.animateTurn(clockwise, Config.turnDelay)
|
||||
context.pause(Config.turnDelay)
|
||||
result(true)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user