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

View File

@ -130,6 +130,7 @@ public class Vars implements Loadable{
/** list of all locales that can be switched to */
public static Locale[] locales;
public static FileTree filet;
public static Net net;
public static ContentLoader content;
public static GameState state;
@ -193,6 +194,7 @@ public class Vars implements Loadable{
Version.init();
filet = new FileTree();
mods = new Mods();
content = new ContentLoader();
loops = new LoopControl();

View File

@ -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);
}
}
}

View File

@ -23,15 +23,15 @@ public class Mods{
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){
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(){
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{
loaded.add(loadmod(file));
@ -41,16 +41,18 @@ public class Mods{
e.printStackTrace();
}
}
filet.buildFiles(loaded);
}
/** @return all loaded plugins. */
/** @return all loaded mods. */
public Array<LoadedMod> all(){
return loaded;
}
/** Iterates through each plugin.*/
/** Iterates through each mod with a main class.*/
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{
@ -63,23 +65,37 @@ public class Mods{
}
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());
Class<?> main = classLoader.loadClass(meta.main);
metas.put(main, meta);
return new LoadedMod(jar, zip, (Mod)main.getDeclaredConstructor().newInstance(), meta);
//make sure the main class exists before loading it; if it doesn't just don't put it there
if(zip.child(mainClass.replace('.', '/') + ".class").exists()){
URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
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.*/
public static class LoadedMod{
public final FileHandle jarFile;
public final FileHandle zipRoot;
/** The location of this mod's zip file on the disk. */
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;
/** This mod's metadata. */
public final ModMeta meta;
public LoadedMod(FileHandle jarFile, FileHandle zipRoot, Mod mod, ModMeta meta){
this.zipRoot = zipRoot;
this.jarFile = jarFile;
public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){
this.root = root;
this.file = file;
this.mod = mod;
this.meta = meta;
}
@ -88,5 +104,6 @@ public class Mods{
/** Plugin metadata information.*/
public static class ModMeta{
public String name, author, description, version, main;
public String[] dependencies = {}; //TODO implement
}
}

View File

@ -1,3 +1,3 @@
org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=5bf89742e927d1951c58cc2743814874c1c9ad25
archash=9f30453676bf2b582c01a46a60965305321dcb9d

View File

@ -332,7 +332,7 @@ public class ServerControl implements ApplicationListener{
info("Name: &ly{0}", mod.meta.name);
info("Version: &ly{0}", mod.meta.version);
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);
}else{
info("No mod with name &ly'{0}'&lg found.");