1
0
mirror of https://github.com/Anuken/Mindustry.git synced 2024-09-21 05:17:50 +03:00

Added mod dependencies

This commit is contained in:
Anuken 2019-10-27 18:07:18 -04:00
parent ef2817513a
commit 9e4e58baf9
3 changed files with 73 additions and 8 deletions

View File

@ -94,6 +94,8 @@ mods.report = Report Bug
mod.enabled = [lightgray]Enabled
mod.disabled = [scarlet]Disabled
mod.disable = Disable
mod.missingdependencies = [scarlet]Missing dependencies: {0}
mod.nowdisabled = [scarlet]Mod '{0}' is missing dependencies:[accent] {1}\n[lightgray]These mods need to be downloaded first.\nThis mod will be automatically disabled.
mod.enable = Enable
mod.requiresrestart = The game will now close to apply the mod changes.
mod.reloadrequired = [scarlet]Reload Required

View File

@ -200,14 +200,61 @@ public class Mods implements Loadable{
}
}
resolveDependencies();
//sort mods to make sure servers handle them properly.
loaded.sort(Structs.comparing(m -> m.name));
buildFiles();
}
private void buildFiles(){
private void resolveDependencies(){
for(LoadedMod mod : Array.<LoadedMod>withArrays(loaded, disabled)){
updateDependencies(mod);
}
disabled.addAll(loaded.select(LoadedMod::hasUnmetDependencies));
loaded.removeAll(LoadedMod::hasUnmetDependencies);
disabled.each(mod -> setEnabled(mod, false));
disabled.distinct();
loaded.distinct();
}
private void updateDependencies(LoadedMod mod){
mod.dependencies.clear();
mod.missingDependencies.clear();
mod.dependencies = mod.meta.dependencies.map(this::locateMod);
for(int i = 0; i < mod.dependencies.size; i++){
if(mod.dependencies.get(i) == null){
mod.missingDependencies.add(mod.meta.dependencies.get(i));
}
}
}
private void topoSort(LoadedMod mod, Array<LoadedMod> stack, ObjectSet<LoadedMod> visited){
visited.add(mod);
mod.dependencies.each(m -> !visited.contains(m), m -> topoSort(m, stack, visited));
stack.add(mod);
}
/** @return mods ordered in the correct way needed for dependencies. */
private Array<LoadedMod> orderedMods(){
ObjectSet<LoadedMod> visited = new ObjectSet<>();
Array<LoadedMod> result = new Array<>();
for(LoadedMod mod : loaded){
if(!visited.contains(mod)){
topoSort(mod, result, visited);
}
}
return result;
}
private LoadedMod locateMod(String name){
return loaded.find(mod -> mod.name.equals(name));
}
private void buildFiles(){
for(LoadedMod mod : orderedMods()){
boolean zipFolder = !mod.file.isDirectory() && mod.root.parent() != null;
String parentName = zipFolder ? mod.root.name() : null;
for(FileHandle file : mod.root.list()){
@ -256,7 +303,6 @@ public class Mods implements Loadable{
loaded.clear();
disabled.clear();
load();
buildFiles();
Sounds.dispose();
Sounds.load();
Core.assets.finishLoading();
@ -275,8 +321,7 @@ public class Mods implements Loadable{
/** Creates all the content found in mod files. */
public void loadContent(){
for(LoadedMod mod : loaded){
for(LoadedMod mod : orderedMods()){
safeRun(mod, () -> {
if(mod.root.child("content").exists()){
FileHandle contentRoot = mod.root.child("content");
@ -336,11 +381,13 @@ public class Mods implements Loadable{
requiresReload = true;
if(!enabled){
loaded.remove(mod);
disabled.add(mod);
if(!disabled.contains(mod)) disabled.add(mod);
}else{
loaded.add(mod);
if(!loaded.contains(mod)) loaded.add(mod);
disabled.remove(mod);
}
loaded.each(this::updateDependencies);
disabled.each(this::updateDependencies);
}
}
@ -465,6 +512,10 @@ public class Mods implements Loadable{
public final String name;
/** This mod's metadata. */
public final ModMeta meta;
/** This mod's dependencies as already-loaded mods. */
public Array<LoadedMod> dependencies = new Array<>();
/** All missing dependencies of this mod as strings. */
public Array<String> missingDependencies = new Array<>();
public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){
this.root = root;
@ -478,6 +529,10 @@ public class Mods implements Loadable{
return Core.settings.getBool("mod-" + name + "-enabled", true);
}
public boolean hasUnmetDependencies(){
return !missingDependencies.isEmpty();
}
@Override
public String getSteamID(){
return Core.settings.getString(name + "-steamid", null);
@ -548,7 +603,7 @@ public class Mods implements Loadable{
/** Plugin metadata information.*/
public static class ModMeta{
public String name, author, description, version, main;
public String[] dependencies = {}; //TODO implement
public Array<String> dependencies = Array.with();
/** Hidden mods are only server-side or client-side, and do not support adding new content. */
public boolean hidden;
}

View File

@ -70,6 +70,11 @@ public class ModsDialog extends FloatingDialog{
hidden(() -> {
if(mods.requiresReload()){
ui.loadAnd("$reloading", () -> {
mods.all().each(mod -> {
if(mod.hasUnmetDependencies()){
ui.showErrorMessage(Core.bundle.format("mod.nowdisabled", mod.name, mod.missingDependencies.toString(", ")));
}
});
mods.reloadContent();
});
}
@ -141,7 +146,10 @@ public class ModsDialog extends FloatingDialog{
t.labelWrap("[lightgray]" + mod.meta.description).growX();
t.row();
}
if(mod.hasUnmetDependencies()){
t.labelWrap(Core.bundle.format("mod.missingdependencies", mod.missingDependencies.toString(", "))).growX();
t.row();
}
}).width(500f);
table.row();
}