diff --git a/build.gradle b/build.gradle
index 62a75a9..4d4eeed 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,7 +24,7 @@ apply from: './gradle/scripts/mixins.gradle'
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
-version = "1.8.5"
+version = "1.8.6"
group= "dev.tilera"
archivesBaseName = "auracore"
diff --git a/src/main/java/com/jadarstudios/developercapes/DevCapes.java b/src/main/java/com/jadarstudios/developercapes/DevCapes.java
new file mode 100644
index 0000000..ffedde8
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/DevCapes.java
@@ -0,0 +1,163 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import com.jadarstudios.developercapes.cape.CapeConfig;
+import com.jadarstudios.developercapes.cape.CapeConfigManager;
+import net.minecraftforge.common.MinecraftForge;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * DeveloperCapes is a library for Minecraft. It allows developers to quickly add capes
+ * for players they specify. DevCapes uses Minecraft Forge.
+ *
+ * @author jadar
+ */
+public class DevCapes {
+ private static DevCapes instance;
+
+ public static final Logger logger = LogManager.getLogger("DevCapes");
+
+ protected DevCapes() {
+ MinecraftForge.EVENT_BUS.register(new RenderEventHandler());
+ }
+
+ public static DevCapes getInstance() {
+ if (instance == null) {
+ instance = new DevCapes();
+ }
+ return instance;
+ }
+
+ /**
+ * InputStream.close() needs to be called on this after you're done!
+ *
+ * @return {@link InputStream} for the {@link URL}
+ */
+ public InputStream getStreamForURL(URL url) {
+ InputStream is = null;
+ try {
+ URLConnection connection = url.openConnection();
+ connection.setRequestProperty(
+ "User-Agent", System.getProperty("java.version")
+ );
+ connection.connect();
+
+ is = connection.getInputStream();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return is;
+ }
+
+ /**
+ * InputStream.close() needs to be called on this after you're done!
+ *
+ * @return {@link InputStream} for the {@link File}
+ */
+ public InputStream getStreamForFile(File file) {
+ InputStream is = null;
+ try {
+ is = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ return is;
+ }
+
+ @Deprecated
+ /**
+ * DEPRECATED: Please use {@link #registerConfig(String jsonUrl)} instead.
+ * Registers a config with DevCapes.
+ *
+ * @param jsonUrl
+ * The URL as a String that links to the Json file that you want
+ * to add
+ * @param identifier
+ * A unique Identifier, normally your mod id
+ * @return The id of the registered config
+ */
+ public int registerConfig(String jsonURL, String identifier) {
+ return this.registerConfig(jsonURL);
+ }
+
+ /**
+ * Registers a config with DevCapes.
+ *
+ * @param jsonUrl The URL as a String that links to the Json file that you want
+ * to add
+ * @return The id of the registered config
+ */
+ public int registerConfig(String jsonUrl) {
+ int id = -1;
+ try {
+ URL url = new URL(jsonUrl);
+ id = this.registerConfig(url);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return id;
+ }
+
+ @Deprecated
+ /**
+ * DEPRECATED: Please use {@link #registerConfig(URL url)} instead.
+ * Registers a config with DevCapes.
+ *
+ * @param jsonUrl
+ * A {@link URL} that links to the Json file that you want to add
+ * @param identifier
+ * A unique Identifier, normally your mod id
+ * @return The id of the registered config
+ */
+ public int registerConfig(URL url, String identifier) {
+ return this.registerConfig(url);
+ }
+
+ /**
+ * Registers a config with DevCapes and returns the ID of the config.
+ *
+ * @param jsonUrl A {@link URL} that links to the Json file that you want to add
+ * @return The id of the registered config
+ */
+ public int registerConfig(URL jsonUrl) {
+ int id = -1;
+ InputStream is = this.getStreamForURL(jsonUrl);
+
+ if (is == null) {
+ DevCapes.logger.error(String.format(
+ "Unable to establish a connection to the server, %s", jsonUrl.getHost()
+ ));
+ return id;
+ }
+
+ CapeConfig config = CapeConfigManager.getInstance().parse(is);
+
+ try {
+ id = CapeConfigManager.getUniqueId();
+ CapeConfigManager.getInstance().addConfig(id, config);
+ } catch (CapeConfigManager.InvalidCapeConfigIdException e) {
+ e.printStackTrace();
+ }
+
+ silentClose(is);
+
+ return id;
+ }
+
+ private static void silentClose(InputStream is) {
+ try {
+ is.close();
+ } catch (IOException ignored) {}
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/HDImageBuffer.java b/src/main/java/com/jadarstudios/developercapes/HDImageBuffer.java
new file mode 100644
index 0000000..912f2b1
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/HDImageBuffer.java
@@ -0,0 +1,41 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 3.3.0.0
+ */
+package com.jadarstudios.developercapes;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import net.minecraft.client.renderer.IImageBuffer;
+
+/**
+ * This class is an implementation of {@link IImageBuffer} that allows capes to be in HD
+ *
+ * @author Jadar
+ */
+@SideOnly(Side.CLIENT)
+public class HDImageBuffer implements IImageBuffer {
+ @Override
+ public BufferedImage parseUserSkin(final BufferedImage texture) {
+ if (texture == null)
+ return null;
+ int imageWidth = texture.getWidth(null) <= 64 ? 64 : texture.getWidth(null);
+ int imageHeight = texture.getHeight(null) <= 32 ? 32 : texture.getHeight(null);
+
+ BufferedImage capeImage = new BufferedImage(imageWidth, imageHeight, 2);
+
+ Graphics graphics = capeImage.getGraphics();
+ graphics.drawImage(texture, 0, 0, null);
+ graphics.dispose();
+
+ return capeImage;
+ }
+
+ @Override
+ public void func_152634_a() {}
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/RenderEventHandler.java b/src/main/java/com/jadarstudios/developercapes/RenderEventHandler.java
new file mode 100644
index 0000000..6ae5b16
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/RenderEventHandler.java
@@ -0,0 +1,40 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes;
+
+import com.jadarstudios.developercapes.cape.ICape;
+import com.jadarstudios.developercapes.user.User;
+import com.jadarstudios.developercapes.user.UserManager;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraftforge.client.event.RenderPlayerEvent;
+
+/**
+ * This is not the class you are looking for.
+ *
+ * @author jadar
+ */
+public class RenderEventHandler {
+ @SubscribeEvent
+ public void renderPlayer(RenderPlayerEvent.Specials.Pre event) {
+ AbstractClientPlayer player = (AbstractClientPlayer) event.entityPlayer;
+
+ UserManager manager = UserManager.getInstance();
+ User user = manager.getUser(player.getUniqueID().toString());
+ if (user == null)
+ return;
+
+ ICape cape = user.capes.get(0);
+ if (cape == null)
+ return;
+
+ boolean flag = cape.isTextureLoaded(player);
+ if (!flag) {
+ cape.loadTexture(player);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/cape/AbstractCape.java b/src/main/java/com/jadarstudios/developercapes/cape/AbstractCape.java
new file mode 100644
index 0000000..7424ce1
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/cape/AbstractCape.java
@@ -0,0 +1,42 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.cape;
+
+import net.minecraft.client.renderer.texture.ITextureObject;
+import net.minecraft.util.ResourceLocation;
+
+/**
+ * Abstract Implementation of ICape used within Dev. Capes
+ *
+ * @author jadar
+ */
+public abstract class AbstractCape implements ICape {
+ protected String name;
+ protected ITextureObject texture;
+ protected ResourceLocation location;
+
+ public AbstractCape(String name) {
+ this.name = name;
+ }
+
+ public AbstractCape() {}
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ITextureObject getTexture() {
+ return this.texture;
+ }
+
+ @Override
+ public ResourceLocation getLocation() {
+ return this.location;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/cape/CapeConfig.java b/src/main/java/com/jadarstudios/developercapes/cape/CapeConfig.java
new file mode 100644
index 0000000..ccdb38a
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/cape/CapeConfig.java
@@ -0,0 +1,27 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.cape;
+
+import java.util.HashMap;
+
+import com.jadarstudios.developercapes.user.Group;
+import com.jadarstudios.developercapes.user.User;
+
+/**
+ * The players that need to be outfitted are stored here
+ *
+ * @author jadar
+ */
+public class CapeConfig {
+ public HashMap groups;
+ public HashMap users;
+
+ public CapeConfig() {
+ groups = new HashMap();
+ users = new HashMap();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/cape/CapeConfigManager.java b/src/main/java/com/jadarstudios/developercapes/cape/CapeConfigManager.java
new file mode 100644
index 0000000..8157b53
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/cape/CapeConfigManager.java
@@ -0,0 +1,180 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.cape;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.BitSet;
+import java.util.Map;
+
+import com.google.common.collect.HashBiMap;
+import com.google.common.primitives.UnsignedBytes;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.jadarstudios.developercapes.DevCapes;
+import com.jadarstudios.developercapes.user.Group;
+import com.jadarstudios.developercapes.user.GroupManager;
+import com.jadarstudios.developercapes.user.User;
+import com.jadarstudios.developercapes.user.UserManager;
+import org.apache.commons.lang3.ObjectUtils;
+
+/**
+ * All configs need a manager, this is it.
+ *
+ * @author jadar
+ */
+public class CapeConfigManager {
+ protected static CapeConfigManager instance;
+
+ protected static BitSet availableIds = new BitSet(256);
+ protected HashBiMap configs;
+
+ static {
+ availableIds.clear(availableIds.size());
+ }
+
+ public CapeConfigManager() {
+ configs = HashBiMap.create();
+ }
+
+ public static CapeConfigManager getInstance() {
+ if (instance == null) {
+ instance = new CapeConfigManager();
+ }
+ return instance;
+ }
+
+ public void addConfig(int id, CapeConfig config) throws InvalidCapeConfigIdException {
+ int realId = claimId(id);
+ this.configs.put(realId, config);
+ addUsers(config.users);
+ addGroups(config.groups);
+ }
+
+ protected void addUsers(Map users) {
+ try {
+ UserManager.getInstance().addUsers(users.values());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void addGroups(Map groups) {
+ try {
+ GroupManager.getInstance().addGroups(groups.values());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public CapeConfig getConfig(int id) {
+ return this.configs.get(id);
+ }
+
+ public int getIdForConfig(CapeConfig config) {
+ return this.configs.inverse().get(config);
+ }
+
+ public static int getUniqueId() {
+ return availableIds.nextClearBit(1);
+ }
+
+ public static int claimId(int id) throws InvalidCapeConfigIdException {
+ if (id <= 0) {
+ throw new InvalidCapeConfigIdException(
+ "The config ID must be a positive non-zero integer"
+ );
+ }
+ try {
+ UnsignedBytes.checkedCast(id);
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ }
+
+ boolean isRegistered = availableIds.get(id);
+ if (isRegistered) {
+ throw new InvalidCapeConfigIdException(
+ String.format("The config ID %d is already claimed.", id)
+ );
+ }
+
+ availableIds.set(id);
+ return id;
+ }
+
+ public CapeConfig parse(InputStream is) {
+ if (is == null) {
+ throw new NullPointerException("Can not parse a null input stream!");
+ }
+
+ CapeConfig instance = new CapeConfig();
+ InputStreamReader isr = new InputStreamReader(is);
+
+ try {
+ Map entries = new Gson().fromJson(isr, Map.class);
+
+ for (Map.Entry entry : entries.entrySet()) {
+ final String nodeName = entry.getKey();
+ final Object obj = entry.getValue();
+ if (obj instanceof Map) {
+ parseGroup(instance, nodeName, (Map) obj);
+ } else if (obj instanceof String) {
+ parseUser(instance, nodeName, (String) obj);
+ }
+ }
+ } catch (JsonSyntaxException e) {
+ DevCapes.logger.error("CapeConfig could not be parsed because:");
+ e.printStackTrace();
+ }
+
+ return instance;
+ }
+
+ protected void parseGroup(CapeConfig config, String node, Map group) {
+ Group g = GroupManager.getInstance().parse(node, group);
+ if (g != null) {
+ config.groups.put(g.name, g);
+ }
+ }
+
+ protected void parseUser(CapeConfig config, String node, String user) {
+ User u = UserManager.getInstance().parse(node, user);
+ if (u != null) {
+ config.users.put(node, u);
+ }
+ }
+
+ /**
+ * DEPRECATED! Please use {@link
+ * com.jadarstudios.developercapes.cape.CapeConfigManager#parse(java.io.InputStream
+ * is)} This will be removed in the next major release.
+ */
+ @Deprecated
+ public CapeConfig parseFromStream(InputStream is) {
+ return this.parse(is);
+ }
+
+ public static class InvalidCapeConfigIdException extends Exception {
+ public InvalidCapeConfigIdException() {
+ super();
+ }
+
+ public InvalidCapeConfigIdException(String s) {
+ super(s);
+ }
+
+ public InvalidCapeConfigIdException(Throwable cause) {
+ super(cause);
+ }
+
+ public InvalidCapeConfigIdException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/cape/CapeManager.java b/src/main/java/com/jadarstudios/developercapes/cape/CapeManager.java
new file mode 100644
index 0000000..4c60f2b
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/cape/CapeManager.java
@@ -0,0 +1,85 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.cape;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+
+import com.jadarstudios.developercapes.DevCapes;
+
+/**
+ * This manages all of the capes, be nice to it or you won't get one!
+ *
+ * @author jadar
+ */
+public class CapeManager {
+ protected static CapeManager instance;
+
+ private HashMap capes;
+
+ public CapeManager() {
+ this.capes = new HashMap();
+ }
+
+ public static CapeManager getInstance() {
+ if (instance == null) {
+ instance = new CapeManager();
+ }
+ return instance;
+ }
+
+ public void addCape(ICape cape) {
+ if (!capes.containsValue(cape)) {
+ capes.put(cape.getName(), cape);
+ }
+ }
+
+ public void addCapes(Collection capes) {
+ for (ICape c : capes) {
+ this.addCape(c);
+ }
+ }
+
+ public ICape getCape(String capeName) {
+ return capes.get(capeName);
+ }
+
+ public ICape newCape(String name) {
+ StaticCape cape = new StaticCape(name);
+ this.capes.put(name, cape);
+ return cape;
+ }
+
+ public ICape parse(String name, Object object) {
+ ICape cape = null;
+ if (object instanceof String || object instanceof URL) {
+ cape = parse(name, object.toString());
+ } else {
+ DevCapes.logger.error(String.format(
+ "Cape, %s, could not be parsed because it is not in an accepted format!",
+ object
+ ));
+ }
+ return cape;
+ }
+
+ protected ICape parse(String name, String url) {
+ ICape cape = null;
+
+ try {
+ cape = new StaticCape(name, new URL(url));
+ } catch (MalformedURLException e) {
+ DevCapes.logger.error(
+ String.format("Are you crazy?? \"%s\" is not a valid URL!", url)
+ );
+ e.printStackTrace();
+ }
+ return cape;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/cape/ICape.java b/src/main/java/com/jadarstudios/developercapes/cape/ICape.java
new file mode 100644
index 0000000..7061487
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/cape/ICape.java
@@ -0,0 +1,28 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.cape;
+
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.renderer.texture.ITextureObject;
+import net.minecraft.util.ResourceLocation;
+
+/**
+ * Any class implementing this will be requested to act as a cape.
+ *
+ * @author jadar
+ */
+public interface ICape {
+ public String getName();
+
+ public ITextureObject getTexture();
+
+ public ResourceLocation getLocation();
+
+ public void loadTexture(AbstractClientPlayer player);
+
+ public boolean isTextureLoaded(AbstractClientPlayer player);
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/cape/StaticCape.java b/src/main/java/com/jadarstudios/developercapes/cape/StaticCape.java
new file mode 100644
index 0000000..f9499a9
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/cape/StaticCape.java
@@ -0,0 +1,61 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.cape;
+
+import java.net.URL;
+
+import com.jadarstudios.developercapes.HDImageBuffer;
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.renderer.ThreadDownloadImageData;
+import net.minecraft.util.ResourceLocation;
+
+/**
+ * Default Cape implementation
+ *
+ * @author jadar
+ */
+public class StaticCape extends AbstractCape {
+ public StaticCape(String name, URL url) {
+ this.setName(name);
+ this.setURL(url);
+ }
+
+ public StaticCape(String name) {
+ this(name, null);
+ }
+
+ @Override
+ public void loadTexture(AbstractClientPlayer player) {
+ ResourceLocation location = this.getLocation();
+ player.func_152121_a(MinecraftProfileTexture.Type.CAPE, location);
+
+ Minecraft.getMinecraft().renderEngine.loadTexture(location, this.getTexture());
+ }
+
+ @Override
+ public boolean isTextureLoaded(AbstractClientPlayer player) {
+ ResourceLocation cape = player.getLocationCape();
+ return cape != null;
+ }
+
+ public void setURL(URL url) {
+ if (url == null) {
+ this.texture = null;
+ return;
+ }
+ this.texture = new ThreadDownloadImageData(
+ null, url.toString(), null, new HDImageBuffer()
+ );
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ this.location = new ResourceLocation("DevCapes/" + name);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/user/Group.java b/src/main/java/com/jadarstudios/developercapes/user/Group.java
new file mode 100644
index 0000000..f47c336
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/user/Group.java
@@ -0,0 +1,60 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.user;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import com.jadarstudios.developercapes.cape.ICape;
+
+/**
+ * This represents a group of players that share a cape
+ *
+ * @author jadar
+ */
+public class Group {
+ protected HashMap users;
+ protected ICape cape;
+ public final String name;
+
+ public Group(String name) {
+ this.users = new HashMap();
+ this.name = name;
+ }
+
+ public void addUser(User user) {
+ if (!this.users.containsValue(user)) {
+ user.capes.add(this.cape);
+ this.users.put(user.userUUID, user);
+ }
+ }
+
+ public void addUsers(Set users) {
+ for (User user : users) {
+ this.addUser(user);
+ }
+ }
+
+ public void removeUser(User user) {
+ if (this.users.containsValue(user)) {
+ this.users.remove(user);
+ user.capes.remove(this.cape);
+ }
+ }
+
+ public ICape getCape() {
+ return this.cape;
+ }
+
+ public void setCape(ICape cape) {
+ for (User user : this.users.values()) {
+ user.capes.remove(this.cape);
+ }
+
+ this.cape = cape;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/user/GroupManager.java b/src/main/java/com/jadarstudios/developercapes/user/GroupManager.java
new file mode 100644
index 0000000..d0eaad8
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/user/GroupManager.java
@@ -0,0 +1,94 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.user;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.jadarstudios.developercapes.DevCapes;
+import com.jadarstudios.developercapes.cape.CapeManager;
+
+/**
+ * All groups have to be managed
+ *
+ * @author jadar
+ */
+public class GroupManager {
+ protected static GroupManager instance;
+
+ private HashMap groups;
+
+ public GroupManager() {
+ this.groups = new HashMap();
+ }
+
+ public static GroupManager getInstance() {
+ if (instance == null) {
+ instance = new GroupManager();
+ }
+ return instance;
+ }
+
+ public void addGroup(Group group) {
+ groups.put(group.name, group);
+
+ try {
+ UserManager.getInstance().addUsers(group.users.values());
+ CapeManager.getInstance().addCape(group.cape);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void addGroups(Collection groups) {
+ for (Group g : groups) {
+ GroupManager.getInstance().addGroup(g);
+ }
+ }
+
+ public Group getGroup(String capeName) {
+ return groups.get(capeName);
+ }
+
+ public Group newGroup(String name) {
+ if (this.getGroup(name) != null) {
+ return this.getGroup(name);
+ }
+ Group group = new Group(name);
+ return group;
+ }
+
+ public Group parse(String name, Map data) {
+ Group group = new Group(name);
+
+ Object usersObj = data.get("users");
+ Object capeUrlObj = data.get("capeUrl");
+
+ if (!(usersObj instanceof ArrayList) || !(capeUrlObj instanceof String)) {
+ DevCapes.logger.error(String.format(
+ "Group %s could not be parsed because it either is invalid or missing elements.",
+ name
+ ));
+ return null;
+ }
+
+ ArrayList users = (ArrayList) usersObj;
+ String capeUrl = (String) capeUrlObj;
+
+ group.cape = CapeManager.getInstance().parse(name, capeUrl);
+
+ for (Object obj : users) {
+ User user = UserManager.getInstance().parse((String) obj, group.cape);
+ if (user != null) {
+ group.addUser(user);
+ }
+ }
+ return group;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/user/User.java b/src/main/java/com/jadarstudios/developercapes/user/User.java
new file mode 100644
index 0000000..3010171
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/user/User.java
@@ -0,0 +1,27 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.user;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jadarstudios.developercapes.cape.ICape;
+
+/**
+ * This player is getting their own cape
+ *
+ * @author jadar
+ */
+public class User {
+ public List capes;
+ public final String userUUID;
+
+ public User(String userUUID) {
+ this.userUUID = userUUID;
+ this.capes = new ArrayList();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/jadarstudios/developercapes/user/UserManager.java b/src/main/java/com/jadarstudios/developercapes/user/UserManager.java
new file mode 100644
index 0000000..9e4bcab
--- /dev/null
+++ b/src/main/java/com/jadarstudios/developercapes/user/UserManager.java
@@ -0,0 +1,84 @@
+/**
+ * DeveloperCapes by Jadar
+ * License: MIT License
+ * (https://raw.github.com/jadar/DeveloperCapes/master/LICENSE)
+ * version 4.0.0.x
+ */
+package com.jadarstudios.developercapes.user;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+import com.jadarstudios.developercapes.DevCapes;
+import com.jadarstudios.developercapes.cape.CapeManager;
+import com.jadarstudios.developercapes.cape.ICape;
+
+/**
+ * Users can not be trusted to put capes on by themselves
+ *
+ * @author jadar
+ */
+public class UserManager {
+ protected static UserManager instance;
+
+ protected HashMap users;
+
+ public UserManager() {
+ this.users = new HashMap();
+ }
+
+ public static UserManager getInstance() {
+ if (instance == null) {
+ instance = new UserManager();
+ }
+ return instance;
+ }
+
+ public User getUser(String username) {
+ return this.users.get(username);
+ }
+
+ public void addUser(User user) throws NullPointerException {
+ if (user == null || user.userUUID == null || user.userUUID.isEmpty()) {
+ throw new NullPointerException("Cannot add a null user!");
+ }
+
+ this.users.put(user.userUUID, user);
+ CapeManager.getInstance().addCapes(user.capes);
+ }
+
+ public void addUsers(Collection users) throws NullPointerException {
+ for (User u : users) {
+ this.addUser(u);
+ }
+ }
+
+ public User newUser(String username) {
+ User user = null;
+ if (this.users.containsKey(username)) {
+ user = this.getUser(username);
+ } else {
+ user = new User(username);
+ this.users.put(username, user);
+ }
+
+ return user;
+ }
+
+ public User parse(String user, Object cape) {
+ User userInstance = new User(user);
+
+ ICape capeInstance = (cape instanceof ICape)
+ ? (ICape) cape
+ : CapeManager.getInstance().parse(user, cape.toString());
+
+ if (capeInstance != null) {
+ userInstance.capes.add(capeInstance);
+ } else {
+ DevCapes.logger.error(String.format("Error parsing cape, %s", cape.toString())
+ );
+ }
+
+ return userInstance;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/dev/tilera/auracore/AuraCore.java b/src/main/java/dev/tilera/auracore/AuraCore.java
index ce5fced..48845f1 100644
--- a/src/main/java/dev/tilera/auracore/AuraCore.java
+++ b/src/main/java/dev/tilera/auracore/AuraCore.java
@@ -76,6 +76,7 @@ public class AuraCore {
@Mod.EventHandler
public void init(FMLInitializationEvent ev) {
+ proxy.init();
ConfigBlocks.blockCrystal.setTickRandomly(true);
Recipes.initRecipes();
NetworkRegistry.INSTANCE.registerGuiHandler(this, proxy);
diff --git a/src/main/java/dev/tilera/auracore/Recipes.java b/src/main/java/dev/tilera/auracore/Recipes.java
index fec6ea3..f903a7c 100644
--- a/src/main/java/dev/tilera/auracore/Recipes.java
+++ b/src/main/java/dev/tilera/auracore/Recipes.java
@@ -1,19 +1,62 @@
package dev.tilera.auracore;
+import java.util.HashSet;
+import java.util.Set;
+
+import dev.tilera.auracore.api.Aspects;
+import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
+import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.ShapelessOreRecipe;
+import thaumcraft.api.ThaumcraftApi;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
import thaumcraft.common.config.ConfigBlocks;
import thaumcraft.common.config.ConfigItems;
import thaumcraft.common.config.ConfigResearch;
public class Recipes {
+
+ static Set oldCrucibleRecipes = new HashSet<>();
public static void initRecipes() {
ConfigResearch.recipes.put("Clusters8", shapelessOreDictRecipe(new ItemStack(ConfigBlocks.blockCrystal, 1, 8), new Object[] { new ItemStack(ConfigItems.itemShard, 1, 7), new ItemStack(ConfigItems.itemShard, 1, 7), new ItemStack(ConfigItems.itemShard, 1, 7), new ItemStack(ConfigItems.itemShard, 1, 7), new ItemStack(ConfigItems.itemShard, 1, 7), new ItemStack(ConfigItems.itemShard, 1, 7) }));
ConfigResearch.recipes.put("Clusters10", shapelessOreDictRecipe(new ItemStack(ConfigBlocks.blockCrystal, 1, 10), new Object[] { new ItemStack(ConfigItems.itemShard, 1, 9), new ItemStack(ConfigItems.itemShard, 1, 9), new ItemStack(ConfigItems.itemShard, 1, 9), new ItemStack(ConfigItems.itemShard, 1, 9), new ItemStack(ConfigItems.itemShard, 1, 9), new ItemStack(ConfigItems.itemShard, 1, 9) }));
ConfigResearch.recipes.put("Clusters9", shapelessOreDictRecipe(new ItemStack(ConfigBlocks.blockCrystal, 1, 9), new Object[] { new ItemStack(ConfigItems.itemShard, 1, 0), new ItemStack(ConfigItems.itemShard, 1, 1), new ItemStack(ConfigItems.itemShard, 1, 2), new ItemStack(ConfigItems.itemShard, 1, 3), new ItemStack(ConfigItems.itemShard, 1, 7) }));
+ if (false) {
+ ThaumcraftApi.addCrucibleRecipe("ALUMENTUM", new ItemStack(ConfigItems.itemResource, 1, 0), 5, new AspectList().merge(Aspect.ENERGY, 6).merge(Aspect.FIRE, 6).merge(Aspects.DESTRUCTION, 3));
+ oldCrucibleRecipes.add("ALUMENTUM");
+ //ThaumcraftApi.addCrucibleRecipe("GUNPOWDER", new ItemStack(Items.gunpowder), 5, new AspectList().merge(Aspect.FIRE, 6).merge(Aspects.DESTRUCTION, 6));
+ ThaumcraftApi.addCrucibleRecipe("NITOR", new ItemStack(ConfigItems.itemResource, 1, 1), 5, new AspectList().merge(Aspect.ENERGY, 4).merge(Aspect.FIRE, 4).merge(Aspect.LIGHT, 6));
+ oldCrucibleRecipes.add("NITOR");
+ ThaumcraftApi.addCrucibleRecipe("THAUMIUM", new ItemStack(ConfigItems.itemResource, 1, 2), 5, new AspectList().merge(Aspect.METAL, 8).merge(Aspect.MAGIC, 4));
+ oldCrucibleRecipes.add("THAUMIUM");
+ ThaumcraftApi.addCrucibleRecipe("TALLOW", new ItemStack(ConfigItems.itemResource, 1, 4), 5, new AspectList().merge(Aspect.FLESH, 4));
+ oldCrucibleRecipes.add("TALLOW");
+ ThaumcraftApi.addCrucibleRecipe("TRANSGOLD", new ItemStack(Items.gold_nugget, 2, 0), 5, new AspectList().merge(Aspect.METAL, 2).merge(Aspects.VALUABLE, 1));
+ oldCrucibleRecipes.add("TRANSGOLD");
+ if (thaumcraft.common.config.Config.foundCopperIngot) {
+ ThaumcraftApi.addCrucibleRecipe("TRANSCOPPER", new ItemStack(ConfigItems.itemNugget, 3, 1), 5, new AspectList().merge(Aspect.METAL, 3).merge(Aspect.LIFE, 1));
+ oldCrucibleRecipes.add("TRANSCOPPER");
+ }
+ if (thaumcraft.common.config.Config.foundTinIngot) {
+ ThaumcraftApi.addCrucibleRecipe("TRANSTIN", new ItemStack(ConfigItems.itemNugget, 3, 2), 5, new AspectList().merge(Aspect.METAL, 3).merge(Aspect.CRYSTAL, 1));
+ oldCrucibleRecipes.add("TRANSTIN");
+ }
+ if (thaumcraft.common.config.Config.foundSilverIngot) {
+ ThaumcraftApi.addCrucibleRecipe("TRANSSILVER", new ItemStack(ConfigItems.itemNugget, 3, 3), 5, new AspectList().merge(Aspect.METAL, 3).merge(Aspect.EXCHANGE, 1));
+ oldCrucibleRecipes.add("TRANSSILVER");
+ }
+ if (thaumcraft.common.config.Config.foundLeadIngot) {
+ ThaumcraftApi.addCrucibleRecipe("TRANSLEAD", new ItemStack(ConfigItems.itemNugget, 3, 4), 5, new AspectList().merge(Aspect.METAL, 3).merge(Aspect.VOID, 1));
+ oldCrucibleRecipes.add("TRANSLEAD");
+ }
+ ThaumcraftApi.addCrucibleRecipe("TRANSIRON", new ItemStack(ConfigItems.itemNugget, 2, 0), 5, new AspectList().merge(Aspect.METAL, 2));
+ oldCrucibleRecipes.add("TRANSIRON");
+ ThaumcraftApi.getCraftingRecipes().removeIf((Object o) -> o instanceof thaumcraft.api.crafting.CrucibleRecipe && oldCrucibleRecipes.contains(((thaumcraft.api.crafting.CrucibleRecipe)o).key));
+ }
}
@SuppressWarnings({"unchecked"})
diff --git a/src/main/java/dev/tilera/auracore/proxy/ClientProxy.java b/src/main/java/dev/tilera/auracore/proxy/ClientProxy.java
index ea1531a..bc0595c 100644
--- a/src/main/java/dev/tilera/auracore/proxy/ClientProxy.java
+++ b/src/main/java/dev/tilera/auracore/proxy/ClientProxy.java
@@ -1,6 +1,7 @@
package dev.tilera.auracore.proxy;
import dev.tilera.auracore.client.gui.GuiArcaneWorkbench;
+import dev.tilera.capes.Capes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import thaumcraft.common.tiles.TileArcaneWorkbench;
@@ -15,4 +16,9 @@ public class ClientProxy extends CommonProxy {
return null;
}
+ @Override
+ public void init() {
+ Capes.initCapes();
+ }
+
}
diff --git a/src/main/java/dev/tilera/auracore/proxy/CommonProxy.java b/src/main/java/dev/tilera/auracore/proxy/CommonProxy.java
index d6dfb5c..5152f15 100644
--- a/src/main/java/dev/tilera/auracore/proxy/CommonProxy.java
+++ b/src/main/java/dev/tilera/auracore/proxy/CommonProxy.java
@@ -10,6 +10,8 @@ public class CommonProxy implements IGuiHandler {
public void preInit() {}
+ public void init() {}
+
@Override
public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
if (id == 0) {
diff --git a/src/main/java/dev/tilera/auracore/world/WorldGenerator.java b/src/main/java/dev/tilera/auracore/world/WorldGenerator.java
index b458444..cb7511c 100644
--- a/src/main/java/dev/tilera/auracore/world/WorldGenerator.java
+++ b/src/main/java/dev/tilera/auracore/world/WorldGenerator.java
@@ -99,7 +99,7 @@ public class WorldGenerator implements IWorldGenerator {
this.structureNode.put(var7.hashCode(), true);
int yPos = world.getHeightValue(var7.chunkPosX, var7.chunkPosZ) + 3;
int nearKey = AuraManager.getClosestAuraWithinRange(world, var7.chunkPosX, yPos, var7.chunkPosZ, 10);
- if (nearKey < 0) {
+ if (nearKey < 0 && yPos > 0) {
int value = random.nextInt(200) + 800;
AuraManager.registerAuraNode(world, (short)value, EnumNodeType.NORMAL, world.provider.dimensionId, var7.chunkPosX, yPos, var7.chunkPosZ);
}
diff --git a/src/main/java/dev/tilera/capes/Capes.java b/src/main/java/dev/tilera/capes/Capes.java
new file mode 100644
index 0000000..cda651b
--- /dev/null
+++ b/src/main/java/dev/tilera/capes/Capes.java
@@ -0,0 +1,25 @@
+package dev.tilera.capes;
+
+import com.jadarstudios.developercapes.DevCapes;
+
+import net.minecraftforge.common.MinecraftForge;
+
+public class Capes {
+
+ private static boolean capesInitialized = false;
+
+ public static void initCapes() {
+ if (!capesInitialized) {
+ capesInitialized = true;
+ try {
+ DevCapes.getInstance().registerConfig(
+ "https://capes.tilera.xyz/devcapes.json"
+ );
+ MinecraftForge.EVENT_BUS.register(new RenderEventHandler());
+ } catch (Exception e) {
+ System.out.print("Cant load capes\n" + e);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/dev/tilera/capes/RenderEventHandler.java b/src/main/java/dev/tilera/capes/RenderEventHandler.java
new file mode 100644
index 0000000..24dad28
--- /dev/null
+++ b/src/main/java/dev/tilera/capes/RenderEventHandler.java
@@ -0,0 +1,31 @@
+package dev.tilera.capes;
+
+import com.jadarstudios.developercapes.cape.ICape;
+import com.jadarstudios.developercapes.user.User;
+import com.jadarstudios.developercapes.user.UserManager;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraftforge.client.event.RenderPlayerEvent;
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+
+public class RenderEventHandler {
+ @SubscribeEvent
+ public void renderPlayer(RenderPlayerEvent.Specials.Pre event) {
+ AbstractClientPlayer player = (AbstractClientPlayer) event.entityPlayer;
+
+ UserManager manager = UserManager.getInstance();
+ User user = manager.getUser(player.getUniqueID().toString());
+ if (user == null) {
+ player.func_152121_a(MinecraftProfileTexture.Type.CAPE, null);
+ return;
+ }
+
+ ICape cape = user.capes.get(0);
+ if (cape == null) {
+ player.func_152121_a(MinecraftProfileTexture.Type.CAPE, null);
+ return;
+ }
+
+ cape.loadTexture(player);
+ }
+}