Skip to content

Commit

Permalink
Add books WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
fuj1n committed Jan 26, 2016
1 parent 2af4286 commit a769978
Show file tree
Hide file tree
Showing 45 changed files with 1,512 additions and 166 deletions.
6 changes: 6 additions & 0 deletions src/main/java/slimeknights/mantle/Mantle.java
Expand Up @@ -4,6 +4,7 @@
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.SidedProxy;

import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand Down Expand Up @@ -31,4 +32,9 @@ public class Mantle {
/* Proxies for sides, used for graphics processing */
@SidedProxy(clientSide = "slimeknights.mantle.client.ClientProxy", serverSide = "slimeknights.mantle.common.CommonProxy")
public static CommonProxy proxy;

@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event){
proxy.preInit();
}
}
5 changes: 5 additions & 0 deletions src/main/java/slimeknights/mantle/client/ClientProxy.java
@@ -1,6 +1,11 @@
package slimeknights.mantle.client;

import slimeknights.mantle.client.book.BookLoader;
import slimeknights.mantle.common.CommonProxy;

public class ClientProxy extends CommonProxy {
@Override
public void preInit() {
new BookLoader();
}
}
108 changes: 108 additions & 0 deletions src/main/java/slimeknights/mantle/client/book/BookLoader.java
@@ -0,0 +1,108 @@
package slimeknights.mantle.client.book;

import com.google.gson.Gson;
import java.util.HashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import slimeknights.mantle.client.book.data.BookData;
import slimeknights.mantle.client.book.data.content.ContentError;
import slimeknights.mantle.client.book.data.content.*;
import slimeknights.mantle.client.book.data.content.PageContent;
import slimeknights.mantle.client.gui.book.GuiBook;
import static slimeknights.mantle.client.book.ResourceHelper.setBookRoot;

/**
* @author fuj1n
*/
@SideOnly(Side.CLIENT)
public class BookLoader implements IResourceManagerReloadListener {

/** GSON object to be used for book loading purposes */
public static final Gson GSON = new Gson();

/** Maps page content presets to names */
private static final HashMap<String, Class<? extends PageContent>> typeToContentMap = new HashMap<>();

/** Internal registry of all books for the purposes of the reloader, maps books to name */
private static final HashMap<String, BookData> books = new HashMap<>();

public BookLoader() {
((IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager()).registerReloadListener(this);

registerPageType("blank", ContentBlank.class);
registerPageType("text", ContentText.class);
registerPageType("image", ContentImage.class);
registerPageType("image with text below", ContentImageText.class);
registerPageType("text with image below", ContentTextImage.class);
registerPageType("text with left image etch", ContentTextLeftImage.class);
registerPageType("text with right image etch", ContentTextRightImage.class);
}

/**
* Registers a type of page prefabricate
*
* @param name The name of the page type
* @param clazz The PageContent class for this page type
* @RecommendedInvoke init
*/
public static void registerPageType(String name, Class<? extends PageContent> clazz) {
if (typeToContentMap.containsKey(name))
throw new IllegalArgumentException("Page type " + name + " already in use.");

typeToContentMap.put(name, clazz);
}

/**
* Gets a type of page prefabricate by name
*
* @param name The name of the page type
* @return The class of the page type, ContentError.class if page type not registered
*/
public static Class<? extends PageContent> getPageType(String name) {
return typeToContentMap.getOrDefault(name, ContentError.class);
}

/**
* Adds a book to the loader, and returns a reference object
* Be warned that the returned BookData object is not immediately populated, and is instead populated when the resources are loaded/reloaded
*
* @param name The name of the book, modid: will be automatically appended to the front of the name unless that is already added
* @param location The location of the book folder, prefixed with the resource domain
* @return The book object, not immediately populated
*/
public static BookData registerBook(String name, String location) {
BookData info = new BookData(location);

books.put(name.contains(":") ? name : Loader.instance().activeModContainer().getModId() + ":" + name, info);

return info;
}

/**
* Returns the GuiScreen for the book
*
* @param name The name of the book, prefixed with modid:
* @return The GuiScreen to open for the book
*/
public static GuiBook getBookGui(String name) {
return null;
}

/**
* Reloads all the books, called when the resource manager reloads, such as when the resource pack or the language is changed
*/
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
for (BookData book : books.values()) {
setBookRoot(book.bookLocation);

book.pageCount = book.cascadeLoad();
book.fullPageCount = (int) Math.ceil((book.pageCount - 1) / 2F) + 1;
}
}
}
122 changes: 122 additions & 0 deletions src/main/java/slimeknights/mantle/client/book/ResourceHelper.java
@@ -0,0 +1,122 @@
package slimeknights.mantle.client.book;

import java.io.IOException;
import java.util.Iterator;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResource;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;

