Skip to content

Commit

Permalink
Added waypoint block, can be queried using navigation upgrades.
Browse files Browse the repository at this point in the history
Fixed drones losing their name when changing their EEPROM.
  • Loading branch information
fnuecke committed Apr 26, 2015
1 parent 226fa52 commit 5672cf8
Show file tree
Hide file tree
Showing 36 changed files with 402 additions and 35 deletions.
Binary file modified assets/blocks.psd
Binary file not shown.
Binary file modified assets/items.psd
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Waypoint

!["This way!" - "No, that way!"](oredict:oc:waypoint)

The waypoint's use lies not in itself, but in how it can be used. [Navigation upgrades](../item/navigationUpgrade.md) can detect waypoints, so devices with a navigation upgrade can use these waypoints to navigate the world. This is particularly useful for writing easily reusable programs for devices such as [robots](robot.md) and [drones](../item/drone.md).

Note that the actual position reported when queried by a navigation upgrade is *the block in front of the waypoint* (indicated by the particle effects). This way you can place it next to and above a chest, and can refer to the waypoint's position as "above the chest", without having to take the waypoint's rotation into account in your program.

A waypoint has two properties that can be used when querying it via a navigation upgrade: the current level of redstone signal it is receiving, and an editable label. The label is a 32-character long string that can be edited either via a GUI or via the component exposed by the waypoint block. These two properties can then be used on the device to determine what to do with the waypoint. For example, a sorting program can be set to treat all blocks with a high redstone signal as inputs and those with a low signal as outputs.
2 changes: 2 additions & 0 deletions src/main/resources/assets/opencomputers/lang/en_US.lang
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tile.oc.screen2.name=Screen (Tier 2)
tile.oc.screen3.name=Screen (Tier 3)
tile.oc.serverRack.name=Server Rack
tile.oc.switch.name=Switch
tile.oc.waypoint.name=Waypoint

