Basic integration for IGWMod, providing manual pages for blocks and items.

This commit is contained in:
Florian Nücke 2015-04-29 16:19:08 +02:00
parent 15cc9a7146
commit cb704dab33
16 changed files with 149 additions and 14 deletions

View File

@ -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. 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. 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.

View File

@ -0,0 +1,5 @@
package li.cil.oc.client.renderer.markdown
object MarkupFormat extends Enumeration {
val Markdown, IGWMod = Value
}

View File

@ -1,6 +1,7 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.markdown.Document import li.cil.oc.client.renderer.markdown.Document
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.FontRenderer
trait BasicTextSegment extends Segment { trait BasicTextSegment extends Segment {
@ -38,6 +39,8 @@ trait BasicTextSegment extends Segment {
lines * lineHeight(renderer) lines * lineHeight(renderer)
} }
override def toString(format: MarkupFormat.Value): String = text
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
protected def text: String protected def text: String

View File

@ -1,9 +1,13 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.util.EnumChatFormatting import net.minecraft.util.EnumChatFormatting
private[markdown] class BoldSegment(parent: Segment, text: String) extends TextSegment(parent, text) { private[markdown] class BoldSegment(parent: Segment, text: String) extends TextSegment(parent, text) {
override protected def format = EnumChatFormatting.BOLD.toString 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{}]"
}
} }

View File

@ -1,6 +1,7 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.TextBufferRenderCache import li.cil.oc.client.renderer.TextBufferRenderCache
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.FontRenderer
import org.lwjgl.opengl.GL11 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 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{}]"
}
} }

View File

@ -1,5 +1,6 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.util.EnumChatFormatting import net.minecraft.util.EnumChatFormatting
private[markdown] class HeaderSegment(parent: Segment, text: String, val level: Int) extends TextSegment(parent, text) { 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 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{}]"
}
} }

View File

@ -1,9 +1,13 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.util.EnumChatFormatting import net.minecraft.util.EnumChatFormatting
private[markdown] class ItalicSegment(parent: Segment, text: String) extends TextSegment(parent, text) { private[markdown] class ItalicSegment(parent: Segment, text: String) extends TextSegment(parent, text) {
override protected def format = EnumChatFormatting.ITALIC.toString 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{}]"
}
} }

View File

@ -3,8 +3,10 @@ package li.cil.oc.client.renderer.markdown.segment
import java.net.URI import java.net.URI
import li.cil.oc.Localization import li.cil.oc.Localization
import li.cil.oc.OpenComputers
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.client.Manual import li.cil.oc.client.Manual
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
private[markdown] class LinkSegment(parent: Segment, text: String, val url: String) extends TextSegment(parent, text) with InteractiveSegment { 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{}]"
}
} }

View File

@ -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.ImageRenderer
import li.cil.oc.api.manual.InteractiveImageRenderer import li.cil.oc.api.manual.InteractiveImageRenderer
import li.cil.oc.client.renderer.markdown.Document import li.cil.oc.client.renderer.markdown.Document
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.FontRenderer
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
@ -74,5 +75,8 @@ private[markdown] class RenderSegment(val parent: Segment, val title: String, va
hovered 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
}
} }

View File

@ -1,8 +1,10 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.client.gui.FontRenderer import net.minecraft.client.gui.FontRenderer
import scala.annotation.tailrec import scala.annotation.tailrec
import scala.collection.mutable
import scala.util.matching.Regex import scala.util.matching.Regex
trait Segment { 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 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. // Used during construction, checks a segment for inner segments.

View File

@ -1,9 +1,13 @@
package li.cil.oc.client.renderer.markdown.segment package li.cil.oc.client.renderer.markdown.segment
import li.cil.oc.client.renderer.markdown.MarkupFormat
import net.minecraft.util.EnumChatFormatting import net.minecraft.util.EnumChatFormatting
private[markdown] class StrikethroughSegment(parent: Segment, text: String) extends TextSegment(parent, text) { private[markdown] class StrikethroughSegment(parent: Segment, text: String) extends TextSegment(parent, text) {
override protected def format = EnumChatFormatting.STRIKETHROUGH.toString 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{}]"
}
} }

View File

@ -96,6 +96,4 @@ private[markdown] class TextSegment(val parent: Segment, val text: String) exten
case _ => None case _ => None
} }
} }
override def toString: String = s"{TextSegment: text = $text}"
} }

View File

@ -32,9 +32,9 @@ import net.minecraft.world.World
import scala.collection.mutable import scala.collection.mutable
object Items extends ItemAPI { 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 override def get(name: String): ItemInfo = descriptors.get(name).orNull

View File

@ -44,6 +44,7 @@ object Mods {
val GregTech = new ClassBasedMod(IDs.GregTech, "gregtech.api.GregTech_API")() val GregTech = new ClassBasedMod(IDs.GregTech, "gregtech.api.GregTech_API")()
val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2, providesPower = true) val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2, providesPower = true)
val IndustrialCraft2Classic = new SimpleMod(IDs.IndustrialCraft2Classic, 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 Mekanism = new SimpleMod(IDs.Mekanism, providesPower = true)
val Minecraft = new SimpleMod(IDs.Minecraft) val Minecraft = new SimpleMod(IDs.Minecraft)
val MineFactoryReloaded = new SimpleMod(IDs.MineFactoryReloaded) val MineFactoryReloaded = new SimpleMod(IDs.MineFactoryReloaded)
@ -114,9 +115,13 @@ object Mods {
// being used rather than other more concrete implementations. // being used rather than other more concrete implementations.
integration.computercraft.ModComputerCraft, 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. // 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 = { def init(): Unit = {
@ -166,6 +171,7 @@ object Mods {
final val GregTech = "gregtech" final val GregTech = "gregtech"
final val IndustrialCraft2 = "IC2" final val IndustrialCraft2 = "IC2"
final val IndustrialCraft2Classic = "IC2-Classic" final val IndustrialCraft2Classic = "IC2-Classic"
final val IngameWiki = "IGWMod"
final val Mekanism = "Mekanism" final val Mekanism = "Mekanism"
final val Minecraft = "Minecraft" final val Minecraft = "Minecraft"
final val MineFactoryReloaded = "MineFactoryReloaded" final val MineFactoryReloaded = "MineFactoryReloaded"

View File

@ -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()
}
}

View File

@ -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
}
}
}
}