/**
* @author fuj1n
*/
@SideOnly(Side.CLIENT)
public class ResourceHelper {

private static String bookRoot;

private ResourceHelper() {
}

public static ResourceLocation getResourceLocation(String path) {
if (path == null)
return null;
if (!path.contains(":")) {
String langPath = Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode();
String defaultLangPath = "en_US";

ResourceLocation res = new ResourceLocation(bookRoot + "/" + langPath + "/" + path);
if (resourceExists(res))
return res;
res = new ResourceLocation(bookRoot + "/" + defaultLangPath + "/" + path);
if (resourceExists(res))
return res;
res = new ResourceLocation(bookRoot + "/" + path);
if (resourceExists(res))
return res;
return null;
} else {
ResourceLocation res = new ResourceLocation(path);
if (resourceExists(res))
return res;
return null;
}
}

public static IResource getResource(ResourceLocation loc) {
if (loc == null)
return null;
try {
return Minecraft.getMinecraft().getResourceManager().getResource(loc);
} catch (IOException e) {
return null;
}
}

public static boolean resourceExists(String location) {
return resourceExists(new ResourceLocation(location));
}

public static boolean resourceExists(ResourceLocation location) {
if (location == null)
return false;
try {
Minecraft.getMinecraft().getResourceManager().getResource(location);
return true;
} catch (IOException e) {
return false;
}
}

public static String resourceToString(IResource resource) {
return resourceToString(resource, true);
}

public static String resourceToString(IResource resource, boolean skipCommments) {
if (resource == null)
return "";
try {
Iterator iterator = IOUtils.readLines(resource.getInputStream(), Charsets.UTF_8).iterator();
StringBuilder builder = new StringBuilder();

boolean isLongComment = false;

while (iterator.hasNext()) {
String s = ((String) iterator.next()).trim();

// Comment skipper
if (skipCommments) {
if (isLongComment) {
if (s.endsWith("*/"))
isLongComment = false;
continue;
} else {
if (s.startsWith("/*")) {
isLongComment = true;
continue;
}
}
if (s.startsWith("//"))
continue;
}

builder.append(s);
}

String data = builder.toString().trim();

return data;
} catch (IOException e) {
e.printStackTrace();
}

return "";
}

public static void setBookRoot(String location) {
bookRoot = location;
}
}
67 changes: 67 additions & 0 deletions src/main/java/slimeknights/mantle/client/book/data/BookData.java
@@ -0,0 +1,67 @@
package slimeknights.mantle.client.book.data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import slimeknights.mantle.client.book.BookLoader;
import static slimeknights.mantle.client.book.ResourceHelper.getResource;
import static slimeknights.mantle.client.book.ResourceHelper.getResourceLocation;
import static slimeknights.mantle.client.book.ResourceHelper.resourceExists;
import static slimeknights.mantle.client.book.ResourceHelper.resourceToString;

/**
* @author fuj1n
*/
@SideOnly(Side.CLIENT)
public class BookData implements IDataItem {

public transient List<SectionData> sections = new ArrayList<SectionData>();
public transient CoverData cover = new CoverData();
public transient int pageCount;
public transient int fullPageCount;

public final transient String bookLocation;

public BookData(String bookLocation) {
this.bookLocation = bookLocation;
}

@Override
public int cascadeLoad() {
int pages = 0;

sections = Arrays.asList(BookLoader.GSON.fromJson(resourceToString(getResource(getResourceLocation("index.json"))), SectionData[].class));

ResourceLocation coverLocation = getResourceLocation("cover.json");

if (resourceExists(coverLocation))
cover = BookLoader.GSON.fromJson(resourceToString(getResource(getResourceLocation("cover.json"))), CoverData.class);
else
cover = new CoverData();

cover.cascadeLoad();

for (SectionData section : sections) {
pages += section.cascadeLoad();
}

cover.cascadeLoad();

return pages;
}

public PageData findPage(int number) {
int pages = 0;
for (SectionData section : sections) {
if (pages + section.pageCount > number)
return section.pages.get(number - pages);
else
pages += section.pageCount;
}

return null;
}
}
16 changes: 16 additions & 0 deletions src/main/java/slimeknights/mantle/client/book/data/CoverData.java
@@ -0,0 +1,16 @@
package slimeknights.mantle.client.book.data;

/**
* @author fuj1n
*/
public class CoverData implements IDataItem {

public int color = 0x8B4631;
public String title = "";
public String subtitle = "";

@Override
public int cascadeLoad() {
return 0;
}
}
13 changes: 13 additions & 0 deletions src/main/java/slimeknights/mantle/client/book/data/IDataItem.java
@@ -0,0 +1,13 @@
package slimeknights.mantle.client.book.data;

import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

/**
* @author fuj1n
*/
@SideOnly(Side.CLIENT)
public interface IDataItem {

int cascadeLoad();
}

0 comments on commit a769978

Please sign in to comment.