# Items
item.oc.AbstractBusCard.name=Abstract Bus Card
Expand Down Expand Up @@ -341,6 +342,7 @@ oc:tooltip.UpgradeSolarGenerator=Can be used to generate energy from sunlight on
oc:tooltip.UpgradeTank=This upgrade provides a tank for fluid storage for robots and drones. Without one of these, they will not be able to store fluids internally.
oc:tooltip.UpgradeTankController=This upgrade allows robots and drones more control in how they interacts with external tanks, and allows them to transfer fluids into and out of fluid tank items in their inventory.
oc:tooltip.UpgradeTractorBeam=Equips a device with extremely advanced technology, nicknamed the "Item Magnet". Allows the device to pick up items anywhere within 3 blocks of its location.
oc:tooltip.Waypoint=Provides a point of reference to devices with a navigation upgrade.
oc:tooltip.WirelessNetworkCard=Allows wireless sending of network messages in addition to normal ones. You can adjust the §fsignal strength§7 to control how far messages are sent. Higher signal strength results in higher energy consumption.
oc:tooltip.WorldSensorCard=Allows reading out information about the world, such as its gravity and whether it has a breathable atmosphere. Use results at own risk. The manufacturer takes no responsibility for bodily or material harm caused by decisions made upon the cards' outputs. We have lawyers. And money. Don't even try.
oc:tooltip.Wrench=A hybrid of Screwdriver and Wrench, this tool is easy to learn, but hard to master.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,11 @@ screen3 {
[yellowDust, "oc:circuitChip3", glass]
[obsidian, yellowDust, obsidian]]
}
waypoint {
input: [[ingotIron, "oc:circuitChip1", ingotIron]
["oc:materialTransistor", "oc:materialInterweb", "oc:materialTransistor"],
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
}

appengTunnel {
type: shapeless
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/main/scala/li/cil/oc/Constants.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ object Constants {
final val ScreenTier3 = "screen3"
final val ServerRack = "serverRack"
final val Switch = "switch"
final val Waypoint = "waypoint"

def Case(tier: Int) = ItemUtils.caseNameWithTierSuffix("case", tier)
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/li/cil/oc/client/GuiHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ object GuiHandler extends CommonGuiHandler {
new gui.Screen(t.origin.buffer, t.tier > 0, () => t.origin.hasKeyboard, () => t.origin.buffer.isRenderingEnabled)
case t: tileentity.Switch if id == GuiType.Switch.id =>
new gui.Switch(player.inventory, t)
case t: tileentity.Waypoint if id == GuiType.Waypoint.id =>
new gui.Waypoint(t)
case _ => null
}
case Some(GuiType.Category.Entity) =>
Expand Down
9 changes: 8 additions & 1 deletion src/main/scala/li/cil/oc/client/PacketHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.ServerPresence => onServerPresence(p)
case PacketType.Sound => onSound(p)
case PacketType.SoundPattern => onSoundPattern(p)
case PacketType.WaypointLabel => onWaypointLabel(p)
case _ => // Invalid packet.
}
}
Expand Down Expand Up @@ -266,7 +267,7 @@ object PacketHandler extends CommonPacketHandler {
for (i <- 0 until count) {
def rv(f: ForgeDirection => Int) = direction match {
case Some(d) => world.rand.nextFloat - 0.5 + f(d) * 0.5
case _ => world.rand.nextFloat * 2 - 1
case _ => world.rand.nextFloat * 2.0 - 1
}
val vx = rv(_.offsetX)
val vy = rv(_.offsetY)
Expand Down Expand Up @@ -610,4 +611,10 @@ object PacketHandler extends CommonPacketHandler {
Audio.play(x + 0.5f, y + 0.5f, z + 0.5f, pattern)
}
}

def onWaypointLabel(p: PacketParser) =
p.readTileEntity[Waypoint]() match {
case Some(waypoint) => waypoint.label = p.readUTF()
case _ => // Invalid packet.
}
}
9 changes: 9 additions & 0 deletions src/main/scala/li/cil/oc/client/PacketSender.scala
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,13 @@ object PacketSender {

pb.sendToServer()
}

def sendWaypointLabel(t: Waypoint): Unit = {
val pb = new SimplePacketBuilder(PacketType.WaypointLabel)

pb.writeTileEntity(t)
pb.writeUTF(t.label)

pb.sendToServer()
}
}
1 change: 1 addition & 0 deletions src/main/scala/li/cil/oc/client/Textures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ object Textures {
val guiRobotSelection = new ResourceLocation(Settings.resourceDomain, "textures/gui/robot_selection.png")
val guiServer = new ResourceLocation(Settings.resourceDomain, "textures/gui/server.png")
val guiSlot = new ResourceLocation(Settings.resourceDomain, "textures/gui/slot.png")
val guiWaypoint = new ResourceLocation(Settings.resourceDomain, "textures/gui/waypoint.png")

val blockCaseFrontOn = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontOn.png")
val blockCaseFrontActivity = new ResourceLocation(Settings.resourceDomain, "textures/blocks/CaseFrontActivity.png")
Expand Down
1 change: 0 additions & 1 deletion src/main/scala/li/cil/oc/client/gui/Manual.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ class Manual extends GuiScreen {
override def initGui(): Unit = {
super.initGui()

val mc = Minecraft.getMinecraft
val screenSize = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight)
val guiSize = new ScaledResolution(mc, 256, 192)
val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
Expand Down
76 changes: 76 additions & 0 deletions src/main/scala/li/cil/oc/client/gui/Waypoint.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package li.cil.oc.client.gui

import li.cil.oc.client.PacketSender
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity
import net.minecraft.client.gui.GuiScreen
import net.minecraft.client.gui.GuiTextField
import net.minecraft.client.gui.ScaledResolution
import org.lwjgl.input.Keyboard
import org.lwjgl.opengl.GL11

class Waypoint(val waypoint: tileentity.Waypoint) extends GuiScreen {
var guiLeft = 0
var guiTop = 0
var xSize = 0
var ySize = 0

var textField: GuiTextField = _

override def updateScreen(): Unit = {
super.updateScreen()
if (mc.thePlayer.getDistanceSq(waypoint.x + 0.5, waypoint.y + 0.5, waypoint.z + 0.5) > 64) {
mc.thePlayer.closeScreen()
}
}

override def doesGuiPauseGame(): Boolean = false

override def initGui(): Unit = {
super.initGui()

val screenSize = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight)
val guiSize = new ScaledResolution(mc, 176, 24)
val (midX, midY) = (screenSize.getScaledWidth / 2, screenSize.getScaledHeight / 2)
guiLeft = midX - guiSize.getScaledWidth / 2
guiTop = midY - guiSize.getScaledHeight / 2
xSize = guiSize.getScaledWidth
ySize = guiSize.getScaledHeight

textField = new GuiTextField(fontRendererObj, guiLeft + 7, guiTop + 8, 164 - 12, 12)
textField.setMaxStringLength(32)
textField.setEnableBackgroundDrawing(false)
textField.setCanLoseFocus(false)
textField.setFocused(true)
textField.setTextColor(0xFFFFFF)
textField.setText(waypoint.label)

Keyboard.enableRepeatEvents(true)
}

override def onGuiClosed(): Unit = {
super.onGuiClosed()
Keyboard.enableRepeatEvents(false)
}

override def keyTyped(char: Char, code: Int): Unit = {
if (!textField.textboxKeyTyped(char, code)) {
if (code == Keyboard.KEY_RETURN) {
val label = textField.getText.take(32)
if (label != waypoint.label) {
waypoint.label = label
PacketSender.sendWaypointLabel(waypoint)
}
}
else super.keyTyped(char, code)
}
}

override def drawScreen(mouseX: Int, mouseY: Int, dt: Float): Unit = {
super.drawScreen(mouseX, mouseY, dt)
GL11.glColor3f(1, 1, 1) // Required under Linux.
mc.renderEngine.bindTexture(Textures.guiWaypoint)
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
textField.drawTextBox()
}
}
53 changes: 29 additions & 24 deletions src/main/scala/li/cil/oc/client/renderer/block/BlockRenderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,32 +140,37 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
}
}

