From bd25a87db3328f83767db0b1d86605f3bd88afc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 11 Jul 2021 20:46:31 +0200 Subject: [PATCH] Add manual. --- build.gradle | 9 ++- gradle.properties | 1 + .../li/cil/oc2/client/manual/Manuals.java | 55 +++++++++++++++++ .../client/manual/ModManualScreenStyle.java | 58 ++++++++++++++++++ .../cil/oc2/client/manual/ModManualStyle.java | 54 ++++++++++++++++ .../cil/oc2/client/manual/package-info.java | 7 +++ .../renderer/font/TerminalFontRenderer.java | 49 +++++++++++++++ .../client/renderer/font/package-info.java | 7 +++ src/main/java/li/cil/oc2/common/Main.java | 4 ++ .../java/li/cil/oc2/common/item/Items.java | 1 + .../li/cil/oc2/common/item/ManualItem.java | 53 ++++++++++++++++ .../li/cil/oc2/data/ModItemModelProvider.java | 1 + src/main/resources/META-INF/mods.toml | 7 ++- .../resources/assets/oc2/doc/en_us/index.md | 15 +++++ src/main/resources/assets/oc2/lang/en_us.json | 6 ++ .../assets/oc2/models/item/manual.json | 6 ++ .../oc2/textures/font/terminus_simple.png | Bin 0 -> 3601 bytes .../assets/oc2/textures/gui/manual/home.png | Bin 0 -> 1904 bytes .../assets/oc2/textures/gui/manual/manual.png | Bin 0 -> 3014 bytes .../oc2/textures/gui/manual/scroll_button.png | Bin 0 -> 1854 bytes .../oc2/textures/gui/manual/tab_button.png | Bin 0 -> 2093 bytes .../assets/oc2/textures/item/manual.png | Bin 0 -> 432 bytes 22 files changed, 329 insertions(+), 4 deletions(-) create mode 100644 src/main/java/li/cil/oc2/client/manual/Manuals.java create mode 100644 src/main/java/li/cil/oc2/client/manual/ModManualScreenStyle.java create mode 100644 src/main/java/li/cil/oc2/client/manual/ModManualStyle.java create mode 100644 src/main/java/li/cil/oc2/client/manual/package-info.java create mode 100644 src/main/java/li/cil/oc2/client/renderer/font/TerminalFontRenderer.java create mode 100644 src/main/java/li/cil/oc2/client/renderer/font/package-info.java create mode 100644 src/main/java/li/cil/oc2/common/item/ManualItem.java create mode 100644 src/main/resources/assets/oc2/doc/en_us/index.md create mode 100644 src/main/resources/assets/oc2/models/item/manual.json create mode 100644 src/main/resources/assets/oc2/textures/font/terminus_simple.png create mode 100644 src/main/resources/assets/oc2/textures/gui/manual/home.png create mode 100644 src/main/resources/assets/oc2/textures/gui/manual/manual.png create mode 100644 src/main/resources/assets/oc2/textures/gui/manual/scroll_button.png create mode 100644 src/main/resources/assets/oc2/textures/gui/manual/tab_button.png create mode 100644 src/main/resources/assets/oc2/textures/item/manual.png diff --git a/build.gradle b/build.gradle index 7e86e00f..06a4950f 100644 --- a/build.gradle +++ b/build.gradle @@ -60,6 +60,9 @@ dependencies { implementation 'li.cil.sedna:sedna:0.0.1+99' implementation 'li.cil.sedna:sedna-buildroot:0.0.1+15' + compileOnly fg.deobf("li.cil.markdown_manual:MarkdownManual:MC${minecraft_version}-Forge-${manual_version}:api") + runtimeOnly fg.deobf("li.cil.markdown_manual:MarkdownManual:MC${minecraft_version}-Forge-${manual_version}") + compileOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}:api") runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}:${jei_version}") @@ -89,7 +92,8 @@ processResources { 'mod_issues_url' : mod_issues_url, 'forge_version_min' : forge_version_min, 'minecraft_version_min': minecraft_version_min, - 'oc2_sedna_version_min': oc2_sedna_version_min + 'oc2_sedna_version_min': oc2_sedna_version_min, + 'manual_version_min' : manual_version, ]) } } @@ -142,11 +146,9 @@ minecraft { } task copyGeneratedResources(type: Copy) { - dependsOn { runData } from "src/generated" into "src/main" exclude "resources/.cache" - exclude "resources/assets/oc2/models/block" } jar { @@ -179,6 +181,7 @@ artifacts { publishing { publications { mavenJava(MavenPublication) { + version "MC${minecraft_version}-Forge-${version}" artifact jar artifact apiJar } diff --git a/gradle.properties b/gradle.properties index 7fe82b3c..461323af 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,7 @@ version_minor=0 version_patch=1 oc2_sedna_version_min=0.0.1 +manual_version=1.0.1+ jei_minecraft_version=1.16.4 jei_version=7.6.1.71 diff --git a/src/main/java/li/cil/oc2/client/manual/Manuals.java b/src/main/java/li/cil/oc2/client/manual/Manuals.java new file mode 100644 index 00000000..caf8d403 --- /dev/null +++ b/src/main/java/li/cil/oc2/client/manual/Manuals.java @@ -0,0 +1,55 @@ +package li.cil.oc2.client.manual; + +import li.cil.manual.api.ManualModel; +import li.cil.manual.api.Tab; +import li.cil.manual.api.prefab.Manual; +import li.cil.manual.api.prefab.provider.NamespaceContentProvider; +import li.cil.manual.api.prefab.provider.NamespacePathProvider; +import li.cil.manual.api.prefab.tab.ItemStackTab; +import li.cil.manual.api.prefab.tab.TextureTab; +import li.cil.manual.api.provider.ContentProvider; +import li.cil.manual.api.provider.PathProvider; +import li.cil.oc2.api.API; +import li.cil.oc2.common.block.Blocks; +import li.cil.oc2.common.item.Items; +import li.cil.oc2.common.util.RegistryUtils; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.RegistryObject; +import net.minecraftforge.registries.DeferredRegister; + +@OnlyIn(Dist.CLIENT) +public final class Manuals { + private static final DeferredRegister MANUALS = RegistryUtils.create(ManualModel.class); + + /////////////////////////////////////////////////////////////////// + + public static final RegistryObject MANUAL = MANUALS.register("manual", Manual::new); + + /////////////////////////////////////////////////////////////////// + + public static void initialize() { + final DeferredRegister pathProviders = RegistryUtils.create(PathProvider.class); + final DeferredRegister contentProviders = RegistryUtils.create(ContentProvider.class); + final DeferredRegister tabs = RegistryUtils.create(Tab.class); + + pathProviders.register("path_provider", () -> new NamespacePathProvider(API.MOD_ID)); + contentProviders.register("content_provider", () -> new NamespaceContentProvider(API.MOD_ID, "doc")); + + tabs.register("home", () -> new TextureTab( + ManualModel.LANGUAGE_KEY + "/index.md", + new TranslationTextComponent("manual." + API.MOD_ID + ".home"), + new ResourceLocation(API.MOD_ID, "textures/gui/manual/home.png"))); + tabs.register("blocks", () -> new ItemStackTab( + ManualModel.LANGUAGE_KEY + "/block/index.md", + new TranslationTextComponent("manual." + API.MOD_ID + ".blocks"), + new ItemStack(Blocks.COMPUTER.get()))); + tabs.register("modules", () -> new ItemStackTab( + ManualModel.LANGUAGE_KEY + "/item/index.md", + new TranslationTextComponent("manual." + API.MOD_ID + ".items"), + new ItemStack(Items.TRANSISTOR.get()))); + } +} diff --git a/src/main/java/li/cil/oc2/client/manual/ModManualScreenStyle.java b/src/main/java/li/cil/oc2/client/manual/ModManualScreenStyle.java new file mode 100644 index 00000000..288d9c39 --- /dev/null +++ b/src/main/java/li/cil/oc2/client/manual/ModManualScreenStyle.java @@ -0,0 +1,58 @@ +package li.cil.oc2.client.manual; + +import li.cil.manual.api.ManualScreenStyle; +import li.cil.oc2.api.API; +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public final class ModManualScreenStyle implements ManualScreenStyle { + public static final ManualScreenStyle INSTANCE = new ModManualScreenStyle(); + + @Override + public ResourceLocation getWindowBackground() { + return new ResourceLocation(API.MOD_ID, "textures/gui/manual/manual.png"); + } + + @Override + public ResourceLocation getScrollButtonTexture() { + return new ResourceLocation(API.MOD_ID, "textures/gui/manual/scroll_button.png"); + } + + @Override + public ResourceLocation getTabButtonTexture() { + return new ResourceLocation(API.MOD_ID, "textures/gui/manual/tab_button.png"); + } + + @Override + public Rectangle2d getDocumentRect() { + return new Rectangle2d(12, 12, 216, 232); + } + + @Override + public Rectangle2d getScrollBarRect() { + return new Rectangle2d(236, 8, 12, 240); + } + + @Override + public Rectangle2d getScrollButtonRect() { + return new Rectangle2d(0, 0, 12, 12); + } + + @Override + public Rectangle2d getTabAreaRect() { + return new Rectangle2d(-52, 12, 52, 232); + } + + @Override + public Rectangle2d getTabRect() { + return new Rectangle2d(0, 0, 64, 24); + } + + @Override + public int getTabOverlap() { + return 0; + } +} diff --git a/src/main/java/li/cil/oc2/client/manual/ModManualStyle.java b/src/main/java/li/cil/oc2/client/manual/ModManualStyle.java new file mode 100644 index 00000000..cc0dfd64 --- /dev/null +++ b/src/main/java/li/cil/oc2/client/manual/ModManualStyle.java @@ -0,0 +1,54 @@ +package li.cil.oc2.client.manual; + +import li.cil.manual.api.ManualStyle; +import li.cil.manual.api.render.FontRenderer; +import li.cil.oc2.client.renderer.font.TerminalFontRenderer; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.SoundEvents; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public final class ModManualStyle implements ManualStyle { + public static final ManualStyle INSTANCE = new ModManualStyle(); + + @Override + public int getRegularTextColor() { + return 0xFFDDDDDD; + } + + @Override + public int getMonospaceTextColor() { + return 0xFF37FF99; + } + + @Override + public int getRegularLinkColor() { + return 0xFF9CC6E7; + } + + @Override + public int getHoveredLinkColor() { + return 0xFFBADCF7; + } + + @Override + public int getRegularDeadLinkColor() { + return 0xFFFF3755; + } + + @Override + public int getHoveredDeadLinkColor() { + return 0xFFFF8497; + } + + @Override + public FontRenderer getMonospaceFont() { + return TerminalFontRenderer.INSTANCE; + } + + @Override + public SoundEvent getPageChangeSound() { + return SoundEvents.UI_BUTTON_CLICK; + } +} diff --git a/src/main/java/li/cil/oc2/client/manual/package-info.java b/src/main/java/li/cil/oc2/client/manual/package-info.java new file mode 100644 index 00000000..ca483892 --- /dev/null +++ b/src/main/java/li/cil/oc2/client/manual/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package li.cil.oc2.client.manual; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/li/cil/oc2/client/renderer/font/TerminalFontRenderer.java b/src/main/java/li/cil/oc2/client/renderer/font/TerminalFontRenderer.java new file mode 100644 index 00000000..e42d0706 --- /dev/null +++ b/src/main/java/li/cil/oc2/client/renderer/font/TerminalFontRenderer.java @@ -0,0 +1,49 @@ +package li.cil.oc2.client.renderer.font; + +import li.cil.manual.api.prefab.renderer.BitmapFontRenderer; +import li.cil.manual.api.render.FontRenderer; +import li.cil.oc2.api.API; +import li.cil.oc2.common.vm.Terminal; +import net.minecraft.util.ResourceLocation; + +public final class TerminalFontRenderer extends BitmapFontRenderer { + public static final FontRenderer INSTANCE = new TerminalFontRenderer(); + + private static final ResourceLocation LOCATION_FONT_TEXTURE = new ResourceLocation(API.MOD_ID, "textures/font/terminus_simple.png"); + private static final String CHARS = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + + @Override + protected CharSequence getCharacters() { + return CHARS; + } + + @Override + protected ResourceLocation getTextureLocation() { + return LOCATION_FONT_TEXTURE; + } + + @Override + protected int getResolution() { + return 128; + } + + @Override + protected int getGapU() { + return 0; + } + + @Override + protected int getGapV() { + return 0; + } + + @Override + protected int charWidth() { + return Terminal.CHAR_WIDTH; + } + + @Override + public int lineHeight() { + return Terminal.CHAR_HEIGHT; + } +} diff --git a/src/main/java/li/cil/oc2/client/renderer/font/package-info.java b/src/main/java/li/cil/oc2/client/renderer/font/package-info.java new file mode 100644 index 00000000..03728289 --- /dev/null +++ b/src/main/java/li/cil/oc2/client/renderer/font/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package li.cil.oc2.client.renderer.font; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/li/cil/oc2/common/Main.java b/src/main/java/li/cil/oc2/common/Main.java index dacacc93..a05d8bd5 100644 --- a/src/main/java/li/cil/oc2/common/Main.java +++ b/src/main/java/li/cil/oc2/common/Main.java @@ -3,6 +3,7 @@ package li.cil.oc2.common; import li.cil.ceres.Ceres; import li.cil.oc2.api.API; import li.cil.oc2.client.ClientSetup; +import li.cil.oc2.client.manual.Manuals; import li.cil.oc2.common.block.Blocks; import li.cil.oc2.common.bus.device.DeviceTypes; import li.cil.oc2.common.bus.device.data.BlockDeviceDataRegistration; @@ -16,6 +17,7 @@ import li.cil.oc2.common.serialization.serializers.Serializers; import li.cil.oc2.common.tags.BlockTags; import li.cil.oc2.common.tags.ItemTags; import li.cil.oc2.common.tileentity.TileEntities; +import li.cil.oc2.common.util.RegistryUtils; import li.cil.oc2.common.util.SoundEvents; import li.cil.sedna.Sedna; import net.minecraftforge.api.distmarker.Dist; @@ -50,6 +52,8 @@ public final class Main { BlockDeviceDataRegistration.initialize(); Firmwares.initialize(); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> Manuals::initialize); + RegistryUtils.finish(); FMLJavaModLoadingContext.get().getModEventBus().register(CommonSetup.class); diff --git a/src/main/java/li/cil/oc2/common/item/Items.java b/src/main/java/li/cil/oc2/common/item/Items.java index ad42037c..868753fb 100644 --- a/src/main/java/li/cil/oc2/common/item/Items.java +++ b/src/main/java/li/cil/oc2/common/item/Items.java @@ -33,6 +33,7 @@ public final class Items { /////////////////////////////////////////////////////////////////// public static final RegistryObject WRENCH = register("wrench", WrenchItem::new); + public static final RegistryObject MANUAL = register("manual", ManualItem::new); public static final RegistryObject NETWORK_CABLE = register("network_cable", NetworkCableItem::new); public static final RegistryObject ROBOT = register("robot", RobotItem::new); diff --git a/src/main/java/li/cil/oc2/common/item/ManualItem.java b/src/main/java/li/cil/oc2/common/item/ManualItem.java new file mode 100644 index 00000000..0c2d51c2 --- /dev/null +++ b/src/main/java/li/cil/oc2/common/item/ManualItem.java @@ -0,0 +1,53 @@ +package li.cil.oc2.common.item; + +import li.cil.manual.api.ManualModel; +import li.cil.manual.api.ManualScreenStyle; +import li.cil.manual.api.ManualStyle; +import li.cil.manual.api.prefab.item.AbstractManualItem; +import li.cil.oc2.client.manual.Manuals; +import li.cil.oc2.client.manual.ModManualScreenStyle; +import li.cil.oc2.client.manual.ModManualStyle; +import li.cil.oc2.common.util.TooltipUtils; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import javax.annotation.Nullable; +import java.util.List; + +public final class ManualItem extends AbstractManualItem { + public ManualItem() { + super(new Properties().tab(ItemGroup.COMMON)); + } + + /////////////////////////////////////////////////////////////////// + + @OnlyIn(Dist.CLIENT) + @Override + public void appendHoverText(final ItemStack stack, @Nullable final World world, final List tooltip, final ITooltipFlag flag) { + super.appendHoverText(stack, world, tooltip, flag); + TooltipUtils.tryAddDescription(stack, tooltip); + } + + /////////////////////////////////////////////////////////////////// + + @Override + protected ManualModel getManualModel() { + return Manuals.MANUAL.get(); + } + + @OnlyIn(Dist.CLIENT) + @Override + protected ManualStyle getManualStyle() { + return ModManualStyle.INSTANCE; + } + + @OnlyIn(Dist.CLIENT) + @Override + protected ManualScreenStyle getScreenStyle() { + return ModManualScreenStyle.INSTANCE; + } +} diff --git a/src/main/java/li/cil/oc2/data/ModItemModelProvider.java b/src/main/java/li/cil/oc2/data/ModItemModelProvider.java index d1be7827..821f4f9e 100644 --- a/src/main/java/li/cil/oc2/data/ModItemModelProvider.java +++ b/src/main/java/li/cil/oc2/data/ModItemModelProvider.java @@ -19,6 +19,7 @@ public final class ModItemModelProvider extends ItemModelProvider { @Override protected void registerModels() { simple(Items.WRENCH); + simple(Items.MANUAL); simple(Items.NETWORK_CABLE); diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 9045c48f..c915d567 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -31,4 +31,9 @@ modId = "oc2-sedna" mandatory = true versionRange = "[${oc2_sedna_version_min},)" ordering = "NONE" -side = "BOTH" \ No newline at end of file +side = "BOTH" +[[dependencies.oc2]] +modId = "markdown_manual" +mandatory = true +versionRange = "[${manual_version_min},)" +side = "CLIENT" \ No newline at end of file diff --git a/src/main/resources/assets/oc2/doc/en_us/index.md b/src/main/resources/assets/oc2/doc/en_us/index.md new file mode 100644 index 00000000..3ef361d0 --- /dev/null +++ b/src/main/resources/assets/oc2/doc/en_us/index.md @@ -0,0 +1,15 @@ +# Manual +Content pending... + +- this is a list. lorem ipsum dolor sit amet and so on and so forth, just want to get a line break. +- end of list + +![block test](block:oc2:computer) + +Some `inline code` test. + +`local d = require('devices')` +`local r = d:find("redstone")` +`r:setRedstoneOutput("left", 15)` + +And finally, a [dead link](dead.md) and a [working one](index.md). diff --git a/src/main/resources/assets/oc2/lang/en_us.json b/src/main/resources/assets/oc2/lang/en_us.json index 75e4c6d6..2752a57a 100644 --- a/src/main/resources/assets/oc2/lang/en_us.json +++ b/src/main/resources/assets/oc2/lang/en_us.json @@ -17,6 +17,8 @@ "item.oc2.wrench": "Scrench", "item.oc2.wrench.desc": "Used to configure devices and to dismantle them (while sneaking).", + "item.oc2.manual": "Manual", + "item.oc2.manual.desc": "Obtain by using a book on a computer casing in the world.", "item.oc2.bus_interface": "Bus Interface", "item.oc2.bus_interface.desc": "Used to attach Bus Cables to external devices.", "item.oc2.network_cable": "Network Cable", @@ -66,6 +68,10 @@ "gui.oc2.file_chooser.confirm_button.overwrite": "Overwrite", "gui.oc2.file_chooser.cancel_button": "Cancel", + "manual.oc2.home": "Home", + "manual.oc2.blocks": "Blocks", + "manual.oc2.items": "Items", + "message.oc2.connector.error.full": "Cannot attach more cables.", "message.oc2.connector.error.too_far": "Distance between connectors is too large.", "message.oc2.connector.error.obstructed": "No clear line of sight between connectors.", diff --git a/src/main/resources/assets/oc2/models/item/manual.json b/src/main/resources/assets/oc2/models/item/manual.json new file mode 100644 index 00000000..450243b2 --- /dev/null +++ b/src/main/resources/assets/oc2/models/item/manual.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "oc2:item/manual" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/oc2/textures/font/terminus_simple.png b/src/main/resources/assets/oc2/textures/font/terminus_simple.png new file mode 100644 index 0000000000000000000000000000000000000000..110e5a1bd2c7a2152edc9e1ca49ea420cc1cb4ba GIT binary patch literal 3601 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 F`CtC|mPr5r literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/oc2/textures/gui/manual/home.png b/src/main/resources/assets/oc2/textures/gui/manual/home.png new file mode 100644 index 0000000000000000000000000000000000000000..fc2b64c2eac9f885fb5129034cdcf6021d72d56c GIT binary patch literal 1904 zcmah~eM}Q)96lxzSLntR9ezZPa~d~nuPqeh=)vfRQlU*PI6nM5+iN*!d$o7if}2qo zb0lt{fF?`<37}IV11C=AglLp(#t)Ea!nO!;W{xpgmB=;~_FjucMYlh$z4!M#zvumZ zz3-Liv@7|%c{~V$`06C39{dM$&x`=@8}?wFfFS>7DlLP}(4=4n+A1WB^k!1%vf2R- zL9zswoiOB*EWDXCQ#KqK{- z0V~N8u*+((F_;TSJh~Wo=gcSqdnjx!j$~+bu!44wuv91&ija67EOQu5m|nSJ!Wpb^ zB%5XJ7>YWbPN6eWNIT4^I5svG6-iKuL;x59Cf~*qE`g0%#7THHlq6$tP7%w!5_Gqc$^B949mNT-Z1+BqRh9@mLAHVSMlnRLmR#Bd}=0%m~gk7t|AmqJ{r zF&*V1Eg4G6O4=Bp>Wg9$%zOo?pe?i`6^u0roIHE^`ha;b4Q&KaaF~Y!A9Y^dA+L&h` zjh?iCoEK$i6YC@#WTF`~7)KIKCJOW?AJ%b`3yX!ZLT{&h4$f>6h`l;BbRsa6J8(}U zlc7^$mw5=!oKWEBwSkilt`O9Bhk%9e79wrn>T!TOCSXwX5Q6-6QlKkSx&c8;_vG#A zNS3b-=}O2U>Q|R3ii$p#W>)O%?Wr9JJetUF%^JB=+8I_lT2XeRR=V`ltbe4v8+EzY z7Wk{)Qm(zWu2=8I(CLfsZ@7ooJo@g}1y}I5o4T9!UjHHh-jC)Cl+>Ez+xlA)3|-;Z zi{p;p9ZWIGR-Jcm*>&OTn2$`yFK!=yqsyUB@9aTjM~`H!cIjOOCy!K}5e(@iZgL=% zs97?dcdM$P?i{-0aKvM>bq;@5XJ7b``sS9p&ntKDo3(HM?aO5Hs*?*JEWTpgE=1ba z?wfy5G|S&Dx)2)vT95?Uwj=)W$fc41_p}c8iI8_b*t5Q2_eCBh32~QX?Hy9LyxUza zIZ<(WZ2XU7)${JBx5gD+du$A)@lCf1hc)N_l11$vUi1}yPIY$9#^pN(oZT_GRnD-! zn*&3wjf=PTe>kmuVedC{#w#tYO<#tbseXTL5Y~Jsuchb2Al@|^yuQ4-z3^xJ?(Ff0 z4PkK+=AN;fMU#04W%u-LS1Na$9%a}HKVY% z_r}a9=}1t#934pZw`v7^Tz;%q$d@au+7-d;>f5R;tD>44^V+tJF=xj+{yePg?hLG3 z{-ipn{fDNWk;0{Cf2y8)bttN`?0{QXa|gdYI?^^1Ia+ZEuFE++0~xGX6U?vG&h1|| zyzJm?h`-~Bc+>Cgm43f91&C@i#blhg^Uiz8ml_W}C=0(=5Iz&?v`1;>W47{$wvp{i z%1`$*MQ?up$*E;OmS_}L{pK}{HrDrT2-Ma85_q_%6g_{g|J2`C3;Yh=G)zk&)LGnz NQmxV|kIOd|{tJDvtzZBE literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/oc2/textures/gui/manual/manual.png b/src/main/resources/assets/oc2/textures/gui/manual/manual.png new file mode 100644 index 0000000000000000000000000000000000000000..107dbfee75626c4cda05424d50a5931ced1ed7a0 GIT binary patch literal 3014 zcmai0d0Z1`8lHf7pdytj{uCiQc&FqNQWBB?CJ0o6h{&;m8j?wvg=At9ARGmRqSfL- z-PVe%c>UD6Dpii?f?@?_6*&~^2}nJN$_)y}aO}*4bCKOY^2^NkzVGur@AJIhm+bQO z@tkQs-y8sdnciM}KL8-0j|5<<3HnuI=}H5DNx86pkUB`PmL)=DWT6-dgUA}00*wOz z+f}0wiXtF2F$|Kzat_#5SPT+jF$WBE5>N#S9uy9H#VMf;aX$W{xCjwb47zg7*%}rK zAcNFGqDB@eSFto45XWVq&)6~rB;qOR2o4w|@FnsPB}8;0JCUg%*PO^!iX|*R{_4SE z^o;|CtJMk?g%T4JLylQVMwC(tjmczEsB{XQ?to@EsAA=6p~gY3vd18d7<@=2Qo;%~ zjL3-?rZ5bNQgc8MjS~mKAq_l&E>{hR>S9?_@}gQAY%G_--rKUM)z{2&z)r4&IP z(U4qik1K)c!t#YRP-GAvmO*kAsxAklJ2Cz%8az>yheRUE4d_@w9FT?=VcN00WkM+w z2#eL>BWNRmwUAsoE`qU(jKb{QD2LI0=p$%BBQXxhWT1nEnU3QHe>ODi1q^SQ5(@s?jVul}>Y@e(gY` z`qP|QGzN>tBvI)ss*w+#jh+XwP%Zp_`Pftw*=U78!197sYD5`}FBwOD1GLTfW_*o= z@fjx)ai>{A5hfA`R45T~ln4^zZJ}_+s0xv&V}we`U5c8_0o^4M7?m@Y=!;D+kw#{c zjlvEW#Dqhb86-x*4&4wlHf0=lHl8r*l%jRUHT3kO*9c|!9zkD*Zz4#JUO!6o zp1DZPB%^m(3XHlk&J6%qmJyXvMdGjjvdnezo?F!2W)N)}sr1aQJvY}T&Y8RN#0Dqf6Djce-nKt^D&j9t2lE=T-j3Fb>(?{)!Ta2@3XyD zEWaw8=lAwp5F1>2a*hD%T|ZJeiuEeILG^{<^+`&D( znDFeIE7D>^7Tawr@7lZh-QCBwRJsHt0ZUV)w;zzA;?ZA>X$r4k6#!V2Vjsd!B#Q+A zU`F!hyZdXhTI$xw=fm^d?wKDKgHZCL7c<2J<^MKWH8~??qt{!)_j_kVi+Y#Ev@-3d zxIECMl<$lE<8;oJVv8zAK~0+Ll{)#lbs^^iq)8f^vZjJgU4gAjSMGuKe^s{jPO)xM zbSySlSU-{E23wT0w>;Bo>t`pp?F4oRKX$$@FRyA1);{U!=_#Ss*4Abn>2D~lIlOP`J}2WD@eS_y;7ZR#iiX&On%+*+%>5` z;l%bMif9Vkxud1~L5;Nk)U&>I2b&KChtNyPotJNCp>RtM`HIpr2 z6QTe(IW5_duzv}LlnHoQ0mj9JCYshwSq*Jl&4{v##Vy6H6{p&hq-I#Y-u@Ry(qP)> zYQJQMXjw&C+?97NlfT$SN;{TxSLv70I>`-0LXu zJ%`J)(+jM?xpw(Y-M!atN7$H+FxX|RYwz7hOZiBywE{x9bJJLa>epn;sEL&x&F)R+ zDeuuJMniu1<8MwqGpGwN(T_&hc;ar&ed%1uF}-`s-0f*t=BX>vv31>BN>6&%Zm3^2Kp8>yq|N=uJ;7E*VHciR=w*l@%qO(onU+5lQjp|b=K;dvkgE`>K2{) zw@33EZuE8QfPJ!0i)X!{WII*tRA%Yl{pnhXe5+s7#_oFCD6wg9U|g+@WUS;ig(Hit!y7DT0PDj(DoEj^;X1%nfYe0QF?NZN*b&t3oL;DGr XA3GNYd)_>V{r&d#@Zn!rwKe5G?!9x) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/oc2/textures/gui/manual/scroll_button.png b/src/main/resources/assets/oc2/textures/gui/manual/scroll_button.png new file mode 100644 index 0000000000000000000000000000000000000000..03323244215f24913d68e824a1d541e7835d73e6 GIT binary patch literal 1854 zcmah~4NMbf7(VAj`BCu?8p+)4V4H&NU5f>K>xtNc)KRQZrAFsG+G~5U?VY^?+OmLl z%nU^nqb-azqi9%Z9l1ahao5rJt7f#fRnn4Z;8b~?l7rgD5)Mze2&S!F>|7KN!j zI1q4BJPCW84i|@e2t?Gy!GFPwBCtr|HxP(PZ-6z7n}U@xr3^zBg~4jK#foQZ(?^`a zia_i<&*CUrSXd}4Oq4Nh8!A_+R4ArE6$&X}NI9>ICp}UZ7b{2vG_(|FcGE0RGcH)r zB=eYjocbc!skxY%qZ*wg|#w z96|Y>?&2ZYr;+vg|E4>gPo%-|X$7DVBSn28rbioaMlVaD*%Zg*yUkQu0p;Rj#YzZu z!40&Ba+tKVlX7vOx&$Iu{0m(D7^qk<3ThY!>I)n(hi$}FB0m3Sy3DUm7uc;K#&c}0KvV!_tw zF^y3}6C8W$vbD?Vx5#5)o_gUJ0zy9ahpNraiI=H6k8S(SZk&^75ny&r#7QW}d zlyxh7m816RJH+9ey$vPti}iyIN7~BIylwsThwkCJt_)-Dfnz$)k`;9|edT@EeXEq- zrJrkbrO0{P`SBHN4forwHB-e()w(WbSKX%e@V!Z-tzm2P%9^;^-6t9w-Cz-zdtWlVi&--L^(XYfe_B53}=1HkaRsSA25giYYeBKYx5x z*I}PAFSEb8JkERSVaedp*7P@i>n)hNU{TD4q8CkP4w|s?os5W z&c1i=;G1o)ttx?D_1nI_mXKcr-WH*3#%d0NrnCspxIGC|Vu108PMd0+yVG2I`m}Yu z@VS4tb7E;zQ`6@8fAsg{M1_QG>2Cip@t2U4l3~mF*vS(!*)@Go)TFV=)8O=rf4rbbKw2>&Qm)i$*G+JGqN78TE4E~rJwM>FT4Pm X>usC5r%vb*UVFN;3-#R*{y! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/oc2/textures/gui/manual/tab_button.png b/src/main/resources/assets/oc2/textures/gui/manual/tab_button.png new file mode 100644 index 0000000000000000000000000000000000000000..d74d300f9688c3a73465c94cc0ff356adc5e6940 GIT binary patch literal 2093 zcmah~X;c$e6drInLKLl4;fUfeP|ISHNgyoKge?IQB#3|z3NC?6k~u&oCIciWqEW0M z_S9Wb&r#g1Xlp@4P+Y-ci>2Blt%_PL;2Jzy6jA7#1VO8|KeD{{efOJtzkA=CqS%2P6o14qZ^!jZ|XZay?KB>!KlUAak!q$)}`a&Ik<*$vp7Nf zg2fUBJX0njvT%(axGO;XeE$U|zXkdR41z*3lhnn7p~3|S$Ffa3he@*JDm;l$Q0f7# z!To4lqoRR+9ScBbmYGerc9wzvBGd}yh-1!#5TPGC6S@*!n2UiGt;0^(cfm;aIfU8Fb?wHV^uVz4y zjfntVd9ND~CyL5xENwvr?LY6^tY~_4{b}{h1()u%>Q9dqdwHIaJH_2Q z*tVrBV58|`%mYSZX2q|Cf?XZ=YYV(Wq&>BJn@XydD$D<9@2zYTCnRk@Br$}|tUTCR z(s?~Ek!OrNCX_5g&Zy1|DNT)i(RAf3zK9n%r;S`&x%d)egP&YgTYPrbLHCMv-_>qy zP2lc*)!MMINKiWG+4P5>m?Ih*d|kHw#4U34cPqL0P&vj?c%&?%SL<1@q~xv__uIS8 zGPfAhv>|0}yYdp!qMz+6aX0?ZSI~2yA!7Dl_j5-3207O+m?Ep%Awx?JyPfrL5x)L3 zb&q%VW}#Ehm=m$hd81E#Z`YnQo>|LqO!=jI-|~uB$pOczb7`G9_RLUqoz1nVYE@m& zR({Al;mP|GySjGFZTcdy0Q%gd`tgc)_5$#>u+xf@^$_H6j{exJ_jYgwE!rRvg(j$% zJlb?ZvlJcEaQMQ)k!YtapE3GcWXFcblV3u_?wrtVUam=|(=8(>vyNjnpD~AS-Py}r zUNfY(e(J`Wnj_OrpK;o`uI#c$ahZoLRL=XdW3lZmrz7g}8K%h7h8{27wrajKzC3&O zRa@x5f#WYWr3jeG|^e@2#ttl#*<7@`c^8sp2)~DwiiuN?d&3CP#ZCEckE8VN=mle(oN% zm#LTWJI`IVf7L^8_nLsOXXK6O5=!jqw@*(USEXF@`1oW0sE1CjyYI>*NdC>0WuQ`c zt(j52%*?oA^i!3)CYc%e;zh$wni9@QjJVtaVY@X>K1SAKe literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/oc2/textures/item/manual.png b/src/main/resources/assets/oc2/textures/item/manual.png new file mode 100644 index 0000000000000000000000000000000000000000..2a9960f2388ef53f671b0f601c7176f35c73bc6a GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8mH?j+SH~o`fV|MqqA0(GF_vL=_A~rCx;mow=XgvBU9)D* z?Afzjx&w^7&72no2ds!+c7Oe$Lx*Z-HoC8laA@{kczNaK`@73ewd%PV`Rs_i6iyJ^1LpYG3VFN(;Gc9FQkP#UXoM94Rd= z{r~@e&IbP;pnG&mg8YJkTw(#k@oStQeO;a|jv*DdTKZ24H97FG#v4f+uTgrS_fGo% z|N28bOQ(fS+gU0xV%uE}I=6JRO?x{ATm)z4*}Q$iB}0)o!e literal 0 HcmV?d00001