diff --git a/src/main/java/li/cil/oc/api/manual/ContentProvider.java b/src/main/java/li/cil/oc/api/manual/ContentProvider.java
index 36c33c5ee..f36b45440 100644
--- a/src/main/java/li/cil/oc/api/manual/ContentProvider.java
+++ b/src/main/java/li/cil/oc/api/manual/ContentProvider.java
@@ -7,6 +7,9 @@ package li.cil.oc.api.manual;
* arbitrary paths. Note that content providers have lower priority
* than content found in resource packs, i.e. content providers will only be
* queried for missing pages, so to speak.
+ *
+ *
+ * @see li.cil.oc.api.prefab.ResourceContentProvider
*/
public interface ContentProvider {
/**
diff --git a/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java b/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java
index 95d5ffd52..8a0225e27 100644
--- a/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java
+++ b/src/main/java/li/cil/oc/api/manual/TabIconRenderer.java
@@ -7,9 +7,9 @@ package li.cil.oc.api.manual;
* provide different graphics for different tabs you'll need to create
* multiple tab renderer instances.
*
- * See the prefabs {@link li.cil.oc.api.prefab.ItemStackTabIconRenderer} and
- * {@link li.cil.oc.api.prefab.IconTabIconRenderer} for simple standard
- * implementations.
+ *
+ * @see li.cil.oc.api.prefab.ItemStackTabIconRenderer
+ * @see li.cil.oc.api.prefab.TextureTabIconRenderer
*/
public interface TabIconRenderer {
/**
diff --git a/src/main/java/li/cil/oc/api/prefab/IconTabIconRenderer.java b/src/main/java/li/cil/oc/api/prefab/IconTabIconRenderer.java
deleted file mode 100644
index 66df1d0d7..000000000
--- a/src/main/java/li/cil/oc/api/prefab/IconTabIconRenderer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package li.cil.oc.api.prefab;
-
-import li.cil.oc.api.manual.TabIconRenderer;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.util.IIcon;
-
-/**
- * Simple implementation of a tab icon renderer using an icon as its graphic.
- */
-@SuppressWarnings("UnusedDeclaration")
-public class IconTabIconRenderer implements TabIconRenderer {
- private final IIcon icon;
-
- public IconTabIconRenderer(IIcon icon) {
- this.icon = icon;
- }
-
- @Override
- public void render() {
- final Tessellator t = Tessellator.instance;
- t.startDrawingQuads();
- t.addVertexWithUV(0, 16, 0, icon.getMinU(), icon.getMaxV());
- t.addVertexWithUV(16, 16, 0, icon.getMaxU(), icon.getMaxV());
- t.addVertexWithUV(16, 0, 0, icon.getMaxU(), icon.getMinV());
- t.addVertexWithUV(0, 0, 0, icon.getMinU(), icon.getMinV());
- t.draw();
- }
-}
diff --git a/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java b/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java
new file mode 100644
index 000000000..d1f9dc55d
--- /dev/null
+++ b/src/main/java/li/cil/oc/api/prefab/ResourceContentProvider.java
@@ -0,0 +1,64 @@
+package li.cil.oc.api.prefab;
+
+import li.cil.oc.api.manual.ContentProvider;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ResourceLocation;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+/**
+ * Basic implementation of a content provider based on Minecraft's resource
+ * loading framework.
+ *
+ * Beware that the manual is unaware of resource domains. In other words, two
+ * paths that are identical except for their resource domain will be the same,
+ * as seen from the manual. This means you should probably place your
+ * documentation somewhere other than doc/, because that's where the
+ * OpenComputers documentation lives, and it is queried first - meaning if you
+ * have a page with the same path as one in OpenComputers, it is practically
+ * unreachable (because the OC provider is always queried first).
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class ResourceContentProvider implements ContentProvider {
+ private final String resourceDomain;
+
+ private final String basePath;
+
+ public ResourceContentProvider(String resourceDomain, String basePath) {
+ this.resourceDomain = resourceDomain;
+ this.basePath = basePath;
+ }
+
+ public ResourceContentProvider(String resourceDomain) {
+ this(resourceDomain, "");
+ }
+
+ @Override
+ public Iterable getContent(String path) {
+ final ResourceLocation location = new ResourceLocation(resourceDomain, basePath + path);
+ InputStream is = null;
+ try {
+ is = Minecraft.getMinecraft().getResourceManager().getResource(location).getInputStream();
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ final ArrayList lines = new ArrayList();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ return lines;
+ } catch (Throwable ignored) {
+ return null;
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/scala/li/cil/oc/client/gui/Manual.scala b/src/main/scala/li/cil/oc/client/gui/Manual.scala
index 0cd100c71..8125c7aae 100644
--- a/src/main/scala/li/cil/oc/client/gui/Manual.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Manual.scala
@@ -64,9 +64,8 @@ class Manual extends GuiScreen {
}
def pushPage(path: String): Unit = {
- val resolvedPath = resolveLink(path, Manual.history.top.path)
- if (resolvedPath != Manual.history.top.path) {
- Manual.history.push(new Manual.History(resolvedPath))
+ if (path != Manual.history.top.path) {
+ Manual.history.push(new Manual.History(path))
refreshPage()
}
}
@@ -85,7 +84,7 @@ class Manual extends GuiScreen {
override def actionPerformed(button: GuiButton): Unit = {
if (button.id >= 0 && button.id < Manual.tabs.length) {
- pushPage(Manual.tabs(button.id).path)
+ api.Manual.navigate(Manual.tabs(button.id).path)
}
}
@@ -107,7 +106,7 @@ class Manual extends GuiScreen {
for ((tab, i) <- Manual.tabs.zipWithIndex if i < 7) {
val x = guiLeft + tabPosX
val y = guiTop + tabPosY + i * (tabHeight - 1)
- add(buttonList, new ImageButton(0, x, y, tabWidth, tabHeight, Textures.guiManualTab))
+ add(buttonList, new ImageButton(i, x, y, tabWidth, tabHeight, Textures.guiManualTab))
}
refreshPage()
@@ -160,7 +159,7 @@ class Manual extends GuiScreen {
// Left click, did we hit a link?
hoveredLink.foreach(link => {
if (link.startsWith("http://") || link.startsWith("https://")) handleUrl(link)
- else pushPage(link)
+ else pushPage(Manual.makeRelative(link, Manual.history.top.path))
})
}
else if (button == 1) {
diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala
index 92a90ea1a..d181f46e4 100644
--- a/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala
+++ b/src/main/scala/li/cil/oc/integration/opencomputers/ModOpenComputers.scala
@@ -1,9 +1,5 @@
package li.cil.oc.integration.opencomputers
-import java.io.InputStream
-import java.lang.Iterable
-
-import com.google.common.base.Charsets
import cpw.mods.fml.common.FMLCommonHandler
import cpw.mods.fml.common.event.FMLInterModComms
import li.cil.oc.Constants
@@ -12,8 +8,9 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.api.internal
-import li.cil.oc.api.manual.ContentProvider
import li.cil.oc.api.manual.PathProvider
+import li.cil.oc.api.prefab.ItemStackTabIconRenderer
+import li.cil.oc.api.prefab.ResourceContentProvider
import li.cil.oc.common.EventHandler
import li.cil.oc.common.Loot
import li.cil.oc.common.SaveHandler
@@ -31,17 +28,12 @@ import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.integration.util.WirelessRedstone
import li.cil.oc.server.network.WirelessNetwork
import li.cil.oc.util.ExtendedNBT._
-import net.minecraft.client.Minecraft
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.util.ResourceLocation
import net.minecraft.world.World
import net.minecraftforge.common.ForgeChunkManager
import net.minecraftforge.common.MinecraftForge
-import scala.collection.convert.WrapAsJava._
-import scala.io.Source
-
object ModOpenComputers extends ModProxy {
override def getMod = Mods.OpenComputers
@@ -206,7 +198,10 @@ object ModOpenComputers extends ModProxy {
}
api.Manual.addProvider(DefinitionPathProvider)
- api.Manual.addProvider(ResourceContentProvider)
+ api.Manual.addProvider(new ResourceContentProvider(Settings.resourceDomain))
+
+ api.Manual.addTab(new ItemStackTabIconRenderer(api.Items.get("case1").createItemStack(1)), "doc/%LANGUAGE%/block/index.md")
+ api.Manual.addTab(new ItemStackTabIconRenderer(api.Items.get("chip1").createItemStack(1)), "doc/%LANGUAGE%/item/index.md")
}
private def blacklistHost(host: Class[_], itemNames: String*) {
@@ -240,24 +235,4 @@ object ModOpenComputers extends ModProxy {
else "item/" + info.name + ".md"
}
- object ResourceContentProvider extends ContentProvider {
- override def getContent(path: String): Iterable[String] = {
- val location = new ResourceLocation(Settings.resourceDomain, path)
- var is: InputStream = null
- try {
- val resource = Minecraft.getMinecraft.getResourceManager.getResource(location)
- is = resource.getInputStream
- // Force resolving immediately via toArray, otherwise we return a read
- // iterator on a closed input stream (because of the finally).
- asJavaIterable(Source.fromInputStream(is)(Charsets.UTF_8).getLines().toArray.toIterable)
- }
- catch {
- case t: Throwable => null
- }
- finally {
- Option(is).foreach(_.close())
- }
- }
- }
-
}