private def needsFlipping(block: Block) =
block.isInstanceOf[Hologram] ||
block.isInstanceOf[Printer] ||
block.isInstanceOf[Print]

// The texture flip this works around only seems to occur for blocks with custom block renderers?
def patchedRenderer(renderer: RenderBlocks, block: Block) =
if (block.isInstanceOf[Hologram] || block.isInstanceOf[Printer] || block.isInstanceOf[Print]) {
PatchedRenderBlocks.blockAccess = renderer.blockAccess
PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture
PatchedRenderBlocks.flipTexture = renderer.flipTexture
PatchedRenderBlocks.renderAllFaces = renderer.renderAllFaces
PatchedRenderBlocks.useInventoryTint = renderer.useInventoryTint
PatchedRenderBlocks.renderFromInside = renderer.renderFromInside
PatchedRenderBlocks.renderMinX = renderer.renderMinX
PatchedRenderBlocks.renderMaxX = renderer.renderMaxX
PatchedRenderBlocks.renderMinY = renderer.renderMinY
PatchedRenderBlocks.renderMaxY = renderer.renderMaxY
PatchedRenderBlocks.renderMinZ = renderer.renderMinZ
PatchedRenderBlocks.renderMaxZ = renderer.renderMaxZ
PatchedRenderBlocks.lockBlockBounds = renderer.lockBlockBounds
PatchedRenderBlocks.partialRenderBounds = renderer.partialRenderBounds
PatchedRenderBlocks.uvRotateEast = renderer.uvRotateEast
PatchedRenderBlocks.uvRotateWest = renderer.uvRotateWest
PatchedRenderBlocks.uvRotateSouth = renderer.uvRotateSouth
PatchedRenderBlocks.uvRotateNorth = renderer.uvRotateNorth
PatchedRenderBlocks.uvRotateTop = renderer.uvRotateTop
PatchedRenderBlocks.uvRotateBottom = renderer.uvRotateBottom
PatchedRenderBlocks
}
else renderer
if (needsFlipping(block)) {
PatchedRenderBlocks.blockAccess = renderer.blockAccess
PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture
PatchedRenderBlocks.flipTexture = renderer.flipTexture
PatchedRenderBlocks.renderAllFaces = renderer.renderAllFaces
PatchedRenderBlocks.useInventoryTint = renderer.useInventoryTint
PatchedRenderBlocks.renderFromInside = renderer.renderFromInside
PatchedRenderBlocks.renderMinX = renderer.renderMinX
PatchedRenderBlocks.renderMaxX = renderer.renderMaxX
PatchedRenderBlocks.renderMinY = renderer.renderMinY
PatchedRenderBlocks.renderMaxY = renderer.renderMaxY
PatchedRenderBlocks.renderMinZ = renderer.renderMinZ
PatchedRenderBlocks.renderMaxZ = renderer.renderMaxZ
PatchedRenderBlocks.lockBlockBounds = renderer.lockBlockBounds
PatchedRenderBlocks.partialRenderBounds = renderer.partialRenderBounds
PatchedRenderBlocks.uvRotateEast = renderer.uvRotateEast
PatchedRenderBlocks.uvRotateWest = renderer.uvRotateWest
PatchedRenderBlocks.uvRotateSouth = renderer.uvRotateSouth
PatchedRenderBlocks.uvRotateNorth = renderer.uvRotateNorth
PatchedRenderBlocks.uvRotateTop = renderer.uvRotateTop
PatchedRenderBlocks.uvRotateBottom = renderer.uvRotateBottom
PatchedRenderBlocks
}
else renderer

