Added mod file tree, bundle loading

This commit is contained in:
Anuken
2019-09-28 21:13:44 -04:00
parent b3666ed2a8
commit 4f9ed73a59
5 changed files with 95 additions and 17 deletions
+2
View File
@@ -130,6 +130,7 @@ public class Vars implements Loadable{
/** list of all locales that can be switched to */ /** list of all locales that can be switched to */
public static Locale[] locales; public static Locale[] locales;
public static FileTree filet;
public static Net net; public static Net net;
public static ContentLoader content; public static ContentLoader content;
public static GameState state; public static GameState state;
@@ -193,6 +194,7 @@ public class Vars implements Loadable{
Version.init(); Version.init();
filet = new FileTree();
mods = new Mods(); mods = new Mods();
content = new ContentLoader(); content = new ContentLoader();
loops = new LoopControl(); loops = new LoopControl();
@@ -0,0 +1,59 @@
package io.anuke.mindustry.core;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.files.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.io.*;
import io.anuke.mindustry.mod.Mods.*;
/** Handles files in a modded context. */
public class FileTree{
private ObjectMap<String, FileHandle> files = new ObjectMap<>();
private ObjectMap<String, Array<FileHandle>> bundles = new ObjectMap<>();
public void buildFiles(Array<LoadedMod> mods){
//TODO many files should not be replaced
for(LoadedMod mod : mods){
mod.root.walk(f -> {
//TODO calling child/parent on these files will give you gibberish; create wrapper class.
files.put(f.path(), f);
});
//load up bundles.
FileHandle folder = mod.root.child("bundles");
if(folder.exists()){
for(FileHandle file : folder.list()){
if(file.name().startsWith("bundle") && file.extension().equals("properties")){
String name = file.nameWithoutExtension();
bundles.getOr(name, Array::new).add(file);
}
}
}
}
//add new keys to each bundle
I18NBundle bundle = Core.bundle;
while(bundle != null){
String str = bundle.getLocale().toString();
String locale = "bundle" + (str.isEmpty() ? "" : "_" + str);
for(FileHandle file : bundles.getOr(locale, Array::new)){
try{
PropertiesUtils.load(bundle.getProperties(), file.reader());
}catch(Exception e){
throw new RuntimeException("Error loading bundle: " + file + "/" + locale, e);
}
}
bundle = bundle.getParent();
}
}
/** Gets an asset file.*/
public FileHandle get(String path){
if(files.containsKey(path)){
return files.get(path);
}else{
return Core.files.internal(path);
}
}
}
+32 -15
View File
@@ -23,15 +23,15 @@ public class Mods{
return modDirectory.child(load.name).child("config.json"); return modDirectory.child(load.name).child("config.json");
} }
/** @return the loaded plugin found by class, or null if not found. */ /** @return the loaded mod found by class, or null if not found. */
public @Nullable LoadedMod getMod(Class<? extends Mod> type){ public @Nullable LoadedMod getMod(Class<? extends Mod> type){
return loaded.find(l -> l.mod.getClass() == type); return loaded.find(l -> l.mod.getClass() == type);
} }
/** Loads all plugins from the folder, but does call any methods on them.*/ /** Loads all mods from the folder, but does call any methods on them.*/
public void load(){ public void load(){
for(FileHandle file : modDirectory.list()){ for(FileHandle file : modDirectory.list()){
if(!file.extension().equals("jar") || !file.extension().equals("zi[")) continue; if(!file.extension().equals("jar") || !file.extension().equals("zip")) continue;
try{ try{
loaded.add(loadmod(file)); loaded.add(loadmod(file));
@@ -41,16 +41,18 @@ public class Mods{
e.printStackTrace(); e.printStackTrace();
} }
} }
filet.buildFiles(loaded);
} }
/** @return all loaded plugins. */ /** @return all loaded mods. */
public Array<LoadedMod> all(){ public Array<LoadedMod> all(){
return loaded; return loaded;
} }
/** Iterates through each plugin.*/ /** Iterates through each mod with a main class.*/
public void each(Consumer<Mod> cons){ public void each(Consumer<Mod> cons){
loaded.each(p -> cons.accept(p.mod)); loaded.each(p -> p.mod != null, p -> cons.accept(p.mod));
} }
private LoadedMod loadmod(FileHandle jar) throws Exception{ private LoadedMod loadmod(FileHandle jar) throws Exception{
@@ -63,23 +65,37 @@ public class Mods{
} }
ModMeta meta = JsonIO.read(ModMeta.class, metaf.readString()); ModMeta meta = JsonIO.read(ModMeta.class, metaf.readString());
String camelized = meta.name.replace(" ", "");
String mainClass = meta.main == null ? camelized.toLowerCase() + "." + camelized + "Mod" : meta.main;
Mod mainMod;
URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, ClassLoader.getSystemClassLoader()); //make sure the main class exists before loading it; if it doesn't just don't put it there
Class<?> main = classLoader.loadClass(meta.main); if(zip.child(mainClass.replace('.', '/') + ".class").exists()){
metas.put(main, meta); URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
return new LoadedMod(jar, zip, (Mod)main.getDeclaredConstructor().newInstance(), meta); Class<?> main = classLoader.loadClass(mainClass);
metas.put(main, meta);
mainMod = (Mod)main.getDeclaredConstructor().newInstance();
}else{
mainMod = null;
}
return new LoadedMod(jar, zip, mainMod, meta);
} }
/** Represents a plugin that has been loaded from a jar file.*/ /** Represents a plugin that has been loaded from a jar file.*/
public static class LoadedMod{ public static class LoadedMod{
public final FileHandle jarFile; /** The location of this mod's zip file on the disk. */
public final FileHandle zipRoot; public final FileHandle file;
/** The root zip file; points to the contents of this mod. */
public final FileHandle root;
/** The mod's main class; may be null. */
public final @Nullable Mod mod; public final @Nullable Mod mod;
/** This mod's metadata. */
public final ModMeta meta; public final ModMeta meta;
public LoadedMod(FileHandle jarFile, FileHandle zipRoot, Mod mod, ModMeta meta){ public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){
this.zipRoot = zipRoot; this.root = root;
this.jarFile = jarFile; this.file = file;
this.mod = mod; this.mod = mod;
this.meta = meta; this.meta = meta;
} }
@@ -88,5 +104,6 @@ public class Mods{
/** Plugin metadata information.*/ /** Plugin metadata information.*/
public static class ModMeta{ public static class ModMeta{
public String name, author, description, version, main; public String name, author, description, version, main;
public String[] dependencies = {}; //TODO implement
} }
} }
+1 -1
View File
@@ -1,3 +1,3 @@
org.gradle.daemon=true org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=5bf89742e927d1951c58cc2743814874c1c9ad25 archash=9f30453676bf2b582c01a46a60965305321dcb9d
@@ -332,7 +332,7 @@ public class ServerControl implements ApplicationListener{
info("Name: &ly{0}", mod.meta.name); info("Name: &ly{0}", mod.meta.name);
info("Version: &ly{0}", mod.meta.version); info("Version: &ly{0}", mod.meta.version);
info("Author: &ly{0}", mod.meta.author); info("Author: &ly{0}", mod.meta.author);
info("Path: &ly{0}", mod.jarFile.path()); info("Path: &ly{0}", mod.file.path());
info("Description: &ly{0}", mod.meta.description); info("Description: &ly{0}", mod.meta.description);
}else{ }else{
info("No mod with name &ly'{0}'&lg found."); info("No mod with name &ly'{0}'&lg found.");