Skip to content

Commit

Permalink
* Completely removed old task scheduling utility for newly optimized …
Browse files Browse the repository at this point in the history
…alternative.

* Optimized task execution handling.
* Added new isModded check to LegacyCheckService
* Added new toBlockFace method to DirectivePoint
* Optimized internal Unity task executions.
* Finalized OrdinalProcedure service.
* Completely removed old PaginatedList.java utility.
* Finalized sub-command injection handling.
* Optimized and fixed remaining issues with Message.java abstraction in tandem with ComponentUtil.
* Optimized labyrinth provided placeholder system.
* Added version support for 1.18+ (1.19 & future versions)
* Added new AbstractClassLoader for alternative class loading from external jars than AddonLoader
* Added class unloading to AddonLoader
* Added new multi-object isNull checking method to Check.java
* Finalized SubCommandList.java and made its internal referencing to depend on localization.
* Added new docket interfacing to unity gui library. Purposed to create ultimate fluidity in menu creation through configuration.
* Added new FormattedString.java class to help act as more of a modular StringUtils utility class.
* Added json string to json object conversion method to JsonIntermediate.java
* Optimized unity menu interaction, fixed resulting item inventory duplication bug in modded environments.
* Fixed TablistInstance.java player list name default.
* Fixed reflection problems 1.18+ with Task.java
* Added simple UnknownGeneric.java interface.
* Fixed WebResponse.java
* Optimized key and value listing for all Node.java related services.
* Enabled atlas map types to allow for custom '.' node separation placeholders.
* Removed deprecated Message.java class.
* Removed deprecated methods from Item.java class.
* Added new MapDecompressionUtils service.
* Finalized Registry.java
* Finalized ExternalDataService.java and switched to new AbstractClassLoader.
  • Loading branch information
Hempfest committed Jun 22, 2022
1 parent a96c666 commit eaf8d47
Show file tree
Hide file tree
Showing 30 changed files with 911 additions and 895 deletions.
Expand Up @@ -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!
*
Expand All @@ -59,7 +48,7 @@ default <T> Deployable<Object> sendPluginMessage(Plugin plugin, T object) {
}

default <T> Deployable<Object> sendPluginMessage(Plugin plugin, T object, @FieldsFrom(LabyrinthPluginChannel.class) LabyrinthPluginChannel<?> channel) {
return Deployable.of(null, unused -> unused = new Vent.Call<>(new LabyrinthPluginMessageEvent(new LabyrinthPluginMessage<T>() {
return Deployable.of(() -> new Vent.Call<>(new LabyrinthPluginMessageEvent(new LabyrinthPluginMessage<T>() {
@Override
public Plugin getPlugin() {
return plugin;
Expand Down
@@ -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;
Expand All @@ -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 <T> The optional main class this loader needs to locate and instantiate.
*/
public abstract class AbstractClassLoader<T> extends URLClassLoader {

private static final Field PLUGIN_CLASS_MAP;
protected final Field PLUGIN_CLASS_MAP;
protected final List<Class<?>> classes;
protected final ClassLoader pluginClassLoader;
protected final T mainClass;

private final List<Class<?>> 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<T> flag = new EasyTypeAdapter<>();
Class<T> 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<T> main, Object... args) throws IOException {
super(new URL[]{file.toURI().toURL()}, parent);
final List<Class<?>> 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)
Expand All @@ -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);
});
Expand All @@ -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();
}
Expand All @@ -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<Class<?>> 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<String, Class<?>> classes = getPluginClassMap();
if (classes.containsKey(name)) {
classes.remove(name);
return true;
} else throw new ClassNotFoundException("Class " + name + " not found, cannot unload.");
}

public List<Class<?>> 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<String, Class<?>> 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<String, Class<?>> getClassMap() throws IllegalStateException {
public final Map<String, Class<?>> getPluginClassMap() throws IllegalStateException {
try {
//noinspection unchecked
return (Map<String, Class<?>>) PLUGIN_CLASS_MAP.get(plugin.getClass().getClassLoader());
return (Map<String, Class<?>>) PLUGIN_CLASS_MAP.get(this.pluginClassLoader);
} catch (ClassCastException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
Expand All @@ -116,7 +160,7 @@ public Map<String, Class<?>> getClassMap() throws IllegalStateException {
@Override
public String toString() {
return "AbstractFileLoader{" +
"Main=" + (mainClass == null ? "N/A" : mainClass) +
"Main=" + mainClass +
'}';
}

Expand Down
Expand Up @@ -14,4 +14,6 @@ default String getPath() {
return null;
}

char getDivider();

}
Expand Up @@ -14,12 +14,25 @@

public class AtlasMap implements Atlas {

private final Map<String, Object> SOURCE = new HashMap<>();
protected final Map<String, Object> SOURCE = new HashMap<>();
protected final Map<String, MemorySpace> 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<String, Object> o = SOURCE;
for (int i = 0; i < a.length - 1; i++) {
Expand Down Expand Up @@ -49,76 +62,34 @@ public Node getNode(String key) {
@Override
public Set<String> getKeys(boolean deep) {
Set<String> keys = new HashSet<>();
for (Object o : SOURCE.entrySet()) {
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) o;
SOURCE.forEach((key, value) -> {
if (deep) {
if (entry.getValue() instanceof Map) {
Map<String, Object> obj = (Map<String, Object>) entry.getValue();
for (Object ob : obj.entrySet()) {
Map.Entry<String, Object> en = (Map.Entry<String, Object>) ob;
if (en.getValue() instanceof Map) {
Map<String, Object> j = (Map<String, Object>) entry.getValue();
for (Object e : j.entrySet()) {
Map.Entry<String, Object> ent = (Map.Entry<String, Object>) e;
if (ent.getValue() instanceof Map) {
Map<String, Object> ja = (Map<String, Object>) ent.getValue();
for (Object ex : ja.entrySet()) {
Map.Entry<String, Object> entr = (Map.Entry<String, Object>) 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<String, Object>) 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<String, Object> getValues(boolean deep) {
Map<String, Object> map = new HashMap<>();
for (Object o : SOURCE.entrySet()) {
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) o;
SOURCE.forEach((key, value) -> {
if (deep) {
if (entry.getValue() instanceof Map) {
Map<String, Object> obj = (Map<String, Object>) entry.getValue();
for (Object ob : obj.entrySet()) {
Map.Entry<String, Object> en = (Map.Entry<String, Object>) ob;
if (en.getValue() instanceof Map) {
Map<String, Object> j = (Map<String, Object>) entry.getValue();
for (Object e : j.entrySet()) {
Map.Entry<String, Object> ent = (Map.Entry<String, Object>) e;
if (ent.getValue() instanceof Map) {
Map<String, Object> ja = (Map<String, Object>) ent.getValue();
for (Object ex : ja.entrySet()) {
Map.Entry<String, Object> entr = (Map.Entry<String, Object>) 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<String, Object>) 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;
}

Expand All @@ -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<String, Object> o = SOURCE;
for (int i = 0; i < a.length - 1; i++) {
Expand All @@ -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<String, Object> ob = SOURCE;
for (int i = 0; i < a.length - 1; i++) {
Expand Down Expand Up @@ -312,4 +283,9 @@ public Object compute(String key, @NotNull BiFunction<? super String, ? super Ob
public Object merge(String key, @NotNull Object value, @NotNull BiFunction<? super Object, ? super Object, ?> remappingFunction) {
return SOURCE.merge(key, value, remappingFunction);
}

@Override
public char getDivider() {
return divider;
}
}

0 comments on commit eaf8d47

Please sign in to comment.