object PatchedRenderBlocks extends RenderBlocks {
override def renderFaceXPos(block: Block, x: Double, y: Double, z: Double, texture: IIcon) {
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/li/cil/oc/common/GuiType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ object GuiType extends ScalaEnum {
val Tablet = new EnumVal { def name = "Tablet"; def subType = GuiType.Category.Item }
val TabletInner = new EnumVal { def name = "TabletInner"; def subType = GuiType.Category.Item }
val Terminal = new EnumVal { def name = "Terminal"; def subType = GuiType.Category.Item }
val Waypoint = new EnumVal { def name = "Waypoint"; def subType = GuiType.Category.Block }

object Category extends ScalaEnum {
sealed trait EnumVal extends Value
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/li/cil/oc/common/PacketType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ object PacketType extends Enumeration {
ServerPresence,
Sound,
SoundPattern,
WaypointLabel, // Goes both ways.

// Client -> Server
ComputerPower,
Expand Down
44 changes: 44 additions & 0 deletions src/main/scala/li/cil/oc/common/block/Waypoint.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package li.cil.oc.common.block

import li.cil.oc.OpenComputers
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.world.World
import net.minecraftforge.common.util.ForgeDirection

class Waypoint extends RedstoneAware {
override protected def customTextures = Array(
None,
Some("WaypointTop"),
Some("WaypointBack"),
Some("WaypointFront"),
Some("WaypointSide"),
Some("WaypointSide")
)

// ----------------------------------------------------------------------- //

override def createTileEntity(world: World, metadata: Int) = new tileentity.Waypoint()

// ----------------------------------------------------------------------- //

override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = {
if (!player.isSneaking) {
if (world.isRemote) {
player.openGui(OpenComputers, GuiType.Waypoint.id, world, x, y, z)
}
true
}
else super.onBlockActivated(world, x, y, z, player, side, hitX, hitY, hitZ)
}

override def getValidRotations(world: World, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case waypoint: tileentity.Waypoint =>
ForgeDirection.VALID_DIRECTIONS.filter {
d => d != waypoint.facing && d != waypoint.facing.getOpposite
}
case _ => super.getValidRotations(world, x, y, z)
}
}
2 changes: 2 additions & 0 deletions src/main/scala/li/cil/oc/common/init/Blocks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ object Blocks {
GameRegistry.registerTileEntity(classOf[tileentity.Switch], Settings.namespace + "switch")
GameRegistry.registerTileEntity(classOf[tileentity.Screen], Settings.namespace + "screen")
GameRegistry.registerTileEntity(classOf[tileentity.ServerRack], Settings.namespace + "serverRack")
GameRegistry.registerTileEntity(classOf[tileentity.Waypoint], Settings.namespace + "waypoint")

Recipes.addBlock(new AccessPoint(), Constants.BlockName.AccessPoint, "oc:accessPoint")
Recipes.addBlock(new Adapter(), Constants.BlockName.Adapter, "oc:adapter")
Expand Down Expand Up @@ -70,5 +71,6 @@ object Blocks {
Items.registerBlock(new Print(), "print")
Recipes.addBlock(new Printer(), "printer", "oc:printer")
Recipes.addBlock(new ChameliumBlock(), "chameliumBlock", "oc:chameliumBlock")
Recipes.addBlock(new Waypoint(), Constants.BlockName.Waypoint, "oc:waypoint")
}
}
13 changes: 12 additions & 1 deletion src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.common.init.Items
import li.cil.oc.common.item.data.DroneData
import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.item.data.RobotData
Expand Down Expand Up @@ -176,7 +177,7 @@ object ExtendedRecipe {

// Swapping EEPROM in devices.
recraft(craftedStack, inventory, mcu, stack => new MCUDataWrapper(stack))
recraft(craftedStack, inventory, drone, stack => new MCUDataWrapper(stack))
recraft(craftedStack, inventory, drone, stack => new DroneDataWrapper(stack))
recraft(craftedStack, inventory, robot, stack => new RobotDataWrapper(stack))
recraft(craftedStack, inventory, tablet, stack => new TabletDataWrapper(stack))

Expand Down Expand Up @@ -228,6 +229,16 @@ object ExtendedRecipe {
override def save(stack: ItemStack) = data.save(stack)
}

private class DroneDataWrapper(val stack: ItemStack) extends ItemDataWrapper {
val data = new DroneData(stack)

override def components = data.components

override def components_=(value: Array[ItemStack]) = data.components = value

override def save(stack: ItemStack) = data.save(stack)
}

private class RobotDataWrapper(val stack: ItemStack) extends ItemDataWrapper {
val data = new RobotData(stack)

Expand Down
Loading

0 comments on commit 5672cf8

Please sign in to comment.