diff --git a/src/main/java/myessentials/curse/Curse.java b/src/main/java/myessentials/curse/Curse.java new file mode 100644 index 0000000..5a84733 --- /dev/null +++ b/src/main/java/myessentials/curse/Curse.java @@ -0,0 +1,37 @@ +package myessentials.curse; + +import com.google.gson.Gson; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; + +public final class Curse { + private Curse() { + } + + /** + * Gets CurseModInfo using the mcf widget api. http://widget.mcf.li/ + * @param projectid The CurseForge project ID + * @return The CurseModInfo object + * @throws IOException + */ + public static CurseModInfo getModInfo(String projectid) throws IOException { + URL url = new URL("http://widget.mcf.li/mc-mods/minecraft/" + projectid + ".json"); + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + return (new Gson()).fromJson(reader, CurseModInfo.class); + } + + /** + * Returns a direct download link of the file for the modid + * @param projectid The CurseForge + * @param downloadid The download id + * @return The download URL + * @throws MalformedURLException + */ + public static URL getDownloadURL(String projectid, String downloadid) throws MalformedURLException { + return new URL("http://minecraft.curseforge.com/mc-mods/" + projectid + "/files/" + downloadid + "/download"); + } +} diff --git a/src/main/java/myessentials/curse/CurseModInfo.java b/src/main/java/myessentials/curse/CurseModInfo.java new file mode 100644 index 0000000..5d5dbf5 --- /dev/null +++ b/src/main/java/myessentials/curse/CurseModInfo.java @@ -0,0 +1,92 @@ +package myessentials.curse; + +import java.util.Map; + +public class CurseModInfo { + private String title; + private String game; + private String category; + private String url; + private String thumbnail; + private String[] authors; + // TODO Downloads Counters + private int favorites; + private int likes; + private String updated_at; + private String created_at; + private String project_url; + private String release_type; + private String license; + private VersionInfo download; + private Map versions; + + public VersionInfo[] getVersions(String mcVersion) { + return versions.get(mcVersion); + } + + public VersionInfo getNewestVersion(String mcVersion) { + VersionInfo newest = null; + for (VersionInfo versionInfo : getVersions(mcVersion)) { + if (newest == null || versionInfo.getId() > newest.getId()) { + newest = versionInfo; + } + } + return newest; + } + + public String getTitle() { + return title; + } + + public String getGame() { + return game; + } + + public String getCategory() { + return category; + } + + public String getUrl() { + return url; + } + + public String getThumbnail() { + return thumbnail; + } + + public String[] getAuthors() { + return authors; + } + + public int getFavorites() { + return favorites; + } + + public int getLikes() { + return likes; + } + + public String getUpdated_at() { + return updated_at; + } + + public String getCreated_at() { + return created_at; + } + + public String getProject_url() { + return project_url; + } + + public String getRelease_type() { + return release_type; + } + + public String getLicense() { + return license; + } + + public VersionInfo getDownload() { + return download; + } +} diff --git a/src/main/java/myessentials/curse/VersionInfo.java b/src/main/java/myessentials/curse/VersionInfo.java new file mode 100644 index 0000000..e46991e --- /dev/null +++ b/src/main/java/myessentials/curse/VersionInfo.java @@ -0,0 +1,39 @@ +package myessentials.curse; + +public class VersionInfo { + private int id; + private String url; + private String name; + private String type; + private String version; + private int downloads; + private String created_at; + + public int getId() { + return id; + } + + public String getUrl() { + return url; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public String getVersion() { + return version; + } + + public int getDownloads() { + return downloads; + } + + public String getCreated_at() { + return created_at; + } +} diff --git a/src/main/java/myessentials/new_config/Config.java b/src/main/java/myessentials/new_config/Config.java new file mode 100644 index 0000000..e429777 --- /dev/null +++ b/src/main/java/myessentials/new_config/Config.java @@ -0,0 +1,88 @@ +package myessentials.new_config; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a class as a Config. + * + * Not currently used, but there are plans! + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Config { + /** + * The filename of the config class + * @return + */ + String value() default ""; + + /** + * The configuration backend to load (forge or json) + * @return + */ + String backend() default "forge"; + + /** + * Marks a field to hold the ConfigData + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + @interface Instance { + } + + /** + * Marks a class as a config group + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @interface Group { + /** + * Returns the name of the category. + * If set to empty string or null, name will be name of the class its attached to. + * + * @return + */ + String name() default ""; + + /** + * Returns the comment of the category. + * + * @return Comment of the category + */ + String comment() default ""; + + Class[] classes() default {}; + } + + /** + * Marks a field as a config property + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + @interface Property { + /** + * Returns the name of the property. + * If set to empty string or null, name will be name of the field its attached to. + * + * @return Name of property + */ + String name() default ""; + + /** + * Returns the comment of the property. + * + * @return Comment of the property + */ + String comment() default ""; + + /** + * Returns if this property can be changed by commands. + * + * @return Can be changed by commands + */ + boolean command() default true; + } +} diff --git a/src/main/java/myessentials/new_config/ConfigProcessor.java b/src/main/java/myessentials/new_config/ConfigProcessor.java index ae419fe..f0329ec 100644 --- a/src/main/java/myessentials/new_config/ConfigProcessor.java +++ b/src/main/java/myessentials/new_config/ConfigProcessor.java @@ -1,7 +1,5 @@ package myessentials.new_config; -import myessentials.new_config.annotations.ConfigGroup; -import myessentials.new_config.annotations.ConfigProperty; import myessentials.new_config.backends.ForgeConfigBackend; import myessentials.new_config.backends.JsonConfigBackend; import myessentials.new_config.data.ConfigGroupData; @@ -27,13 +25,22 @@ public static ConfigData load(Class clazz, IConfigBackend backend) { Map groups = genGroups(clazz, null, backend); ConfigData cfgData = new ConfigData(groups, backend); cfgData.load(); + for (Field f : clazz.getFields()) { + Config.Instance instAnnot = clazz.getAnnotation(Config.Instance.class); + if (instAnnot == null || !ConfigData.class.isAssignableFrom(f.getClass())) continue; + try { + f.set(null, cfgData); + } catch (IllegalAccessException e) { + // TODO Handle this exception nicely? + } + } return cfgData; } private static Map genGroups(Class clazz, String parentFullName, IConfigBackend backend) { Map groupsMap = new HashMap(); for (Class c : clazz.getClasses()) { - ConfigGroup groupAnnot = getConfigGroupAnnotation(c); + Config.Group groupAnnot = getConfigGroupAnnotation(c); if (groupAnnot == null) continue; String groupName = (groupAnnot.name() == null || groupAnnot.name().trim().isEmpty()) ? c.getSimpleName() : groupAnnot.name(); String groupFullName = (parentFullName != null ? (parentFullName + ".") : "") + groupName; @@ -59,7 +66,7 @@ private static Map genGroups(Class clazz, String par private static Map genProps(Class clazz, String groupFullName, IConfigBackend backend) { Map propertiesMap = new HashMap(); for (Field field : clazz.getFields()) { - ConfigProperty propAnnot = field.getAnnotation(ConfigProperty.class); + Config.Property propAnnot = field.getAnnotation(Config.Property.class); if (propAnnot == null) continue; String propName = (propAnnot.name() == null || propAnnot.name().trim().isEmpty()) ? field.getName() : propAnnot.name(); String propFullName = groupFullName + "." + propName; @@ -70,13 +77,13 @@ private static Map genProps(Class clazz, String g return propertiesMap; } - private static ConfigGroup getConfigGroupAnnotation(Class clazz) { - ConfigGroup annot = null; - if (clazz.isAnnotationPresent(ConfigGroup.class)) { - annot = clazz.getAnnotation(ConfigGroup.class); - } else if (ConfigGroup.class.isAssignableFrom(clazz)) { + private static Config.Group getConfigGroupAnnotation(Class clazz) { + Config.Group annot = null; + if (clazz.isAnnotationPresent(Config.Group.class)) { + annot = clazz.getAnnotation(Config.Group.class); + } else if (Config.Group.class.isAssignableFrom(clazz)) { try { - annot = (ConfigGroup) clazz.newInstance(); + annot = (Config.Group) clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/myessentials/new_config/annotations/ConfigGroup.java b/src/main/java/myessentials/new_config/annotations/ConfigGroup.java deleted file mode 100644 index 9cff84a..0000000 --- a/src/main/java/myessentials/new_config/annotations/ConfigGroup.java +++ /dev/null @@ -1,27 +0,0 @@ -package myessentials.new_config.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ConfigGroup { - /** - * Returns the name of the category. - * If set to empty string or null, name will be name of the class its attached to. - * - * @return - */ - String name() default ""; - - /** - * Returns the comment of the category. - * - * @return Comment of the category - */ - String comment() default ""; - - Class[] classes() default {}; -} diff --git a/src/main/java/myessentials/new_config/annotations/ConfigProperty.java b/src/main/java/myessentials/new_config/annotations/ConfigProperty.java deleted file mode 100644 index 96bc6c7..0000000 --- a/src/main/java/myessentials/new_config/annotations/ConfigProperty.java +++ /dev/null @@ -1,32 +0,0 @@ -package myessentials.new_config.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface ConfigProperty { - /** - * Returns the name of the property. - * If set to empty string or null, name will be name of the field its attached to. - * - * @return Name of property - */ - String name() default ""; - - /** - * Returns the comment of the property. - * - * @return Comment of the property - */ - String comment() default ""; - - /** - * Returns if this property can be changed by commands. - * - * @return Can be changed by commands - */ - boolean command() default true; -} diff --git a/src/main/java/myessentials/new_config/backends/JsonConfigBackend.java b/src/main/java/myessentials/new_config/backends/JsonConfigBackend.java index 4056eb7..5b53082 100644 --- a/src/main/java/myessentials/new_config/backends/JsonConfigBackend.java +++ b/src/main/java/myessentials/new_config/backends/JsonConfigBackend.java @@ -81,6 +81,7 @@ private Object getValue(JsonElement element, Class type) { for (int i=0; i this.currentVersion) { + } + } + } catch(Exception e) { + // TODO Handle safely + } + } + + private double stringToVersion(String versionStr) { + return Double.parseDouble(versionStr.replace(".", "")); + } +} diff --git a/src/test/java/myessentials/test/config/ConfigTest.java b/src/test/java/myessentials/test/config/ConfigTest.java new file mode 100644 index 0000000..a556c01 --- /dev/null +++ b/src/test/java/myessentials/test/config/ConfigTest.java @@ -0,0 +1,44 @@ +package myessentials.test.config; + +import myessentials.new_config.ConfigProcessor; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.net.URISyntaxException; + +public class ConfigTest { + private int[] realIntTestArrValues = {1, 2, 3}; + private double[] realDoubleTestArrValues = {1.1, 2.2, 3.3}; + private float[] realFloatTestArrValues = {1.1f, 2.2f, 3.3f}; + private boolean[] realBoolTestArrValues = {true, false, false, true, true}; + private String[] realStringTestArrValues = {"Hello", "World!"}; + +// @Before + public void setup() { + try { + ConfigProcessor.load(TestConfig.class, new File(ConfigTest.class.getClassLoader().getResource("test_config.json").toURI())); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + +// @Test + public void testValues() { + Assert.assertEquals(TestConfig.TypeTestGroup.intTest, 50); + Assert.assertEquals(TestConfig.TypeTestGroup.doubleTest, 12.5, 0); + Assert.assertEquals(TestConfig.TypeTestGroup.floatTest, 88.8885f, 0f); + Assert.assertEquals(TestConfig.TypeTestGroup.booleanTest, false); + Assert.assertEquals(TestConfig.TypeTestGroup.stringTest, "Hello World!"); + + Assert.assertArrayEquals(TestConfig.ArrayTypeTestGroup.intTest, realIntTestArrValues); + Assert.assertArrayEquals(TestConfig.ArrayTypeTestGroup.doubleTest, realDoubleTestArrValues, 0); + Assert.assertArrayEquals(TestConfig.ArrayTypeTestGroup.floatTest, realFloatTestArrValues, 0); + Assert.assertEquals(TestConfig.ArrayTypeTestGroup.booleanTest, realBoolTestArrValues); + Assert.assertArrayEquals(TestConfig.ArrayTypeTestGroup.stringTest, realStringTestArrValues); + + Assert.assertEquals(TestConfig.DefaultTestGroup.aDefault, "Hello World!"); + Assert.assertEquals(TestConfig.DefaultTestGroup.anOverriddenDefault, "Yo!"); + } +} diff --git a/src/test/java/myessentials/test/config/TestConfig.java b/src/test/java/myessentials/test/config/TestConfig.java new file mode 100644 index 0000000..1623af1 --- /dev/null +++ b/src/test/java/myessentials/test/config/TestConfig.java @@ -0,0 +1,55 @@ +package myessentials.test.config; + +import myessentials.new_config.Config; +import myessentials.new_config.data.ConfigData; + +@Config +public class TestConfig { + @Config.Instance + public static ConfigData Data; + + @Config.Group(name = "TypeTest") + public static class TypeTestGroup { + @Config.Property + public static int intTest; + + @Config.Property + public static double doubleTest; + + @Config.Property + public static float floatTest; + + @Config.Property + public static boolean booleanTest; + + @Config.Property + public static String stringTest; + } + + @Config.Group(name = "ArrayTypeTest") + public static class ArrayTypeTestGroup { + @Config.Property + public static int[] intTest; + + @Config.Property + public static double[] doubleTest; + + @Config.Property + public static float[] floatTest; + + @Config.Property + public static boolean[] booleanTest; + + @Config.Property + public static String[] stringTest; + } + + @Config.Group(name = "DefaultGroupTest") + public static class DefaultTestGroup { + @Config.Property(name = "is_a_default") + public static String aDefault = "Hello World!"; + + @Config.Property(name = "is_overridden") + public static String anOverriddenDefault = "Hello World!"; + } +} diff --git a/src/test/resources/test_config.json b/src/test/resources/test_config.json new file mode 100644 index 0000000..0675e47 --- /dev/null +++ b/src/test/resources/test_config.json @@ -0,0 +1,19 @@ +{ + "TypeTest": { + "intTest": 50, + "doubleTest": 12.5, + "floatTest": 88.8885, + "booleanTest": false, + "stringTest": "Hello World!" + }, + "ArrayTypeTest": { + "intTest": [1, 2, 3], + "doubleTest": [1.1, 2.2, 3.3], + "floatTest": [1.1, 2.2, 3.3], + "booleanTest": [true, false, false, true, true], + "stringTest": ["Hello", "World!"] + }, + "DefaultGroupTest": { + "is_overridden": "Yo!" + } +} \ No newline at end of file