From cb704dab33b408d00cf63b7702dc5e7816b95c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Wed, 29 Apr 2015 16:19:08 +0200 Subject: [PATCH] Basic integration for IGWMod, providing manual pages for blocks and items. --- .../opencomputers/doc/en_US/block/print.md | 2 +- .../renderer/markdown/MarkupFormat.scala | 5 ++ .../markdown/segment/BasicTextSegment.scala | 3 + .../markdown/segment/BoldSegment.scala | 6 +- .../markdown/segment/CodeSegment.scala | 6 +- .../markdown/segment/HeaderSegment.scala | 6 +- .../markdown/segment/ItalicSegment.scala | 6 +- .../markdown/segment/LinkSegment.scala | 9 ++- .../markdown/segment/RenderSegment.scala | 6 +- .../renderer/markdown/segment/Segment.scala | 21 +++++++ .../segment/StrikethroughSegment.scala | 6 +- .../markdown/segment/TextSegment.scala | 2 - .../scala/li/cil/oc/common/init/Items.scala | 4 +- .../scala/li/cil/oc/integration/Mods.scala | 10 +++- .../oc/integration/igw/ModIngameWiki.scala | 14 +++++ .../oc/integration/igw/WikiEventHandler.scala | 57 +++++++++++++++++++ 16 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 src/main/scala/li/cil/oc/client/renderer/markdown/MarkupFormat.scala create mode 100644 src/main/scala/li/cil/oc/integration/igw/ModIngameWiki.scala create mode 100644 src/main/scala/li/cil/oc/integration/igw/WikiEventHandler.scala diff --git a/src/main/resources/assets/opencomputers/doc/en_US/block/print.md b/src/main/resources/assets/opencomputers/doc/en_US/block/print.md index 8fea03113..e1775103e 100644 --- a/src/main/resources/assets/opencomputers/doc/en_US/block/print.md +++ b/src/main/resources/assets/opencomputers/doc/en_US/block/print.md @@ -6,6 +6,6 @@ 3D prints can be recycled by putting them as input into a [3D printer](printer.md). This will re-use some of the [chamelium](../item/chamelium.md) that was used to print them. Color that was used to print the model will not be recycled. -Holding the key for OpenComputers' extended tooltips (default is [Shift]), a print's active state will be shown, if any. +Holding the key for OpenComputers' extended tooltips (default is `Shift`), a print's active state will be shown, if any. Printed blocks are also Forge MultiPart compatible. If present, multiple prints can be placed into a single block-space, unless they do not collide, and the total number of shapes in the block-space does not exceed the limit for a single model. Due to the nature of Forge MultiPart, prints can therefore also be placed into the same block-space as any other Forge MultiPart compatible block, such as torches, levers, cables or red alloy wires from Project Red, for example. diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/MarkupFormat.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/MarkupFormat.scala new file mode 100644 index 000000000..72a5c3118 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/MarkupFormat.scala @@ -0,0 +1,5 @@ +package li.cil.oc.client.renderer.markdown + +object MarkupFormat extends Enumeration { + val Markdown, IGWMod = Value +} diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala index 7fd3e328f..d19a4d21e 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BasicTextSegment.scala @@ -1,6 +1,7 @@ package li.cil.oc.client.renderer.markdown.segment import li.cil.oc.client.renderer.markdown.Document +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.client.gui.FontRenderer trait BasicTextSegment extends Segment { @@ -38,6 +39,8 @@ trait BasicTextSegment extends Segment { lines * lineHeight(renderer) } + override def toString(format: MarkupFormat.Value): String = text + // ----------------------------------------------------------------------- // protected def text: String diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BoldSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BoldSegment.scala index 820d423b2..908bf155f 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BoldSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/BoldSegment.scala @@ -1,9 +1,13 @@ package li.cil.oc.client.renderer.markdown.segment +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.util.EnumChatFormatting private[markdown] class BoldSegment(parent: Segment, text: String) extends TextSegment(parent, text) { override protected def format = EnumChatFormatting.BOLD.toString - override def toString: String = s"{BoldSegment: text = $text}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"**$text**" + case MarkupFormat.IGWMod => s"[prefix{l}]$text [prefix{}]" + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala index 46f36f4aa..5356e55e4 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/CodeSegment.scala @@ -1,6 +1,7 @@ package li.cil.oc.client.renderer.markdown.segment import li.cil.oc.client.renderer.TextBufferRenderCache +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.client.gui.FontRenderer import org.lwjgl.opengl.GL11 @@ -30,5 +31,8 @@ private[markdown] class CodeSegment(val parent: Segment, val text: String) exten override protected def stringWidth(s: String, renderer: FontRenderer): Int = s.length * TextBufferRenderCache.renderer.charRenderWidth - override def toString: String = s"{CodeSegment: text = $text}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"`$text`" + case MarkupFormat.IGWMod => s"[prefix{1}]$text [prefix{}]" + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/HeaderSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/HeaderSegment.scala index 18657a757..1baf4e06a 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/HeaderSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/HeaderSegment.scala @@ -1,5 +1,6 @@ package li.cil.oc.client.renderer.markdown.segment +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.util.EnumChatFormatting private[markdown] class HeaderSegment(parent: Segment, text: String, val level: Int) extends TextSegment(parent, text) { @@ -9,5 +10,8 @@ private[markdown] class HeaderSegment(parent: Segment, text: String, val level: override protected def format = EnumChatFormatting.UNDERLINE.toString - override def toString: String = s"{HeaderSegment: text = $text, level = $level}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"${"#" * level} $text" + case MarkupFormat.IGWMod => s"[prefix{l}]$text [prefix{}]" + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/ItalicSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/ItalicSegment.scala index ee6bd34d8..e8afb72e9 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/ItalicSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/ItalicSegment.scala @@ -1,9 +1,13 @@ package li.cil.oc.client.renderer.markdown.segment +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.util.EnumChatFormatting private[markdown] class ItalicSegment(parent: Segment, text: String) extends TextSegment(parent, text) { override protected def format = EnumChatFormatting.ITALIC.toString - override def toString: String = s"{ItalicSegment: text = $text}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"*$text*" + case MarkupFormat.IGWMod => s"[prefix{o}]$text [prefix{}]" + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala index 15fc30289..213cf4443 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/LinkSegment.scala @@ -3,8 +3,10 @@ package li.cil.oc.client.renderer.markdown.segment import java.net.URI import li.cil.oc.Localization +import li.cil.oc.OpenComputers import li.cil.oc.api import li.cil.oc.client.Manual +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.client.Minecraft private[markdown] class LinkSegment(parent: Segment, text: String, val url: String) extends TextSegment(parent, text) with InteractiveSegment { @@ -54,5 +56,10 @@ private[markdown] class LinkSegment(parent: Segment, text: String, val url: Stri } } - override def toString: String = s"{LinkSegment: text = $text, url = $url}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"[$text]($url)" + case MarkupFormat.IGWMod => + if (url.startsWith("http://") || url.startsWith("https://")) text + else s"[link{${OpenComputers.ID}:$url}]$text [link{}]" + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala index d1183338c..d635e98d5 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/RenderSegment.scala @@ -3,6 +3,7 @@ package li.cil.oc.client.renderer.markdown.segment import li.cil.oc.api.manual.ImageRenderer import li.cil.oc.api.manual.InteractiveImageRenderer import li.cil.oc.client.renderer.markdown.Document +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.client.gui.FontRenderer import org.lwjgl.opengl.GL11 @@ -74,5 +75,8 @@ private[markdown] class RenderSegment(val parent: Segment, val title: String, va hovered } - override def toString: String = s"{RendererSegment: title = $title, imageRenderer = $imageRenderer}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"![$title]($imageRenderer)" + case MarkupFormat.IGWMod => "(Sorry, images only work in the OpenComputers manual for now.)" // TODO + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala index 7e6ca0527..645dd1a90 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/Segment.scala @@ -1,8 +1,10 @@ package li.cil.oc.client.renderer.markdown.segment +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.client.gui.FontRenderer import scala.annotation.tailrec +import scala.collection.mutable import scala.util.matching.Regex trait Segment { @@ -46,6 +48,25 @@ trait Segment { */ def render(x: Int, y: Int, indent: Int, maxWidth: Int, renderer: FontRenderer, mouseX: Int, mouseY: Int): Option[InteractiveSegment] = None + def renderAsText(format: MarkupFormat.Value): Iterable[String] = { + var segment = this + val result = mutable.Buffer.empty[String] + val builder = mutable.StringBuilder.newBuilder + while (segment != null) { + builder.append(segment.toString(format)) + if (segment.isLast) { + result += builder.toString() + builder.clear() + } + segment = segment.next + } + result.toIterable + } + + def toString(format: MarkupFormat.Value): String + + override def toString: String = toString(MarkupFormat.Markdown) + // ----------------------------------------------------------------------- // // Used during construction, checks a segment for inner segments. diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/StrikethroughSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/StrikethroughSegment.scala index 3b2056c79..e3b544e22 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/StrikethroughSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/StrikethroughSegment.scala @@ -1,9 +1,13 @@ package li.cil.oc.client.renderer.markdown.segment +import li.cil.oc.client.renderer.markdown.MarkupFormat import net.minecraft.util.EnumChatFormatting private[markdown] class StrikethroughSegment(parent: Segment, text: String) extends TextSegment(parent, text) { override protected def format = EnumChatFormatting.STRIKETHROUGH.toString - override def toString: String = s"{StrikethroughSegment: text = $text}" + override def toString(format: MarkupFormat.Value): String = format match { + case MarkupFormat.Markdown => s"~~$text~~" + case MarkupFormat.IGWMod => s"[prefix{m}]$text [prefix{}]" + } } diff --git a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala index 9c0bc8383..491c6faad 100644 --- a/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala +++ b/src/main/scala/li/cil/oc/client/renderer/markdown/segment/TextSegment.scala @@ -96,6 +96,4 @@ private[markdown] class TextSegment(val parent: Segment, val text: String) exten case _ => None } } - - override def toString: String = s"{TextSegment: text = $text}" } diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index d09a0e920..4b30ae26d 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -32,9 +32,9 @@ import net.minecraft.world.World import scala.collection.mutable object Items extends ItemAPI { - private val descriptors = mutable.Map.empty[String, ItemInfo] + val descriptors = mutable.Map.empty[String, ItemInfo] - private val names = mutable.Map.empty[Any, String] + val names = mutable.Map.empty[Any, String] override def get(name: String): ItemInfo = descriptors.get(name).orNull diff --git a/src/main/scala/li/cil/oc/integration/Mods.scala b/src/main/scala/li/cil/oc/integration/Mods.scala index 9b50bf26f..715db2a1f 100644 --- a/src/main/scala/li/cil/oc/integration/Mods.scala +++ b/src/main/scala/li/cil/oc/integration/Mods.scala @@ -44,6 +44,7 @@ object Mods { val GregTech = new ClassBasedMod(IDs.GregTech, "gregtech.api.GregTech_API")() val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2, providesPower = true) val IndustrialCraft2Classic = new SimpleMod(IDs.IndustrialCraft2Classic, providesPower = true) + val IngameWiki = new SimpleMod(IDs.IngameWiki, version = "@[1.1.3,)") val Mekanism = new SimpleMod(IDs.Mekanism, providesPower = true) val Minecraft = new SimpleMod(IDs.Minecraft) val MineFactoryReloaded = new SimpleMod(IDs.MineFactoryReloaded) @@ -114,9 +115,13 @@ object Mods { // being used rather than other more concrete implementations. integration.computercraft.ModComputerCraft, - // We go last to ensure all other mod integration is done, e.g. to + // We go late to ensure all other mod integration is done, e.g. to // allow properly checking if wireless redstone is present. - integration.opencomputers.ModOpenComputers + integration.opencomputers.ModOpenComputers, + + // Run IGW registration after OC registration because we use the manual + // in there to know which pages to register. + integration.igw.ModIngameWiki ) def init(): Unit = { @@ -166,6 +171,7 @@ object Mods { final val GregTech = "gregtech" final val IndustrialCraft2 = "IC2" final val IndustrialCraft2Classic = "IC2-Classic" + final val IngameWiki = "IGWMod" final val Mekanism = "Mekanism" final val Minecraft = "Minecraft" final val MineFactoryReloaded = "MineFactoryReloaded" diff --git a/src/main/scala/li/cil/oc/integration/igw/ModIngameWiki.scala b/src/main/scala/li/cil/oc/integration/igw/ModIngameWiki.scala new file mode 100644 index 000000000..2e85980ca --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/igw/ModIngameWiki.scala @@ -0,0 +1,14 @@ +package li.cil.oc.integration.igw + +import li.cil.oc.api.Driver +import li.cil.oc.integration.ModProxy +import li.cil.oc.integration.Mods +import net.minecraftforge.common.MinecraftForge + +object ModIngameWiki extends ModProxy { + override def getMod = Mods.IngameWiki + + override def initialize(): Unit = { + WikiEventHandler.init() + } +} diff --git a/src/main/scala/li/cil/oc/integration/igw/WikiEventHandler.scala b/src/main/scala/li/cil/oc/integration/igw/WikiEventHandler.scala new file mode 100644 index 000000000..c8b8dfe1d --- /dev/null +++ b/src/main/scala/li/cil/oc/integration/igw/WikiEventHandler.scala @@ -0,0 +1,57 @@ +package li.cil.oc.integration.igw + +import java.util + +import cpw.mods.fml.common.eventhandler.SubscribeEvent +import igwmod.api.PageChangeEvent +import igwmod.api.WikiRegistry +import li.cil.oc.OpenComputers +import li.cil.oc.api +import li.cil.oc.client.Manual +import li.cil.oc.client.renderer.markdown +import li.cil.oc.client.renderer.markdown.MarkupFormat +import li.cil.oc.common.init.Items +import net.minecraftforge.common.MinecraftForge + +import scala.collection.convert.WrapAsJava._ +import scala.collection.convert.WrapAsScala._ + +object WikiEventHandler { + var lastPath = "" + + def init(): Unit = { + MinecraftForge.EVENT_BUS.register(this) + + for ((name, info) <- Items.descriptors) { + val stack = info.createItemStack(1) + val path = api.Manual.pathFor(stack) + if (path != null && api.Manual.contentFor(path) != null) { + WikiRegistry.registerBlockAndItemPageEntry(stack) + } + } + } + + @SubscribeEvent + def onPageChangeEvent(e: PageChangeEvent): Unit = { + val path = + if (e.associatedStack != null) + "/" + api.Manual.pathFor(e.associatedStack) + else if (e.currentFile.startsWith(OpenComputers.ID + ":")) + e.currentFile.stripPrefix(OpenComputers.ID + ":") + else null + + val base = lastPath + lastPath = "" + if (path != null) { + val resolvedPath = Manual.makeRelative(path, base) + val content = api.Manual.contentFor(resolvedPath) + if (content != null) { + val document = markdown.Document.parse(content) + val processed = document.renderAsText(MarkupFormat.IGWMod) + e.pageText = new util.ArrayList[String](asJavaCollection(processed)) + e.currentFile = resolvedPath + lastPath = resolvedPath + } + } + } +}