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