diff --git a/src/main/resources/assets/opencomputers/doc/en_US/drone.md b/src/main/resources/assets/opencomputers/doc/en_US/drone.md new file mode 100644 index 000000000..744bef8b7 --- /dev/null +++ b/src/main/resources/assets/opencomputers/doc/en_US/drone.md @@ -0,0 +1,5 @@ +# Drone + +![Big brother is trying to watch you.](oredict:oc:drone) + +Drones are built using a [drone case](droneCase1.md) in the [assembler](assembler.md). They are entity-based [robots](robot.md), a little cheaper but with more limited functionality. diff --git a/src/main/resources/assets/opencomputers/doc/en_US/robot.md b/src/main/resources/assets/opencomputers/doc/en_US/robot.md new file mode 100644 index 000000000..798f4e42e --- /dev/null +++ b/src/main/resources/assets/opencomputers/doc/en_US/robot.md @@ -0,0 +1,7 @@ +# Robot + +![His name was Tobor.](block:OpenComputers:robot) + +Unlike computers, robots can move around and interact with the world much like a player can. They can *not* interact with external components, however! If you need to communicate with a computer or other robots, use a [wireless network card](wlanCard.md), or create some low-level protocol using redstone signals via a [redstone card](redstoneCard1.md), for example. + +Robots are built by placing a [computer case](case1.md) in an [assembler](assembler.md). diff --git a/src/main/resources/assets/opencomputers/doc/en_US/tablet.md b/src/main/resources/assets/opencomputers/doc/en_US/tablet.md new file mode 100644 index 000000000..83e8887d8 --- /dev/null +++ b/src/main/resources/assets/opencomputers/doc/en_US/tablet.md @@ -0,0 +1,9 @@ +# Tablet + +![Touch me if you can.](oredict:oc:tablet) + + Tablets are built by placing a [tablet case](tabletCase1.md) into an [assembler](assembler.md), configuring as desired and assembling it. Tablets act as portable computers that cannot directly interact with the world - for example, basic [redstone cards](redstoneCard1.md) do not work in them. A number of upgrades, however, do, such as the [sign upgrade](signUpgrade.md) or the [piston upgrade](pistonUpgrade.md). + +To force rebooting a tablet, shift-rightclick it while holding it in your hand. Unlike computers, tablets do not persist across the player holding it leaving and re-entering the game. They also do not persist across the player holding the tablet changing dimensions (e.g. going to the Nether or back). + +Tablets can be put into a [charger](charger.md) to refill their energy, and to access the first [hard disk](hdd1.md) built into the tablet from a [computer](case1.md) connected to the charger - in this setup, the charger will act similar to a [disk drive](diskDrive.md), with the tablet being the [floppy disk](floppy.md). This can be very useful in case you forgot to install an OS on the hard drive built into the tablet, or after bricking a tablet's OS. diff --git a/src/main/scala/li/cil/oc/util/PseudoMarkdown.scala b/src/main/scala/li/cil/oc/util/PseudoMarkdown.scala index ebbce0587..cf33ba3f3 100644 --- a/src/main/scala/li/cil/oc/util/PseudoMarkdown.scala +++ b/src/main/scala/li/cil/oc/util/PseudoMarkdown.scala @@ -175,10 +175,11 @@ object PseudoMarkdown { override def height(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = { var lines = 0 var chars = text + if (indent == 0) chars = chars.dropWhile(_.isWhitespace) var lineChars = maxChars(chars, maxWidth - indent, renderer) while (chars.length > lineChars) { lines += 1 - chars = chars.drop(lineChars) + chars = chars.drop(lineChars).dropWhile(_.isWhitespace) lineChars = maxChars(chars, maxWidth, renderer) } (lines * lineHeight(renderer) * resolvedScale).toInt @@ -187,9 +188,10 @@ object PseudoMarkdown { override def width(indent: Int, maxWidth: Int, renderer: FontRenderer): Int = { var currentX = indent var chars = text + if (indent == 0) chars = chars.dropWhile(_.isWhitespace) var lineChars = maxChars(chars, maxWidth - indent, renderer) while (chars.length > lineChars) { - chars = chars.drop(lineChars) + chars = chars.drop(lineChars).dropWhile(_.isWhitespace) lineChars = maxChars(chars, maxWidth, renderer) currentX = 0 } @@ -201,6 +203,7 @@ object PseudoMarkdown { var currentX = x + indent var currentY = y var chars = text + if (indent == 0) chars = chars.dropWhile(_.isWhitespace) var numChars = maxChars(chars, maxWidth - indent, renderer) val interactive = findInteractive() var hovered: Option[InteractiveSegment] = None @@ -215,7 +218,7 @@ object PseudoMarkdown { GL11.glPopMatrix() currentX = x currentY += (lineHeight(renderer) * fontScale).toInt - chars = chars.drop(numChars) + chars = chars.drop(numChars).dropWhile(_.isWhitespace) numChars = maxChars(chars, maxWidth, renderer) } @@ -489,7 +492,8 @@ object PseudoMarkdown { val href = m.group(2) if (href.startsWith("item:")) { val desc = href.stripPrefix("item:") - val (name, optMeta) = desc.splitAt(desc.lastIndexOf('@')) + val splitIndex = desc.lastIndexOf('@') + val (name, optMeta) = if (splitIndex > 0) desc.splitAt(splitIndex) else (desc, "") val meta = if (Strings.isNullOrEmpty(optMeta)) 0 else Integer.parseInt(optMeta.drop(1)) Item.itemRegistry.getObject(name) match { case item: Item => new ItemStackSegment(s, m.group(1), Array(new ItemStack(item, 1, meta))) @@ -498,10 +502,11 @@ object PseudoMarkdown { } else if (href.startsWith("block:")) { val desc = href.stripPrefix("block:") - val (name, optMeta) = desc.splitAt(desc.lastIndexOf('@')) + val splitIndex = desc.lastIndexOf('@') + val (name, optMeta) = if (splitIndex > 0) desc.splitAt(splitIndex) else (desc, "") val meta = if (Strings.isNullOrEmpty(optMeta)) 0 else Integer.parseInt(optMeta.drop(1)) Block.blockRegistry.getObject(name) match { - case block: Block => new ItemStackSegment(s, m.group(1), Array(new ItemStack(block, 1, meta))) + case block: Block if Item.getItemFromBlock(block) != null => new ItemStackSegment(s, m.group(1), Array(new ItemStack(block, 1, meta))) case _ => new TextSegment(s, "Failed resolving " + href) } }