diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/api/MessagingService.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/api/MessagingService.java index bf3341b3..1566230e 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/api/MessagingService.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/api/MessagingService.java @@ -22,17 +22,6 @@ */ public interface MessagingService extends Service, Message.Factory { - /** - * Get a new message operation instance. - * - * @see MessagingService#getEmptyMailer() - * @deprecated This utility is being replaced, use {@link MessagingService#getEmptyMailer()} instead. - * @return A new message instance. - */ - @Deprecated() - @NotNull com.github.sanctum.labyrinth.library.Message getNewMessage(); - - /** * Get a new object for sending numerous types of displayable messages! * @@ -59,7 +48,7 @@ default Deployable sendPluginMessage(Plugin plugin, T object) { } default Deployable sendPluginMessage(Plugin plugin, T object, @FieldsFrom(LabyrinthPluginChannel.class) LabyrinthPluginChannel channel) { - return Deployable.of(null, unused -> unused = new Vent.Call<>(new LabyrinthPluginMessageEvent(new LabyrinthPluginMessage() { + return Deployable.of(() -> new Vent.Call<>(new LabyrinthPluginMessageEvent(new LabyrinthPluginMessage() { @Override public Plugin getPlugin() { return plugin; diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AbstractClassLoader.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AbstractClassLoader.java index 84bb3f4f..8395efc6 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AbstractClassLoader.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AbstractClassLoader.java @@ -1,5 +1,10 @@ package com.github.sanctum.labyrinth.data; +import com.github.sanctum.labyrinth.LabyrinthProvider; +import com.github.sanctum.labyrinth.annotation.Experimental; +import com.github.sanctum.labyrinth.library.EasyTypeAdapter; +import com.github.sanctum.labyrinth.library.TypeFlag; +import com.google.common.collect.ImmutableList; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; @@ -14,27 +19,31 @@ import java.util.zip.ZipEntry; import org.bukkit.plugin.Plugin; +/** + * A class dedicated to allowing developers to load external jars into memory. + * + * @param The optional main class this loader needs to locate and instantiate. + */ public abstract class AbstractClassLoader extends URLClassLoader { - private static final Field PLUGIN_CLASS_MAP; + protected final Field PLUGIN_CLASS_MAP; + protected final List> classes; + protected final ClassLoader pluginClassLoader; + protected final T mainClass; - private final List> classes; - private final Plugin plugin; - final T mainClass; - - static { + protected AbstractClassLoader(File file, ClassLoader parent, Object... args) throws IOException { + super(new URL[]{file.toURI().toURL()}, parent); + TypeFlag flag = new EasyTypeAdapter<>(); + Class main = flag.getType(); try { PLUGIN_CLASS_MAP = Class.forName("org.bukkit.plugin.java.PluginClassLoader").getDeclaredField("classes"); PLUGIN_CLASS_MAP.setAccessible(true); } catch (NoSuchFieldException | ClassNotFoundException e) { - throw new IllegalStateException("Unable to reach class map", e); + throw new IllegalStateException("Unable to reach plugin class map", e); } - } - - protected AbstractClassLoader(Plugin plugin, File file, ClassLoader parent, Class main, Object... args) throws IOException { - super(new URL[]{file.toURI().toURL()}, parent); final List> loadedClasses = new ArrayList<>(); - this.plugin = plugin; + final Plugin plugin = LabyrinthProvider.getInstance().getPluginInstance(); + this.pluginClassLoader = plugin.getClass().getClassLoader(); if (!file.isFile()) throw new IllegalArgumentException("The provided file is not a jar file!"); new JarFile(file).stream() .map(ZipEntry::getName) @@ -50,7 +59,7 @@ protected AbstractClassLoader(Plugin plugin, File file, ClassLoader parent, Clas plugin.getLogger().warning(e::getMessage); return; } - getClassMap().put(s, resolvedClass); + getPluginClassMap().put(s, resolvedClass); plugin.getLogger().finest(() -> "Loaded '" + s + "' successfully."); loadedClasses.add(resolvedClass); }); @@ -76,7 +85,7 @@ protected AbstractClassLoader(Plugin plugin, File file, ClassLoader parent, Clas } } } - this.mainClass = addonClass.getDeclaredConstructor(constructor.getParameterTypes()).newInstance(args); + this.mainClass = constructor != null ? constructor.newInstance(args) : addonClass.getDeclaredConstructor().newInstance(); } else { this.mainClass = addonClass.getDeclaredConstructor().newInstance(); } @@ -88,26 +97,61 @@ protected AbstractClassLoader(Plugin plugin, File file, ClassLoader parent, Clas } else this.mainClass = null; } - public AbstractClassLoader(Plugin plugin, File file, ClassLoader parent) throws IOException { - this(plugin, file, parent, null); + /** + * Get the main class for this class loader. + * + * @return the main class for this class loader if one exists. + */ + public T getMainClass() { + return mainClass; } - public Plugin getPlugin() { - return plugin; + /** + * Get a list of all classes loaded by this class loader. + * + * @return all classes loaded by this class loader. + */ + public List> getClasses() { + return ImmutableList.copyOf(classes); } - public T getMain() { - return mainClass; + /** + * Unload a class from memory. If the provided class is not found an exception will occur, if the provided string results in a path + * this method will switch in an attempt at locating and removing the relative class files it belongs to. + * + * @param name The name of the class file or path. + * @return true if the class(es) got removed from memory. + * @throws ClassNotFoundException if the attempted class resolve fails and the included text doesn't result in a valid directory. + */ + @Experimental + public boolean unload(String name) throws ClassNotFoundException { + Map> classes = getPluginClassMap(); + if (classes.containsKey(name)) { + classes.remove(name); + return true; + } else throw new ClassNotFoundException("Class " + name + " not found, cannot unload."); } - public List> getClasses() { - return classes; + /** + * Simply unload a loaded class from this addon loader. + * + * @param clazz The class to unload. + * @throws WrongLoaderUsedException when the class attempting removal belongs to a different loader instance. + * @return true if the class was able to unload. + */ + @Experimental + public boolean unload(Class clazz) throws WrongLoaderUsedException { + Map> classes = getPluginClassMap(); + String name = clazz.getName().replace("/", ".").substring(0, clazz.getName().length() - 6); + classes.remove(name); + if (!this.classes.contains(clazz)) throw new WrongLoaderUsedException("Class " + clazz.getName() + " does not belong to this loader!"); + return this.classes.remove(clazz); } - public Map> getClassMap() throws IllegalStateException { + public final Map> getPluginClassMap() throws IllegalStateException { try { //noinspection unchecked - return (Map>) PLUGIN_CLASS_MAP.get(plugin.getClass().getClassLoader()); + return (Map>) PLUGIN_CLASS_MAP.get(this.pluginClassLoader); } catch (ClassCastException | IllegalAccessException e) { throw new IllegalStateException(e); } @@ -116,7 +160,7 @@ public Map> getClassMap() throws IllegalStateException { @Override public String toString() { return "AbstractFileLoader{" + - "Main=" + (mainClass == null ? "N/A" : mainClass) + + "Main=" + mainClass + '}'; } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Atlas.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Atlas.java index c58017e8..410946f0 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Atlas.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Atlas.java @@ -14,4 +14,6 @@ default String getPath() { return null; } + char getDivider(); + } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasMap.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasMap.java index c8db80aa..57e7987e 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasMap.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasMap.java @@ -14,12 +14,25 @@ public class AtlasMap implements Atlas { - private final Map SOURCE = new HashMap<>(); + protected final Map SOURCE = new HashMap<>(); protected final Map QUERY = new HashMap<>(); + protected final char divider; + + public AtlasMap(char divider) { + this.divider = divider; + } + + public AtlasMap() { + this.divider = '.'; + } + + String dividerAdapt() { + return divider == '.' ? "[" + divider + "]" : divider + ""; + } @Override public boolean isNode(String key) { - String[] a = key.split("\\."); + String[] a = key.split(dividerAdapt()); String k = a[Math.max(0, a.length - 1)]; Map o = SOURCE; for (int i = 0; i < a.length - 1; i++) { @@ -49,76 +62,34 @@ public Node getNode(String key) { @Override public Set getKeys(boolean deep) { Set keys = new HashSet<>(); - for (Object o : SOURCE.entrySet()) { - Map.Entry entry = (Map.Entry) o; + SOURCE.forEach((key, value) -> { if (deep) { - if (entry.getValue() instanceof Map) { - Map obj = (Map) entry.getValue(); - for (Object ob : obj.entrySet()) { - Map.Entry en = (Map.Entry) ob; - if (en.getValue() instanceof Map) { - Map j = (Map) entry.getValue(); - for (Object e : j.entrySet()) { - Map.Entry ent = (Map.Entry) e; - if (ent.getValue() instanceof Map) { - Map ja = (Map) ent.getValue(); - for (Object ex : ja.entrySet()) { - Map.Entry entr = (Map.Entry) ex; - keys.add(entry.getKey() + "." + en.getKey() + "." + ent.getKey() + "." + entr.getKey()); - } - } else { - keys.add(entry.getKey() + "." + en.getKey() + "." + ent.getKey()); - } - } - } else { - keys.add(entry.getKey() + "." + en.getKey()); - } - } + if (value instanceof Map) { + keys.addAll(MapDecompressionUtils.getInstance().decompress(((Map) value).entrySet(), divider, null).toSet()); } else { - keys.add(entry.getKey()); + keys.add(key); } } else { - keys.add(entry.getKey()); + keys.add(key); } - } + }); return keys; } @Override public Map getValues(boolean deep) { Map map = new HashMap<>(); - for (Object o : SOURCE.entrySet()) { - Map.Entry entry = (Map.Entry) o; + SOURCE.forEach((key, value) -> { if (deep) { - if (entry.getValue() instanceof Map) { - Map obj = (Map) entry.getValue(); - for (Object ob : obj.entrySet()) { - Map.Entry en = (Map.Entry) ob; - if (en.getValue() instanceof Map) { - Map j = (Map) entry.getValue(); - for (Object e : j.entrySet()) { - Map.Entry ent = (Map.Entry) e; - if (ent.getValue() instanceof Map) { - Map ja = (Map) ent.getValue(); - for (Object ex : ja.entrySet()) { - Map.Entry entr = (Map.Entry) ex; - map.put(entry.getKey() + "." + en.getKey() + "." + ent.getKey() + "." + entr.getKey(), entr.getValue()); - } - } else { - map.put(entry.getKey() + "." + en.getKey() + "." + ent.getKey(), ent.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + en.getKey(), en.getValue()); - } - } + if (value instanceof Map) { + map.putAll(MapDecompressionUtils.getInstance().decompress(((Map) value).entrySet(), divider, null).toMap()); } else { - map.put(entry.getKey(), entry.getValue()); + map.put(key, value); } } else { - map.put(entry.getKey(), entry.getValue()); + map.put(key, value); } - } + }); return map; } @@ -145,7 +116,7 @@ public boolean containsValue(Object value) { @Override public Object get(Object key) { String ke = (String) key; - String[] a = ke.split("\\."); + String[] a = ke.split(dividerAdapt()); String k = a[Math.max(0, a.length - 1)]; Map o = SOURCE; for (int i = 0; i < a.length - 1; i++) { @@ -168,7 +139,7 @@ public Object get(Object key) { @Nullable @Override public Object put(String key, Object o) { - String[] a = key.split("\\."); + String[] a = key.split(dividerAdapt()); String k = a[Math.max(0, a.length - 1)]; Map ob = SOURCE; for (int i = 0; i < a.length - 1; i++) { @@ -312,4 +283,9 @@ public Object compute(String key, @NotNull BiFunction remappingFunction) { return SOURCE.merge(key, value, remappingFunction); } + + @Override + public char getDivider() { + return divider; + } } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasNode.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasNode.java index 3e877d63..b8230ee0 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasNode.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/AtlasNode.java @@ -1,8 +1,6 @@ package com.github.sanctum.labyrinth.data; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -53,13 +51,13 @@ public void set(Object o) { @Override public Node getParent() { - String[] k = this.key.split("//."); + String[] k = this.key.split(MAP.dividerAdapt()); StringBuilder builder = new StringBuilder(); for (int i = 0; i < k.length - 1; i++) { - builder.append(k[i]).append("."); + builder.append(k[i]).append(MAP.divider); } String key = builder.toString(); - if (key.endsWith(".")) { + if (key.endsWith(MAP.divider + "")) { key = key.substring(0, builder.length() - 1); } if (key.equals(this.key)) return this; @@ -79,14 +77,14 @@ public String getPath() { @Override public boolean isNode(String node) { - return MAP.isNode(this.key + "." + node); + return MAP.isNode(this.key + MAP.divider + node); } @Override public Node getNode(String node) { - return (Node) Optional.ofNullable(MAP.QUERY.get(this.key + "." + node)).orElseGet(() -> { - AtlasNode n = new AtlasNode(this.key + "." + node, MAP); - MAP.QUERY.put(this.key + "." + node, n); + return (Node) Optional.ofNullable(MAP.QUERY.get(this.key + MAP.divider + node)).orElseGet(() -> { + AtlasNode n = new AtlasNode(this.key + MAP.divider + node, MAP); + MAP.QUERY.put(this.key + MAP.divider + node, n); return n; }); } @@ -97,33 +95,9 @@ public Set getKeys(boolean deep) { if (get() instanceof Map) { Map map1 = (Map) get(); if (deep) { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - keys.add(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey()); - } - } else { - keys.add(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey()); - } - } - } else { - keys.add(entry.getKey() + "." + entry2.getKey()); - } - } - } - keys.add(entry.getKey()); - } + return MapDecompressionUtils.getInstance().decompress(map1.entrySet(), MAP.divider, null).toSet(); } else { - for (Map.Entry entry : map1.entrySet()) { - keys.add(entry.getKey()); - } + keys.addAll(map1.keySet()); } } else { keys.add(this.key); @@ -137,54 +111,9 @@ public Map getValues(boolean deep) { if (get() instanceof Map) { Map map1 = (Map) get(); if (deep) { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - map.put(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey(), entry4.getValue()); - } - } else { - map.put(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey(), entry3.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + entry2.getKey(), entry2.getValue()); - } - } - } - map.put(entry.getKey(), entry.getValue()); - } + return MapDecompressionUtils.getInstance().decompressNormalValues(map1.entrySet(), MAP.divider, null); } else { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - map.put(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey(), entry4.getValue()); - } - } else { - map.put(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey(), entry3.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + entry2.getKey(), entry2.getValue()); - } - } - } else { - map.put(entry.getKey(), entry.getValue()); - } - } + map.putAll(map1); } } else { map.put(this.key, get()); diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Configurable.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Configurable.java index 5650b422..533134a3 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Configurable.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Configurable.java @@ -74,7 +74,7 @@ public static void registerClass(@NotNull Class> c) { } else throw new RuntimeException("NodePointer annotation missing, JSON object serialization requires it."); } catch (Exception e) { - LabyrinthProvider.getService(Service.MESSENGER).getNewMessage().error("Class " + c.getSimpleName() + " failed to register JSON serialization handlers."); + LabyrinthProvider.getService(Service.MESSENGER).getEmptyMailer().error("Class " + c.getSimpleName() + " failed to register JSON serialization handlers.").deploy(); e.printStackTrace(); } } @@ -141,7 +141,7 @@ public static void registerClass(@NotNull Class> c, Obj } else throw new RuntimeException("NodePointer annotation missing, JSON object serialization requires it."); } catch (Exception e) { - LabyrinthProvider.getService(Service.MESSENGER).getNewMessage().error("Class " + c.getSimpleName() + " failed to register JSON serialization handlers."); + LabyrinthProvider.getService(Service.MESSENGER).getEmptyMailer().error("Class " + c.getSimpleName() + " failed to register JSON serialization handlers.").deploy(); e.printStackTrace(); } } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/ConfigurableNode.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/ConfigurableNode.java index c8a389f9..efadba4b 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/ConfigurableNode.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/ConfigurableNode.java @@ -226,7 +226,7 @@ public boolean create() { try { config.create(); } catch (IOException ex) { - LabyrinthProvider.getService(Service.MESSENGER).getNewMessage().error("- An issue occurred while attempting to create the backing file for the '" + config.getName() + "' configuration."); + LabyrinthProvider.getService(Service.MESSENGER).getEmptyMailer().error("- An issue occurred while attempting to create the backing file for the '" + config.getName() + "' configuration.").deploy(); ex.printStackTrace(); } } @@ -282,35 +282,11 @@ public Set getKeys(boolean deep) { Set keys = new HashSet<>(); JsonConfiguration json = (JsonConfiguration) config; if (json.get(this.key) instanceof Map) { - Map map1 = (Map) json.get(this.key); + Map level1 = (Map) json.get(this.key); if (deep) { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - keys.add(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey()); - } - } else { - keys.add(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey()); - } - } - } else { - keys.add(entry.getKey() + "." + entry2.getKey()); - } - } - } - keys.add(entry.getKey()); - } + return MapDecompressionUtils.getInstance().decompress(level1.entrySet(), '.', null).toSet(); } else { - for (Map.Entry entry : map1.entrySet()) { - keys.add(entry.getKey()); - } + keys.addAll(level1.keySet()); } } else { keys.add(this.key); @@ -327,56 +303,11 @@ public Map getValues(boolean deep) { Map map = new HashMap<>(); JsonConfiguration json = (JsonConfiguration) config; if (json.get(this.key) instanceof Map) { - Map map1 = (Map) json.get(this.key); + Map level1 = (Map) json.get(this.key); if (deep) { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - map.put(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey(), entry4.getValue()); - } - } else { - map.put(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey(), entry3.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + entry2.getKey(), entry2.getValue()); - } - } - } - map.put(entry.getKey(), entry.getValue()); - } + return MapDecompressionUtils.getInstance().decompress(level1.entrySet(), '.', null).toMap(); } else { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - map.put(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey(), entry4.getValue()); - } - } else { - map.put(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey(), entry3.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + entry2.getKey(), entry2.getValue()); - } - } - } else { - map.put(entry.getKey(), entry.getValue()); - } - } + map.putAll(level1); } } else { map.put(this.key, get()); diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/LabyrinthPluginChannel.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/LabyrinthPluginChannel.java index f31b61ee..a0d9fc14 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/LabyrinthPluginChannel.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/LabyrinthPluginChannel.java @@ -6,7 +6,13 @@ import java.lang.reflect.InvocationTargetException; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +/** + * A labyrinth plugin channel designed to provide developers with a means to inquire desired object responses from output messaging through {@link LabyrinthPluginMessageEvent} + * + * @param The type of object this channel references + */ public final class LabyrinthPluginChannel { public static final LabyrinthPluginChannel MESSAGE = new LabyrinthPluginChannel<>("message", Message.class); @@ -37,12 +43,12 @@ public Class getType() { return this.tClass; } - public Object getResponse(@NotNull Plugin plugin, @NotNull Object o) { + public @Nullable Object getResponse(@NotNull Plugin sender, @NotNull Object o) { try { return new Vent.Call<>(LabyrinthPluginMessageEvent.class.getDeclaredConstructor(LabyrinthPluginMessage.class, LabyrinthPluginChannel.class).newInstance(new LabyrinthPluginMessage() { @Override public Plugin getPlugin() { - return plugin; + return sender; } @Override diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/MapDecompression.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/MapDecompression.java new file mode 100644 index 00000000..0d5fdd60 --- /dev/null +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/MapDecompression.java @@ -0,0 +1,18 @@ +package com.github.sanctum.labyrinth.data; + +import com.github.sanctum.labyrinth.data.container.LabyrinthCollection; +import com.github.sanctum.labyrinth.data.container.LabyrinthMap; +import java.util.Map; +import java.util.Set; + +public interface MapDecompression { + + Set toSet(); + + LabyrinthCollection toLabyrinthSet(); + + Map toMap(); + + LabyrinthMap toLabyrinthMap(); + +} diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/MapDecompressionUtils.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/MapDecompressionUtils.java new file mode 100644 index 00000000..ccacfa39 --- /dev/null +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/MapDecompressionUtils.java @@ -0,0 +1,116 @@ +package com.github.sanctum.labyrinth.data; + +import com.github.sanctum.labyrinth.data.container.LabyrinthCollection; +import com.github.sanctum.labyrinth.data.container.LabyrinthEntryMap; +import com.github.sanctum.labyrinth.data.container.LabyrinthMap; +import com.github.sanctum.labyrinth.data.container.LabyrinthSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class MapDecompressionUtils { + + static MapDecompressionUtils instance; + + MapDecompressionUtils(){} + + private String appendChild(String key, char divider, String text) { + return key != null ? key + divider + text : text; + } + + public MapDecompression decompress(@NotNull Iterable> iterable, char divider, @Nullable String parentKey) { + return new MapDecompression() { + @Override + public Set toSet() { + return decompressNormalKeys(iterable, divider, parentKey); + } + + @Override + public LabyrinthCollection toLabyrinthSet() { + return decompressLabyrinthKeys(iterable, divider, parentKey); + } + + @Override + public Map toMap() { + return decompressNormalValues(iterable, divider, parentKey); + } + + @Override + public LabyrinthMap toLabyrinthMap() { + return decompressLabyrinthValues(iterable, divider, parentKey); + } + }; + } + + Set decompressNormalKeys(@NotNull Iterable> iterable, char divider, @Nullable String parent) { + Set set = new HashSet<>(); + for (Map.Entry entry : iterable) { + if (entry.getValue() instanceof Map) { + set.addAll(decompressNormalKeys(((Map) entry.getValue()).entrySet(), divider, appendChild(parent, divider, entry.getKey()))); + } else { + if (entry.getValue() instanceof LabyrinthMap) { + decompressLabyrinthKeys(((LabyrinthMap) entry.getValue()).entries(), divider, appendChild(parent, divider, entry.getKey())).forEach(set::add); + } else { + set.add(appendChild(parent, divider, entry.getKey())); + } + } + } + return set; + } + + Map decompressNormalValues(@NotNull Iterable> iterable, char divider, @Nullable String parent) { + Map m = new HashMap<>(); + for (Map.Entry entry : iterable) { + if (entry.getValue() instanceof Map) { + m.putAll(decompressNormalValues(((Map) entry.getValue()).entrySet(), divider, appendChild(parent, divider, entry.getKey()))); + } else { + if (entry.getValue() instanceof LabyrinthMap) { + decompressLabyrinthValues(((LabyrinthMap) entry.getValue()).entries(), divider, appendChild(parent, divider, entry.getKey())).forEach(e -> m.put(e.getKey(), e.getValue())); + } else { + m.put(appendChild(parent, divider, entry.getKey()), entry.getValue()); + } + } + } + return m; + } + + LabyrinthCollection decompressLabyrinthKeys(@NotNull Iterable> iterable, char divider, @Nullable String parent) { + LabyrinthCollection set = new LabyrinthSet<>(); + for (Map.Entry entry : iterable) { + if (entry.getValue() instanceof LabyrinthMap) { + set.addAll(decompressLabyrinthKeys(((LabyrinthMap) entry.getValue()).entries(), divider, appendChild(parent, divider, entry.getKey()))); + } else { + if (entry.getValue() instanceof Map) { + set.addAll(decompressNormalKeys(((Map) entry.getValue()).entrySet(), divider, appendChild(parent, divider, entry.getKey()))); + } else { + set.add(appendChild(parent, divider, entry.getKey())); + } + } + } + return set; + } + + LabyrinthMap decompressLabyrinthValues(@NotNull Iterable> iterable, char divider, @Nullable String parent) { + LabyrinthMap m = new LabyrinthEntryMap<>(); + for (Map.Entry entry : iterable) { + if (entry.getValue() instanceof LabyrinthMap) { + decompressLabyrinthValues(((LabyrinthMap) entry.getValue()).entries(), divider, appendChild(parent, divider, entry.getKey())).forEach(e -> m.put(e.getKey(), e.getValue())); + } else { + if (entry.getValue() instanceof Map) { + decompressNormalValues(((Map) entry.getValue()).entrySet(), divider, appendChild(parent, divider, entry.getKey())).forEach(m::put); + } else { + m.put(appendChild(parent, divider, entry.getKey()), entry.getValue()); + } + } + } + return m; + } + + public static @NotNull MapDecompressionUtils getInstance() { + return instance != null ? instance : (instance = new MapDecompressionUtils()); + } + +} diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Registry.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Registry.java index be026ccb..968e5fe4 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Registry.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/Registry.java @@ -28,13 +28,13 @@ */ public class Registry { - private final Class CLASS; - private Predicate FILTER; + private final Class type; + private Predicate filter; private Object handle = null; private String PACKAGE; public Registry(Class cl) { - this.CLASS = cl; + this.type = cl; } /** @@ -64,30 +64,29 @@ public Registry source(Object loader) { * * @param packageName the name of the package to search * @return this Registry instance - * @deprecated Use {@link Registry#filter(String)} instead!! */ - @Deprecated - public Registry pick(String packageName) { - this.PACKAGE = packageName; - return this; - } - public Registry filter(String packageName) { this.PACKAGE = packageName; return this; } + /** + * Optionally search using a provided predicate. + * + * @param predicate the search processor. + * @return this Registry instance + */ public Registry filter(Predicate predicate) { - this.FILTER = predicate; + this.filter = predicate; return this; } /** - * Specify actions on each element instantiated from query. + * Acquire all instantiated elements from query. * * @return the leftover data from the registry data operation */ - public RegistryData operate() { + public RegistryData confine() { Set> classes = Sets.newHashSet(); JarFile jarFile = null; if (this.handle != null) { @@ -102,18 +101,18 @@ public RegistryData operate() { Stream entries = jarFile.stream(); - if (this.FILTER != null) { + if (this.filter != null) { entries.forEach(entry -> { String className = entry.getName().replace("/", "."); final String substring = className.substring(0, Math.max(className.length() - 6, 0)); - if (this.FILTER.test(className)) { + if (this.filter.test(className)) { Class clazz = null; try { clazz = Class.forName(substring); } catch (ClassNotFoundException ignored) { } if (clazz != null) { - if (CLASS.isAssignableFrom(clazz)) { + if (type.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } @@ -132,7 +131,7 @@ public RegistryData operate() { } catch (ClassNotFoundException ignored) { } if (clazz != null) { - if (CLASS.isAssignableFrom(clazz)) { + if (type.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } @@ -146,7 +145,7 @@ public RegistryData operate() { } catch (ClassNotFoundException ignored) { } if (clazz != null) { - if (CLASS.isAssignableFrom(clazz)) { + if (type.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } @@ -167,6 +166,214 @@ public RegistryData operate() { return new RegistryData<>(additions, handle, PACKAGE); } + /** + * Acquire all instantiated elements from query using custom constructor arguments. + * + * @param args The constructor arguments to input. + * @return the leftover data from the registry data operation + */ + public RegistryData construct(Object... args) { + Set> classes = Sets.newHashSet(); + JarFile jarFile = null; + if (this.handle != null) { + try { + jarFile = new JarFile(URLDecoder.decode(this.handle.getClass().getProtectionDomain().getCodeSource().getLocation().getFile(), String.valueOf(StandardCharsets.UTF_8))); + } catch (IOException e) { + e.printStackTrace(); // TODO: Decide whether to return/rethrow at this point so as to avoid NPE on line 89 + } + } + + if (jarFile == null) throw new IllegalStateException("Invalid jar file"); + + Stream entries = jarFile.stream(); + + if (this.filter != null) { + entries.forEach(entry -> { + String className = entry.getName().replace("/", "."); + final String substring = className.substring(0, Math.max(className.length() - 6, 0)); + if (this.filter.test(className)) { + Class clazz = null; + try { + clazz = Class.forName(substring); + } catch (ClassNotFoundException ignored) { + } + if (clazz != null) { + if (type.isAssignableFrom(clazz)) { + classes.add((Class) clazz); + } + } + } + }); + } else { + entries.forEach(entry -> { + + String className = entry.getName().replace("/", "."); + final String substring = className.substring(0, Math.max(className.length() - 6, 0)); + if (this.PACKAGE != null) { + if (className.startsWith(PACKAGE) && className.endsWith(".class")) { + Class clazz = null; + try { + clazz = Class.forName(substring); + } catch (ClassNotFoundException ignored) { + } + if (clazz != null) { + if (type.isAssignableFrom(clazz)) { + classes.add((Class) clazz); + } + } + } + } else { + + if (className.endsWith(".class")) { + Class clazz = null; + try { + clazz = Class.forName(substring); + } catch (ClassNotFoundException ignored) { + } + if (clazz != null) { + if (type.isAssignableFrom(clazz)) { + classes.add((Class) clazz); + } + } + } + } + }); + } + Constructor constructor = null; + for (Constructor con : this.type.getConstructors()) { + if (args.length == con.getParameters().length) { + int success = 0; + for (int i = 0; i < args.length; i++) { + Class objectClass = args[i].getClass(); + Class typeClass = con.getParameters()[i].getType(); + if (objectClass.isAssignableFrom(typeClass)) { + success++; + } + if (success == args.length) { + constructor = (Constructor) con; + break; + } + } + } + } + List additions = new LinkedList<>(); + for (Class aClass : classes) { + try { + T a = constructor != null ? constructor.newInstance(args) : aClass.getDeclaredConstructor().newInstance(); + additions.add(a); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + break; + } + } + return new RegistryData<>(additions, handle, PACKAGE); + } + + /** + * Acquire all instantiated elements from query using custom constructor arguments and run an operation. + * + * @param operation The operation to run on all initialized objects. + * @param args The constructor arguments to input. + * @return the leftover data from the registry data operation + */ + public RegistryData construct(Consumer operation, Object... args) { + Set> classes = Sets.newHashSet(); + JarFile jarFile = null; + if (this.handle != null) { + try { + jarFile = new JarFile(URLDecoder.decode(this.handle.getClass().getProtectionDomain().getCodeSource().getLocation().getFile(), String.valueOf(StandardCharsets.UTF_8))); + } catch (IOException e) { + e.printStackTrace(); // TODO: Decide whether to return/rethrow at this point so as to avoid NPE on line 89 + } + } + + if (jarFile == null) throw new IllegalStateException("Invalid jar file"); + + Stream entries = jarFile.stream(); + + if (this.filter != null) { + entries.forEach(entry -> { + String className = entry.getName().replace("/", "."); + final String substring = className.substring(0, Math.max(className.length() - 6, 0)); + if (this.filter.test(className)) { + Class clazz = null; + try { + clazz = Class.forName(substring); + } catch (ClassNotFoundException ignored) { + } + if (clazz != null) { + if (type.isAssignableFrom(clazz)) { + classes.add((Class) clazz); + } + } + } + }); + } else { + entries.forEach(entry -> { + + String className = entry.getName().replace("/", "."); + final String substring = className.substring(0, Math.max(className.length() - 6, 0)); + if (this.PACKAGE != null) { + if (className.startsWith(PACKAGE) && className.endsWith(".class")) { + Class clazz = null; + try { + clazz = Class.forName(substring); + } catch (ClassNotFoundException ignored) { + } + if (clazz != null) { + if (type.isAssignableFrom(clazz)) { + classes.add((Class) clazz); + } + } + } + } else { + + if (className.endsWith(".class")) { + Class clazz = null; + try { + clazz = Class.forName(substring); + } catch (ClassNotFoundException ignored) { + } + if (clazz != null) { + if (type.isAssignableFrom(clazz)) { + classes.add((Class) clazz); + } + } + } + } + }); + } + Constructor constructor = null; + for (Constructor con : this.type.getConstructors()) { + if (args.length == con.getParameters().length) { + int success = 0; + for (int i = 0; i < args.length; i++) { + Class objectClass = args[i].getClass(); + Class typeClass = con.getParameters()[i].getType(); + if (objectClass.isAssignableFrom(typeClass)) { + success++; + } + if (success == args.length) { + constructor = (Constructor) con; + break; + } + } + } + } + List additions = new LinkedList<>(); + for (Class aClass : classes) { + try { + T a = constructor != null ? constructor.newInstance(args) : aClass.getDeclaredConstructor().newInstance(); + operation.accept(a); + additions.add(a); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + break; + } + } + return new RegistryData<>(additions, handle, PACKAGE); + } + /** * Specify actions on each element instantiated from query. * @@ -187,18 +394,18 @@ public RegistryData operate(Consumer operation) { Stream entries = jarFile.stream(); - if (this.FILTER != null) { + if (this.filter != null) { entries.forEach(entry -> { String className = entry.getName().replace("/", "."); final String substring = className.substring(0, Math.max(className.length() - 6, 0)); - if (this.FILTER.test(className)) { + if (this.filter.test(className)) { Class clazz = null; try { clazz = Class.forName(substring); } catch (ClassNotFoundException ignored) { } if (clazz != null) { - if (CLASS.isAssignableFrom(clazz)) { + if (type.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } @@ -217,7 +424,7 @@ public RegistryData operate(Consumer operation) { } catch (ClassNotFoundException ignored) { } if (clazz != null) { - if (CLASS.isAssignableFrom(clazz)) { + if (type.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } @@ -231,7 +438,7 @@ public RegistryData operate(Consumer operation) { } catch (ClassNotFoundException ignored) { } if (clazz != null) { - if (CLASS.isAssignableFrom(clazz)) { + if (type.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } @@ -366,12 +573,7 @@ public RegistryData construct(Object... o) { for (Class cl : classes) { if (this.type.isAssignableFrom(cl)) { try { - T e; - if (constructor != null) { - e = (T) cl.getDeclaredConstructor(constructor.getParameterTypes()).newInstance(o); - } else { - e = (T) cl.getDeclaredConstructor().newInstance(); - } + T e = constructor != null ? constructor.newInstance(o) : (T) cl.getDeclaredConstructor().newInstance(); data.add(e); } catch (Exception ex) { ex.printStackTrace(); @@ -408,12 +610,7 @@ public RegistryData construct(Consumer action, Object... o) { for (Class cl : classes) { if (this.type.isAssignableFrom(cl)) { try { - T e; - if (constructor != null) { - e = (T) cl.getDeclaredConstructor(constructor.getParameterTypes()).newInstance(o); - } else { - e = (T) cl.getDeclaredConstructor().newInstance(); - } + T e = constructor != null ? constructor.newInstance(o) : (T) cl.getDeclaredConstructor().newInstance(); action.accept(e); data.add(e); } catch (Exception ex) { diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlas.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlas.java index 1f34a6fc..67534d3d 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlas.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlas.java @@ -15,4 +15,6 @@ default String getPath() { return null; } + char getDivider(); + } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasMap.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasMap.java index 818c4ae8..8b4af89a 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasMap.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasMap.java @@ -1,5 +1,6 @@ package com.github.sanctum.labyrinth.data.container; +import com.github.sanctum.labyrinth.data.MapDecompressionUtils; import com.github.sanctum.labyrinth.data.MemorySpace; import com.github.sanctum.labyrinth.data.Node; import com.github.sanctum.labyrinth.data.ReplaceableKeyedValue; @@ -18,12 +19,25 @@ public class LabyrinthAtlasMap implements LabyrinthAtlas { - private final LabyrinthMap SOURCE = new LabyrinthEntryMap<>(); + protected final LabyrinthMap SOURCE = new LabyrinthEntryMap<>(); protected final LabyrinthMap QUERY = new LabyrinthEntryMap<>(); + protected final char divider; + + public LabyrinthAtlasMap() { + this.divider = '.'; + } + + public LabyrinthAtlasMap(char divider) { + this.divider = divider; + } + + String dividerAdapt() { + return divider == '.' ? "[" + divider + "]" : divider + ""; + } @Override public boolean isNode(String key) { - String[] a = key.split("\\."); + String[] a = key.split(dividerAdapt()); String k = a[Math.max(0, a.length - 1)]; LabyrinthMap o = SOURCE; for (int i = 0; i < a.length - 1; i++) { @@ -53,76 +67,34 @@ public Node getNode(String key) { @Override public Set getKeys(boolean deep) { Set keys = new HashSet<>(); - for (Object o : SOURCE.entries()) { - Map.Entry entry = (Map.Entry) o; + SOURCE.forEach(e -> { if (deep) { - if (entry.getValue() instanceof Map) { - Map obj = (Map) entry.getValue(); - for (Object ob : obj.entrySet()) { - Map.Entry en = (Map.Entry) ob; - if (en.getValue() instanceof Map) { - Map j = (Map) entry.getValue(); - for (Object e : j.entrySet()) { - Map.Entry ent = (Map.Entry) e; - if (ent.getValue() instanceof Map) { - Map ja = (Map) ent.getValue(); - for (Object ex : ja.entrySet()) { - Map.Entry entr = (Map.Entry) ex; - keys.add(entry.getKey() + "." + en.getKey() + "." + ent.getKey() + "." + entr.getKey()); - } - } else { - keys.add(entry.getKey() + "." + en.getKey() + "." + ent.getKey()); - } - } - } else { - keys.add(entry.getKey() + "." + en.getKey()); - } - } + if (e.getValue() instanceof LabyrinthMap) { + MapDecompressionUtils.getInstance().decompress((LabyrinthMap) e.getValue(), divider, null).toLabyrinthSet().forEach(keys::add); } else { - keys.add(entry.getKey()); + keys.add(e.getKey()); } } else { - keys.add(entry.getKey()); + keys.add(e.getKey()); } - } + }); return keys; } @Override public Map getValues(boolean deep) { Map map = new HashMap<>(); - for (Object o : SOURCE.entries()) { - Map.Entry entry = (Map.Entry) o; + SOURCE.forEach(e -> { if (deep) { - if (entry.getValue() instanceof Map) { - Map obj = (Map) entry.getValue(); - for (Object ob : obj.entrySet()) { - Map.Entry en = (Map.Entry) ob; - if (en.getValue() instanceof Map) { - Map j = (Map) entry.getValue(); - for (Object e : j.entrySet()) { - Map.Entry ent = (Map.Entry) e; - if (ent.getValue() instanceof Map) { - Map ja = (Map) ent.getValue(); - for (Object ex : ja.entrySet()) { - Map.Entry entr = (Map.Entry) ex; - map.put(entry.getKey() + "." + en.getKey() + "." + ent.getKey() + "." + entr.getKey(), entr.getValue()); - } - } else { - map.put(entry.getKey() + "." + en.getKey() + "." + ent.getKey(), ent.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + en.getKey(), en.getValue()); - } - } + if (e.getValue() instanceof LabyrinthMap) { + MapDecompressionUtils.getInstance().decompress((LabyrinthMap) e.getValue(), divider, null).toLabyrinthMap().forEach(ev -> map.put(ev.getKey(), ev.getValue())); } else { - map.put(entry.getKey(), entry.getValue()); + map.put(e.getKey(), e.getValue()); } } else { - map.put(entry.getKey(), entry.getValue()); + map.put(e.getKey(), e.getValue()); } - } + }); return map; } @@ -148,8 +120,7 @@ public boolean containsValue(Object value) { @Override public Object get(String key) { - String ke = key; - String[] a = ke.split("\\."); + String[] a = key.split(dividerAdapt()); String k = a[Math.max(0, a.length - 1)]; LabyrinthMap o = SOURCE; for (int i = 0; i < a.length - 1; i++) { @@ -172,7 +143,7 @@ public Object get(String key) { @Nullable @Override public Object put(String key, Object o) { - String[] a = key.split("\\."); + String[] a = key.split(dividerAdapt()); String k = a[Math.max(0, a.length - 1)]; LabyrinthMap ob = SOURCE; for (int i = 0; i < a.length - 1; i++) { @@ -220,4 +191,9 @@ public void clear() { public Iterator> iterator() { return SOURCE.iterator(); } + + @Override + public char getDivider() { + return divider; + } } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasNode.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasNode.java index 3fdbb6a6..ad1d1b6c 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasNode.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/container/LabyrinthAtlasNode.java @@ -1,5 +1,6 @@ package com.github.sanctum.labyrinth.data.container; +import com.github.sanctum.labyrinth.data.MapDecompressionUtils; import com.github.sanctum.labyrinth.data.Node; import com.github.sanctum.labyrinth.data.Primitive; import com.google.gson.Gson; @@ -54,13 +55,13 @@ public void set(Object o) { @Override public Node getParent() { - String[] k = this.key.split("//."); + String[] k = this.key.split(MAP.dividerAdapt()); StringBuilder builder = new StringBuilder(); for (int i = 0; i < k.length - 1; i++) { - builder.append(k[i]).append("."); + builder.append(k[i]).append(MAP.divider); } String key = builder.toString(); - if (key.endsWith(".")) { + if (key.endsWith(MAP.divider + "")) { key = key.substring(0, builder.length() - 1); } if (key.equals(this.key)) return this; @@ -80,14 +81,14 @@ public String getPath() { @Override public boolean isNode(String node) { - return MAP.isNode(this.key + "." + node); + return MAP.isNode(this.key + MAP.divider + node); } @Override public Node getNode(String node) { - return (Node) Optional.ofNullable(MAP.QUERY.get(this.key + "." + node)).orElseGet(() -> { - LabyrinthAtlasNode n = new LabyrinthAtlasNode(this.key + "." + node, MAP); - MAP.QUERY.put(this.key + "." + node, n); + return (Node) Optional.ofNullable(MAP.QUERY.get(this.key + MAP.divider + node)).orElseGet(() -> { + LabyrinthAtlasNode n = new LabyrinthAtlasNode(this.key + MAP.divider + node, MAP); + MAP.QUERY.put(this.key + MAP.divider + node, n); return n; }); } @@ -95,34 +96,12 @@ public Node getNode(String node) { @Override public Set getKeys(boolean deep) { Set keys = new HashSet<>(); - if (get() instanceof Map) { - Map map1 = (Map) get(); + if (get() instanceof LabyrinthMap) { + LabyrinthMap map1 = (LabyrinthMap) get(); if (deep) { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - keys.add(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey()); - } - } else { - keys.add(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey()); - } - } - } else { - keys.add(entry.getKey() + "." + entry2.getKey()); - } - } - } - keys.add(entry.getKey()); - } + return MapDecompressionUtils.getInstance().decompress(map1, MAP.divider, null).toSet(); } else { - for (Map.Entry entry : map1.entrySet()) { + for (Map.Entry entry : map1.entries()) { keys.add(entry.getKey()); } } @@ -135,56 +114,13 @@ public Set getKeys(boolean deep) { @Override public Map getValues(boolean deep) { Map map = new HashMap<>(); - if (get() instanceof Map) { - Map map1 = (Map) get(); + if (get() instanceof LabyrinthMap) { + LabyrinthMap map1 = (LabyrinthMap) get(); if (deep) { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - map.put(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey(), entry4.getValue()); - } - } else { - map.put(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey(), entry3.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + entry2.getKey(), entry2.getValue()); - } - } - } - map.put(entry.getKey(), entry.getValue()); - } + return MapDecompressionUtils.getInstance().decompress(map1, MAP.divider, null).toMap(); } else { - for (Map.Entry entry : map1.entrySet()) { - if (entry.getValue() instanceof Map) { - Map map2 = (Map) entry.getValue(); - for (Map.Entry entry2 : map2.entrySet()) { - if (entry2.getValue() instanceof Map) { - Map map3 = (Map) entry2.getValue(); - for (Map.Entry entry3 : map3.entrySet()) { - if (entry3.getValue() instanceof Map) { - Map map4 = (Map) entry2.getValue(); - for (Map.Entry entry4 : map4.entrySet()) { - map.put(this.key + "." + entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey() + "." + entry4.getKey(), entry4.getValue()); - } - } else { - map.put(entry.getKey() + "." + entry2.getKey() + "." + entry3.getKey(), entry3.getValue()); - } - } - } else { - map.put(entry.getKey() + "." + entry2.getKey(), entry2.getValue()); - } - } - } else { - map.put(entry.getKey(), entry.getValue()); - } + for (Map.Entry entry : map1.entries()) { + map.put(entry.getKey(), entry.getValue()); } } } else { diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/service/Check.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/service/Check.java index 35462a98..da5b7c5d 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/service/Check.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/data/service/Check.java @@ -6,7 +6,6 @@ import com.github.sanctum.labyrinth.annotation.Note; import com.github.sanctum.labyrinth.api.Service; import com.github.sanctum.labyrinth.library.Mailer; -import com.github.sanctum.labyrinth.library.Message; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/event/custom/VentMap.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/event/custom/VentMap.java index 043cae6e..f377ec91 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/event/custom/VentMap.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/event/custom/VentMap.java @@ -10,7 +10,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -//FIXME public abstract class VentMap implements Service { /** diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/ComponentChunk.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/ComponentChunk.java index c1e25127..697c00fa 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/ComponentChunk.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/ComponentChunk.java @@ -2,6 +2,7 @@ import com.github.sanctum.labyrinth.LabyrinthProvider; import com.github.sanctum.labyrinth.formatting.string.CustomColor; +import com.github.sanctum.labyrinth.formatting.string.FormattedString; import com.github.sanctum.labyrinth.library.ListUtils; import com.github.sanctum.labyrinth.library.StringUtils; import java.util.ArrayList; @@ -126,7 +127,7 @@ public Message.Chunk replace(String text, String replacement) { TextComponent replace = new TextComponent(); List components = new ArrayList<>(); for (BaseComponent c : parent.getExtra()) { - TextComponent n = new TextComponent(StringUtils.use(c.toLegacyText()).replaceIgnoreCase(text, replacement)); + TextComponent n = new TextComponent(new FormattedString(c.toLegacyText()).replace(text, replacement).get()); components.add(n); } replace.setExtra(components); @@ -136,7 +137,6 @@ public Message.Chunk replace(String text, String replacement) { @Override public String getText() { - Bukkit.broadcastMessage("Got text '" + parent.getText() + "'"); return parent.getText(); } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/TextChunk.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/TextChunk.java index ea8f4fc4..942466ee 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/TextChunk.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/TextChunk.java @@ -2,6 +2,7 @@ import com.github.sanctum.labyrinth.LabyrinthProvider; import com.github.sanctum.labyrinth.formatting.string.CustomColor; +import com.github.sanctum.labyrinth.formatting.string.FormattedString; import com.github.sanctum.labyrinth.library.ListUtils; import com.github.sanctum.labyrinth.library.StringUtils; import java.util.ArrayList; @@ -133,7 +134,7 @@ public TextChunk setText(String text) { @Override public Message.Chunk replace(String text, String replacement) { - this.text = StringUtils.use(this.text).replaceIgnoreCase(text, replacement); + this.text = new FormattedString(this.text).replace(text, replacement).get(); return this; } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/pagination/AbstractPaginatedCollection.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/pagination/AbstractPaginatedCollection.java index f5985287..1865b313 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/pagination/AbstractPaginatedCollection.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/pagination/AbstractPaginatedCollection.java @@ -102,30 +102,30 @@ public AbstractPaginatedCollection limit(int elementsPer) { * @return A deployable reordering operation. */ public Deployable> reorder() { - return Deployable.of(this, collection1 -> { - collection1.sorted = true; + return Deployable.of(() -> { + sorted = true; Set> toAdd = new HashSet<>(); List toSort = new ArrayList<>(); - if (collection1.predicate != null) { - toSort = collection1.collection.stream().filter(collection1.predicate).collect(Collectors.toList()); + if (predicate != null) { + toSort = collection.stream().filter(predicate).collect(Collectors.toList()); } - if (collection1.comparator != null) { + if (comparator != null) { if (toSort.isEmpty()) { - toSort = collection1.collection.stream().sorted(collection1.comparator).collect(Collectors.toList()); + toSort = collection.stream().sorted(comparator).collect(Collectors.toList()); } else { - toSort = toSort.stream().sorted(collection1.comparator).collect(Collectors.toList()); + toSort = toSort.stream().sorted(comparator).collect(Collectors.toList()); } } if (toSort.isEmpty()) { - toSort = new ArrayList<>(collection1.collection); + toSort = new ArrayList<>(collection); } - collection1.collection = toSort; + collection = toSort; - int totalPageCount = collection1.size(); + int totalPageCount = size(); for (int slot = 1; slot < totalPageCount + 1; slot++) { int page = slot; - Page newPage = new Page.Impl<>(collection1, slot); + Page newPage = new Page.Impl<>(AbstractPaginatedCollection.this, slot); if (page <= totalPageCount) { if (!toSort.isEmpty()) { @@ -134,7 +134,7 @@ public Deployable> reorder() { for (T value : toSort) { index++; - if ((((page * collection1.initialElementsPer) + placeholder + 1) == index) && (index != ((page * collection1.initialElementsPer) + collection1.initialElementsPer + 1))) { + if ((((page * initialElementsPer) + placeholder + 1) == index) && (index != ((page * initialElementsPer) + initialElementsPer + 1))) { placeholder++; newPage.add(value); } @@ -144,7 +144,8 @@ public Deployable> reorder() { } toAdd.add(newPage); } - collection1.set.addAll(toAdd); + set.addAll(toAdd); + return AbstractPaginatedCollection.this; }); } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/string/FormattedString.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/string/FormattedString.java index 691aa9e2..9e03c072 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/string/FormattedString.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/formatting/string/FormattedString.java @@ -8,63 +8,61 @@ public final class FormattedString { - private final String context; - private String formatted; + private String context; public FormattedString(@NotNull String context) { this.context = context; - this.formatted = context; } public FormattedString append(char c) { - this.formatted += String.valueOf(c); + this.context += String.valueOf(c); return this; } public FormattedString append(@NotNull CharSequence sequence) { - this.formatted += sequence.toString(); + this.context += sequence.toString(); return this; } public FormattedString append(@NotNull Number number) { if (number instanceof Double) { - this.formatted += number.doubleValue(); + this.context += number.doubleValue(); } if (number instanceof Long) { - this.formatted += number.longValue(); + this.context += number.longValue(); } if (number instanceof Integer) { - this.formatted += number.intValue(); + this.context += number.intValue(); } if (number instanceof Short) { - this.formatted += number.shortValue(); + this.context += number.shortValue(); } if (number instanceof Float) { - this.formatted += number.floatValue(); + this.context += number.floatValue(); } if (number instanceof Byte) { - this.formatted += number.byteValue(); + this.context += number.byteValue(); } return this; } public FormattedString color() { - this.formatted = new ColoredString(formatted).toString(); + this.context = new ColoredString(context).toString(); return this; } public FormattedString translate() { - this.formatted = LabyrinthProvider.getService(PlaceholderFormatService.class).replaceAll(context, null); + this.context = LabyrinthProvider.getService(PlaceholderFormatService.class).replaceAll(context, null); return this; } public FormattedString translate(@NotNull Object variable) { - this.formatted = LabyrinthProvider.getService(PlaceholderFormatService.class).replaceAll(context, variable); + this.context = LabyrinthProvider.getService(PlaceholderFormatService.class).replaceAll(context, variable); return this; } public FormattedString replace(@NotNull String regex, @NotNull String replacement) { - this.formatted = Pattern.compile(regex, Pattern.LITERAL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(formatted) + this.context = Pattern.compile(regex, Pattern.LITERAL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(this.context) .replaceAll(Matcher.quoteReplacement(replacement)); return this; } @@ -84,7 +82,7 @@ public boolean containsAll(CharSequence... sequences) { } public String get() { - return formatted; + return context; } } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Deployable.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Deployable.java index 1badf965..6f72af81 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Deployable.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Deployable.java @@ -4,10 +4,14 @@ import com.github.sanctum.labyrinth.annotation.Note; import com.github.sanctum.labyrinth.api.Service; import com.github.sanctum.labyrinth.api.TaskService; +import com.github.sanctum.labyrinth.interfacing.UnknownGeneric; +import com.github.sanctum.labyrinth.task.TaskScheduler; import java.util.Date; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -107,6 +111,15 @@ public interface Deployable { */ CompletableFuture submit(); + /** + * Check if this deployable has been deployed. + * + * @return true if the resulting object of this deployable has already been processed. + */ + default boolean isDeployed() { + return get() != null; + } + /** * Complete the deployable information processing and get the object reference. * @@ -126,6 +139,26 @@ default T get() { return complete(); } + /** + * Get the object reference or provide another one instead. + * + * @param other The other object to provide. + * @return An object reference. + */ + default T orElse(T other) { + return Optional.ofNullable(get()).orElse(other); + } + + /** + * Get the object reference or provide another one instead. + * + * @param supplier The other object to provide. + * @return An object reference. + */ + default T orElseGet(Supplier supplier) { + return Optional.ofNullable(get()).orElseGet(supplier); + } + /** * Create a default deployable instance * @@ -136,7 +169,6 @@ default T get() { */ static Deployable of(@Nullable T t, final @NotNull Consumer action) { return new Deployable() { - @Override public Deployable deploy() { action.accept(t); @@ -198,4 +230,146 @@ public CompletableFuture submit() { }; } + /** + * Create a default deployable runnable instance + * + * @return A fresh deployable instance. + */ + static Deployable of(Runnable runnable) { + return new Deployable() { + + final UnknownGeneric g = new UnknownGeneric(){}; + + @Override + public Deployable deploy() { + runnable.run(); + return this; + } + + @Override + public Deployable deploy(Consumer consumer) { + deploy(); + consumer.accept(g); + return this; + } + + @Override + public Deployable queue() { + TaskScheduler.of(runnable).schedule(); + return this; + } + + @Override + public Deployable queue(Consumer consumer, long timeout) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(() -> { + runnable.run(); + consumer.accept(g); + }, HUID.randomID().toString(), timeout); + return this; + } + + @Override + public Deployable queue(Consumer consumer, Date date) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(() -> { + runnable.run(); + consumer.accept(g); + }, HUID.randomID().toString(), date); + return this; + } + + @Override + public DeployableMapping map(Function mapper) { + return new DeployableMapping<>(() -> submit().join(), (Function) mapper); + } + + @Override + public Deployable queue(long timeout) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(runnable, HUID.randomID().toString(), timeout); + return this; + } + + @Override + public Deployable queue(Date date) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(runnable, HUID.randomID().toString(), date); + return this; + } + + @Override + public CompletableFuture submit() { + return CompletableFuture.supplyAsync(() -> g); + } + }; + } + + /** + * Create a default deployable supplier instance + * + * @return A fresh deployable instance. + */ + static Deployable of(Supplier supplier) { + return new Deployable() { + + T element; + + @Override + public Deployable deploy() { + element = supplier.get(); + return this; + } + + @Override + public Deployable deploy(Consumer consumer) { + deploy(); + consumer.accept(element); + return this; + } + + @Override + public Deployable queue() { + element = submit().join(); + return this; + } + + @Override + public Deployable queue(Consumer consumer, long timeout) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(() -> { + deploy(); + consumer.accept(element); + }, HUID.randomID().toString(), timeout); + return this; + } + + @Override + public Deployable queue(Consumer consumer, Date date) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(() -> { + deploy(); + consumer.accept(element); + }, HUID.randomID().toString(), date); + return this; + } + + @Override + public DeployableMapping map(Function mapper) { + return new DeployableMapping<>(() -> deploy().get(), (Function) mapper); + } + + @Override + public Deployable queue(long timeout) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(this::deploy, HUID.randomID().toString(), timeout); + return this; + } + + @Override + public Deployable queue(Date date) { + LabyrinthProvider.getService(Service.TASK).getScheduler(TaskService.SYNCHRONOUS).wait(this::deploy, HUID.randomID().toString(), date); + return this; + } + + @Override + public CompletableFuture submit() { + return CompletableFuture.supplyAsync(supplier); + } + }; + } + } diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/DeployableMapping.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/DeployableMapping.java index 06dc87ff..dbec17db 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/DeployableMapping.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/DeployableMapping.java @@ -4,6 +4,7 @@ import com.github.sanctum.labyrinth.annotation.Comment; import com.github.sanctum.labyrinth.api.Service; import com.github.sanctum.labyrinth.api.TaskService; +import com.github.sanctum.labyrinth.task.TaskScheduler; import java.util.Date; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -22,6 +23,11 @@ public final class DeployableMapping implements Deployable { this.parent = o.get(); } + @Override + public R get() { + return value; + } + @Override public DeployableMapping deploy() { if (this.value == null) { @@ -41,7 +47,7 @@ public DeployableMapping deploy(Consumer consumer) { @Override public DeployableMapping queue() { - deploy(); + TaskScheduler.of(this::deploy).schedule(); return this; } @@ -77,7 +83,7 @@ public DeployableMapping queue(Consumer consumer, Date date) { @Override public DeployableMapping map(Function mapper) { - return new DeployableMapping<>(() -> submit().join(), (Function) mapper); + return new DeployableMapping<>(() -> deploy().get(), (Function) mapper); } @Override diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Item.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Item.java index c5166e05..1eb821ca 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Item.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Item.java @@ -47,7 +47,6 @@ * * @author Hempfest */ -@SuppressWarnings("ConstantConditions") public class Item { private static final LinkedList cache = new LinkedList<>(); @@ -166,54 +165,6 @@ public Item shape(Consumer consumer) { return shape(workbench); } - @Deprecated - @Note("Use Item#process() or Item#edit() instead.") - public Item buildStack() { - ItemStack item = new ItemStack(mat); - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(StringUtils.use(name).translate()); - item.setItemMeta(meta); - this.item = item; - return this; - } - - @Deprecated - @Note("Use Item#edit() instead.") - public Item attachLore(List lore) { - ItemMeta meta = item.getItemMeta(); - meta.setLore(lore.stream().map(s -> StringUtils.use(s).translate()).collect(Collectors.toList())); - item.setItemMeta(meta); - return this; - } - - @Deprecated - @Note("Use Item#edit() instead.") - public Item addEnchant(Enchantment e, int level) { - ItemStack i = item; - i.addUnsafeEnchantment(e, level); - this.item = i; - return this; - } - - @Deprecated - @Note("Use Item#shape(Consumer) or Item#shape(Workbench) instead.") - public Item shapeRecipe(String... shape) { - ShapedRecipe recipe = new ShapedRecipe(key, item); - String top = shape[0]; - String middle = shape[1]; - String bottom = shape[2]; - recipe.shape(top, middle, bottom); - if (!this.recipeStackMap.isEmpty()) { - setupItemstacks(recipe, top, middle, bottom); - } - if (!this.recipeMap.isEmpty()) { - setupMaterials(recipe, top, middle, bottom); - } - - this.recipe = recipe; - return this; - } - void setupItemstacks(ShapedRecipe recipe, String top, String middle, String bottom) { if (this.recipeStackMap.get(top.charAt(0)) != null) { recipe.setIngredient((top).charAt(0), new RecipeChoice.ExactChoice(this.recipeStackMap.get(top.charAt(0)))); diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/ListUtils.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/ListUtils.java index 49ee0e08..9080528d 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/ListUtils.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/ListUtils.java @@ -37,7 +37,7 @@ public static ListUtils use(List list) { * @return a list utility for element appendage/replacement */ public static ListUtils use(T[] list) { - return use(Arrays.asList(list)); + return new ListUtils<>(Arrays.asList(list)); } /** diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Message.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Message.java deleted file mode 100644 index 51cf7d0a..00000000 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Message.java +++ /dev/null @@ -1,249 +0,0 @@ -package com.github.sanctum.labyrinth.library; - -import com.github.sanctum.labyrinth.formatting.string.ColoredString; -import java.util.function.Predicate; -import java.util.logging.Logger; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.BaseComponent; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; - -/** - * @deprecated Use {@linkplain Mailer} instead! - * @author Hempfest - */ -@SuppressWarnings("UnusedReturnValue") -@Deprecated -public class Message { - - private Logger logger = Logger.getLogger("Minecraft"); - private Plugin plugin; - private String prefix; - private Player p; - - - public Message(Plugin plugin) { - this.plugin = plugin; - this.logger = plugin.getLogger(); - } - - /** - * Send a specified player messages. - * - * @param p the player to use - */ - public Message(Player p) { - this.p = p; - this.prefix = ""; - } - - /** - * Send the specified player messages with a specified prefix. - * - * @param p the player to use - * @param prefix the prefix to send - */ - public Message(Player p, String prefix) { - this.p = p; - this.prefix = prefix; - } - - /** - * Update the player to receive the messages. - * - * @param player the new player should now receive messages - * @return this Message instance - */ - public Message setPlayer(Player player) { - this.p = player; - return this; - } - - /** - * @deprecated Use {@link Message#setPlayer(Player)} - */ - @Deprecated - public Message assignPlayer(Player player) { - this.p = player; - return this; - } - - /** - * Update the prefix used for the message. - * - * @param prefix the prefix to use - * @return this Message instance - */ - public Message setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - /** - * Send a string message to a player automatically colored. - * - * @param text the context to send the player - * @return this Message instance - */ - public Message send(String text) { - String result; - if (prefix == null || prefix.isEmpty()) { - result = StringUtils.use(text).translate(); - } else { - result = StringUtils.use(prefix + " " + text).translate(); - } - p.sendMessage(result); - return this; - } - - /** - * Broadcast a message publicly. - * - * @param text the context to broadcast - * @return this Message instance - */ - public Message broadcast(String text) { - if (plugin != null) { - if (this.prefix == null) { - this.prefix = "&7[&e" + plugin.getName() + "&7]&r"; - } - Bukkit.broadcastMessage(StringUtils.use(prefix + " " + text).translate()); - } - return this; - } - - /** - * Broadcast a message publicly to those with permission. - * - * @param text the context to broadcast - * @return this Message instance - */ - public Message broadcast(String text, String permission) { - if (plugin != null) { - if (this.prefix == null) { - this.prefix = "&7[&e" + plugin.getName() + "&7]&r"; - } - Bukkit.broadcast(StringUtils.use(prefix + " " + text).translate(), permission); - } - return this; - } - - /** - * Broadcast a message publicly to those who meet the desired terms. - * - * @param text The text to broadcast. - * @param player The prerequisite to receiving the message. - * @return this Message instance. - */ - public Message broadcast(String text, Predicate player) { - if (plugin != null) { - if (this.prefix == null) { - this.prefix = "&7[&e" + plugin.getName() + "&7]&r"; - } - for (Player p : Bukkit.getOnlinePlayers()) { - if (player.test(p)) { - p.sendMessage(StringUtils.use(prefix + " " + text).translate()); - } - } - } else { - for (Player p : Bukkit.getOnlinePlayers()) { - if (player.test(p)) { - p.sendMessage(StringUtils.use(text).translate()); - } - } - } - return this; - } - - /** - * Send the player an interactive chat component. - * - * @param component the component to build and send - * @return this Message instance - */ - public Message build(BaseComponent component) { - p.spigot().sendMessage(component); - return this; - } - - /** - * Send a player the list of interactive chat components. - * - * @param components the list of interactive chat to send - * @return this Message instance - */ - public Message build(BaseComponent... components) { - p.spigot().sendMessage(components); - return this; - } - - /** - * Send an action bar message to the player. - * - * @param text the message to display - * @return this Message instance - */ - public Message action(String text) { - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new ColoredString(text, ColoredString.ColorType.HEX).toComponent()); - return this; - } - - /** - * NOTE: Only for console use. - *

- * Send console an info message. - * - * @param text the text to be used within the message - */ - public Message info(String text) { - logger.info(text); - return this; - } - - /** - * NOTE: Only for console use. - *

- * Send console an error message. - * - * @param text the text to be used within the message - */ - public Message error(String text) { - logger.severe(text); - return this; - } - - /** - * NOTE: Only for console use. - *

- * Send console a warning message. - * - * @param text the text to be used within the message - */ - public Message warn(String text) { - logger.warning(text); - return this; - } - - /** - * Use this to easily send message degrees to console. - * - * @param plugin the plugin to log console messages for - * @return a console messaging object - */ - public static Message loggedFor(Plugin plugin) { - return new Message(plugin); - } - - /** - * Use this to easily send messages to player or server. - * - * @param player the target player - * @return a player & server messaging object - */ - public static Message form(Player player) { - return new Message(player); - } - - -} diff --git a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Workbench.java b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Workbench.java index a91c84f2..4b4e807d 100644 --- a/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Workbench.java +++ b/labyrinth-common/src/main/java/com/github/sanctum/labyrinth/library/Workbench.java @@ -2,6 +2,7 @@ import com.github.sanctum.labyrinth.data.SimpleKeyedValue; import com.github.sanctum.labyrinth.data.container.LabyrinthCollection; +import org.bukkit.entity.Player; public interface Workbench { @@ -16,4 +17,8 @@ default Workbench put(char symbol, WorkbenchSlot... slots) { LabyrinthCollection> get(); + static void open(Player player) { + player.openWorkbench(null, true); + } + } diff --git a/labyrinth-gui/src/main/java/com/github/sanctum/labyrinth/gui/unity/simple/MemoryDocket.java b/labyrinth-gui/src/main/java/com/github/sanctum/labyrinth/gui/unity/simple/MemoryDocket.java index 8872aa68..85a2534c 100644 --- a/labyrinth-gui/src/main/java/com/github/sanctum/labyrinth/gui/unity/simple/MemoryDocket.java +++ b/labyrinth-gui/src/main/java/com/github/sanctum/labyrinth/gui/unity/simple/MemoryDocket.java @@ -83,7 +83,7 @@ public MemoryDocket setFilter(Predicate predicate) { return this; } - @Comment("This method is used for translating player names for skull items, it is expected to be the placeholder for returning a player username and is used in tandem with a Unique Data Converter") + @Note("This method is used for translating player names for skull items, it is expected to be the placeholder for returning a player username and is used in tandem with a Unique Data Converter") public MemoryDocket setNamePlaceholder(@NotNull String placeholder) { this.nameHolder = placeholder; return this; @@ -95,48 +95,13 @@ public MemoryDocket setDataConverter(@NotNull WideFunction return this; } - @Comment("This method is used for setting up unique translations. Example; a singular parent object being attached for extra placeholders.") + @Note("This method is used for setting up unique translations. Example; a singular parent object being attached for extra placeholders.") public MemoryDocket setUniqueDataConverter(@NotNull V t, @NotNull WideFunction function) { this.uniqueData = t; this.uniqueDataConverter = (WideFunction) function; return this; } - private void handleClickEvent(MemoryItem item, ItemElement ed) { - if (item.isNotRemovable()) { - ed.setClick(click -> { - click.setCancelled(true); - if (item.isExitOnClick()) click.getParent().getParent().getParent().close(click.getElement()); - if (item.getMessage() != null) { - String message = item.getMessage(); - if (uniqueData != null) { - message = uniqueDataConverter.accept(message, uniqueData); - } - Mailer.empty(click.getElement()).chat(message).deploy(); - } - if (item.getOpenOnClick() != null) { - String open = item.getOpenOnClick(); - if (uniqueData != null) { - open = uniqueDataConverter.accept(open, uniqueData); - } - MenuRegistration registration = MenuRegistration.getInstance(); - Menu registered = registration.get(open).get(); - if (registered != null) { - registered.open(click.getElement()); - } else { - if (item.getOpenOnClick().startsWith("/")) { - String command = item.getOpenOnClick().replace("/", ""); - if (uniqueData != null) { - command = uniqueDataConverter.accept(command, uniqueData); - } - click.getElement().performCommand(command); - } - } - } - }); - } - } - @Override public @NotNull Docket load() { this.title = memory.getNode("title").toPrimitive().getString(); @@ -176,6 +141,7 @@ private void handleClickEvent(MemoryItem item, ItemElement ed) { ItemStack result = i.toItem(); ItemElement element = new ItemElement<>(); element.setElement(result); + handlePlayerHeadLookup(true, result, element); if (i.getSlot() > -1) { element.setSlot(i.getSlot()); } @@ -242,21 +208,7 @@ private void handleClickEvent(MemoryItem item, ItemElement ed) { element.setLimit(pagination.getLimit()); element.setPopulate((value, item) -> { item.setElement(built); - if (dataConverter != null && nameHolder != null && new FormattedString(built.getType().name()).contains("player_head", "skull_item")) { - String name = dataConverter.accept(nameHolder, value); - PlayerSearch search = PlayerSearch.of(name); - if (search != null) { - item.setElement(edit -> edit.setItem(CustomHead.Manager.get(search.getPlayer())).build()); - if (built.hasItemMeta()) { - if (built.getItemMeta().hasDisplayName()) { - item.setElement(edit -> edit.setTitle(built.getItemMeta().getDisplayName()).build()); - } - if (built.getItemMeta().hasLore()) { - item.setElement(edit -> edit.setLore(built.getItemMeta().getLore()).build()); - } - } - } - } + handlePlayerHeadLookup(false, built, item, value); String title = item.getName(); if (pagination != null) { if (pagination.isNotRemovable()) { @@ -387,6 +339,62 @@ private void handleClickEvent(MemoryItem item, ItemElement ed) { return instance; } + protected void handleClickEvent(MemoryItem item, ItemElement ed) { + if (item.isNotRemovable()) { + ed.setClick(click -> { + click.setCancelled(true); + if (item.isExitOnClick()) click.getParent().getParent().getParent().close(click.getElement()); + if (item.getMessage() != null) { + String message = item.getMessage(); + if (uniqueData != null) { + message = uniqueDataConverter.accept(message, uniqueData); + } + Mailer.empty(click.getElement()).chat(message).deploy(); + } + if (item.getOpenOnClick() != null) { + String open = item.getOpenOnClick(); + if (uniqueData != null) { + open = uniqueDataConverter.accept(open, uniqueData); + } + MenuRegistration registration = MenuRegistration.getInstance(); + Menu registered = registration.get(open).get(); + if (registered != null) { + registered.open(click.getElement()); + } else { + if (item.getOpenOnClick().startsWith("/")) { + String command = item.getOpenOnClick().replace("/", ""); + if (uniqueData != null) { + command = uniqueDataConverter.accept(command, uniqueData); + } + click.getElement().performCommand(command); + } + } + } + }); + } + } + + @Comment("Handle player head to user translations, local being a unique object instead of paginated.") + protected void handlePlayerHeadLookup(boolean local, ItemStack built, ItemElement item, Object... args) { + boolean pass = local ? !Check.isNull(uniqueData, uniqueDataConverter, nameHolder) : !Check.isNull(dataConverter, nameHolder); + if (pass && new FormattedString(built.getType().name()).contains("player_head", "skull_item")) { + String name = local ? uniqueDataConverter.accept(nameHolder, uniqueData) : dataConverter.accept(nameHolder, (T) args[0]); + PlayerSearch search = PlayerSearch.of(name); + if (search != null) { + item.setElement(edit -> edit.setItem(CustomHead.Manager.get(search.getPlayer())).build()); + if (built.hasItemMeta()) { + if (built.getItemMeta().hasDisplayName()) { + item.setElement(edit -> edit.setTitle(built.getItemMeta().getDisplayName()).build()); + } + if (built.getItemMeta().hasLore()) { + item.setElement(edit -> edit.setLore(built.getItemMeta().getLore()).build()); + } + } + } + } + } + + @Comment("Handle memory item placeholder translation on a string with a provided value") protected String handlePaginationReplacements(MemoryItem item, String context, T value) { final FormattedString string = new FormattedString(context); for (Map.Entry entry : item.getReplacements().entrySet()) { diff --git a/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/Labyrinth.java b/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/Labyrinth.java index ad0e1e93..1b04702a 100644 --- a/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/Labyrinth.java +++ b/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/Labyrinth.java @@ -32,17 +32,11 @@ import com.github.sanctum.labyrinth.event.custom.Vent; import com.github.sanctum.labyrinth.event.custom.VentMap; import com.github.sanctum.labyrinth.event.custom.VentMapImpl; -import com.github.sanctum.labyrinth.formatting.FancyMessage; import com.github.sanctum.labyrinth.formatting.Message; import com.github.sanctum.labyrinth.formatting.completion.SimpleTabCompletion; import com.github.sanctum.labyrinth.formatting.completion.TabCompletionIndex; import com.github.sanctum.labyrinth.formatting.component.ActionComponent; import com.github.sanctum.labyrinth.formatting.string.CustomColor; -import com.github.sanctum.labyrinth.formatting.string.DefaultColor; -import com.github.sanctum.labyrinth.gui.unity.construct.Menu; -import com.github.sanctum.labyrinth.gui.unity.construct.MenuRegistration; -import com.github.sanctum.labyrinth.gui.unity.simple.Docket; -import com.github.sanctum.labyrinth.gui.unity.simple.MemoryDocket; import com.github.sanctum.labyrinth.library.Applicable; import com.github.sanctum.labyrinth.library.CommandUtils; import com.github.sanctum.labyrinth.library.Cooldown; @@ -54,7 +48,6 @@ import com.github.sanctum.labyrinth.library.StringUtils; import com.github.sanctum.labyrinth.library.TimeWatch; import com.github.sanctum.labyrinth.library.TypeFlag; -import com.github.sanctum.labyrinth.library.WrittenBook; import com.github.sanctum.labyrinth.permissions.Permissions; import com.github.sanctum.labyrinth.permissions.impl.DefaultImplementation; import com.github.sanctum.labyrinth.permissions.impl.VaultImplementation; @@ -312,11 +305,7 @@ Deployable registerImplementations() { } Deployable registerHandshake() { - return Deployable.of(this, plugin -> { - ExternalDataService.Handshake handshake = new ExternalDataService.Handshake(plugin); - - TaskScheduler.of(handshake::locate).schedule().next(handshake::register).scheduleLater(1); - }); + return Deployable.of(this, plugin -> TaskScheduler.of(ExternalDataService.Handshake.getInstance(plugin)).schedule()); } Deployable registerDefaultPlaceholders() { @@ -380,7 +369,6 @@ public void onDisable() { @Subscribe(priority = Vent.Priority.LOW) public void onJoin(DefaultEvent.Join e) { PlayerSearch.of(e.getPlayer()); - Docket.newInstance(FileList.search(this).get("test").getRoot()).setList(() -> Arrays.asList(DefaultColor.values())).load().toMenu().open(e.getPlayer()); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -553,12 +541,6 @@ public Plugin getPluginInstance() { return this; } - @Override - @NotNull - public com.github.sanctum.labyrinth.library.Message getNewMessage() { - return com.github.sanctum.labyrinth.library.Message.loggedFor(this); - } - @Override public @NotNull Mailer getEmptyMailer() { return Mailer.empty(this); diff --git a/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/AnvilMechhanicsLoader.java b/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/AnvilMechhanicsLoader.java new file mode 100644 index 00000000..e5d77cce --- /dev/null +++ b/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/AnvilMechhanicsLoader.java @@ -0,0 +1,15 @@ +package com.github.sanctum.labyrinth.data.service; + +import com.github.sanctum.labyrinth.LabyrinthProvider; +import com.github.sanctum.labyrinth.data.AbstractClassLoader; +import java.io.File; +import java.io.IOException; + +class AnvilMechhanicsLoader extends AbstractClassLoader { + + static final ClassLoader parent = LabyrinthProvider.getInstance().getPluginInstance().getClass().getClassLoader(); + + AnvilMechhanicsLoader(File file, Object... args) throws IOException { + super(file, parent, args); + } +} diff --git a/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/ExternalDataService.java b/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/ExternalDataService.java index feecfe22..52b2481f 100644 --- a/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/ExternalDataService.java +++ b/labyrinth-plugin/src/main/java/com/github/sanctum/labyrinth/data/service/ExternalDataService.java @@ -1,13 +1,20 @@ package com.github.sanctum.labyrinth.data.service; +import com.github.sanctum.labyrinth.LabyrinthProvider; +import com.github.sanctum.labyrinth.annotation.Ordinal; import com.github.sanctum.labyrinth.api.LabyrinthAPI; +import com.github.sanctum.labyrinth.api.TaskService; import com.github.sanctum.labyrinth.data.FileList; import com.github.sanctum.labyrinth.data.Registry; +import com.github.sanctum.labyrinth.task.Task; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.util.List; import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; import org.bukkit.plugin.ServicePriority; +import org.jetbrains.annotations.NotNull; /** * Used solely to load {@link AnvilMechanics} for use with {@link com.github.sanctum.labyrinth.gui.unity.construct.Menu} on RUNTIME. @@ -28,31 +35,33 @@ protected void setValid() { this.valid = true; } - public static class Handshake { + public static class Handshake extends Task { + private static final long serialVersionUID = -6080924258181953124L; + static Handshake handshake; private final LabyrinthAPI instance; - private final String version; - private boolean located; - public Handshake(LabyrinthAPI instance) { + Handshake(LabyrinthAPI instance) { + super("Labyrinth-Handshake", TaskService.SYNCHRONOUS); this.instance = instance; this.version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].substring(1); } - public String getVersion() { - return version; - } - - public boolean isLocated() { - return located; - } - - public boolean locate() { + @Ordinal + private void initialize() { if (!located) { + // create a stream containing the version jar. InputStream stream = instance.getPluginInstance().getResource(version + ".jar"); + if (stream == null) { + instance.getLogger().severe("==================================================================="); + instance.getLogger().severe("- Version service " + version + " not supported. Consult labyrinth developers."); + instance.getLogger().severe("==================================================================="); + return; + } + File file = new File("plugins/Labyrinth/Service/" + version + ".jar"); if (!file.getParentFile().exists()) { @@ -68,63 +77,58 @@ public boolean locate() { } } - if (stream == null) { - instance.getLogger().severe("==================================================================="); - instance.getLogger().severe("- Version service " + version + " not found. Consult labyrinth developers."); - instance.getLogger().severe("==================================================================="); - return false; - } - if (!file.exists()) { this.located = true; + // write the jar file to the service's directory. FileList.copy(stream, file); instance.getLogger().info("==================================================================="); instance.getLogger().info("- Compiling version " + version + "."); instance.getLogger().info("==================================================================="); - } - return true; - } else { - return false; - } - } - - public boolean register() { - - List services = new Registry.Loader<>(ExternalDataService.class).from("Service").source(instance.getPluginInstance()).confine(key -> { - - AnvilMechanics mechanics = key.getMechanics(); - if (mechanics != null) { - - if (!key.getServerVersion().contains(version)) { + try { + AnvilMechhanicsLoader loader = new AnvilMechhanicsLoader(file); + ExternalDataService service = loader.getMainClass(); + AnvilMechanics mechanics = service.getMechanics(); + if (mechanics != null) { + if (!service.getServerVersion().contains(version)) { + instance.getLogger().severe("==================================================================="); + instance.getLogger().severe("- Version service " + service.getServerVersion() + " invalid for " + version); + instance.getLogger().severe("==================================================================="); + return; + } + + Bukkit.getServicesManager().register(AnvilMechanics.class, mechanics, instance.getPluginInstance(), ServicePriority.High); + + instance.getLogger().info("==================================================================="); + instance.getLogger().info("- Version service " + service.getClass().getSimpleName() + " selected as primary anvil mechanics."); + instance.getLogger().info("==================================================================="); + + service.setValid(); + } else { + instance.getLogger().warning("==================================================================="); + instance.getLogger().warning("- Version service " + service.getClass().getSimpleName() + " has invalid anvil mechanics..."); + instance.getLogger().warning("==================================================================="); + } + } catch (IOException e) { instance.getLogger().severe("==================================================================="); - instance.getLogger().severe("- Version service " + key.getServerVersion() + " invalid for " + version); + instance.getLogger().severe("- Unable to resolve version service " + version + ", contact labyrinth developers."); instance.getLogger().severe("==================================================================="); - return; } - Bukkit.getServicesManager().register(AnvilMechanics.class, mechanics, instance.getPluginInstance(), ServicePriority.High); - - instance.getLogger().info("==================================================================="); - instance.getLogger().info("- Version service " + key.getClass().getSimpleName() + " selected as primary anvil gui instructor."); - instance.getLogger().info("==================================================================="); - - key.setValid(); - - } else { - instance.getLogger().warning("==================================================================="); - instance.getLogger().warning("- Version service " + key.getClass().getSimpleName() + " has an invalid mechanical override skipping..."); - instance.getLogger().warning("==================================================================="); } - - }).getData(); - - if (services.size() == 1 && services.get(0).isValid()) { - this.located = true; - return true; } + } + + @Override + public String toString() { + return "Handshake{" + + "version='" + version + '\'' + + ", located=" + located + + '}'; + } - return false; + public static Handshake getInstance(@NotNull LabyrinthAPI api) { + return handshake != null ? handshake : (handshake = new Handshake(api)); } }