diff --git a/core/src/io/anuke/mindustry/core/Platform.java b/core/src/io/anuke/mindustry/core/Platform.java index d7aa0ea55d..a7c5826a63 100644 --- a/core/src/io/anuke/mindustry/core/Platform.java +++ b/core/src/io/anuke/mindustry/core/Platform.java @@ -31,6 +31,11 @@ public interface Platform{ return Array.with(); } + /** Steam: Return external workshop mods to be loaded.*/ + default Array getExternalMods(){ + return Array.with(); + } + /** Steam: View a map listing on the workshop.*/ default void viewMapListing(Map map){} diff --git a/core/src/io/anuke/mindustry/mod/Mods.java b/core/src/io/anuke/mindustry/mod/Mods.java index bfe8df2ce1..97a4e06255 100644 --- a/core/src/io/anuke/mindustry/mod/Mods.java +++ b/core/src/io/anuke/mindustry/mod/Mods.java @@ -61,7 +61,7 @@ public class Mods implements Loadable{ file.copyTo(dest); try{ - loaded.add(loadMod(file)); + loaded.add(loadMod(file, false)); requiresReload = true; }catch(IOException e){ dest.delete(); @@ -163,16 +163,30 @@ public class Mods implements Loadable{ if(!file.extension().equals("jar") && !file.extension().equals("zip") && !(file.isDirectory() && file.child("mod.json").exists())) continue; try{ - LoadedMod mod = loadMod(file); + LoadedMod mod = loadMod(file, false); if(mod.enabled()){ loaded.add(mod); }else{ disabled.add(mod); } - }catch(IllegalArgumentException ignored){ }catch(Exception e){ - Log.err("Failed to load plugin file {0}. Skipping.", file); - e.printStackTrace(); + Log.err("Failed to load mod file {0}. Skipping.", file); + Log.err(e); + } + } + + //load mods now + for(FileHandle file : platform.getExternalMods()){ + try{ + LoadedMod mod = loadMod(file, true); + if(mod.enabled()){ + loaded.add(mod); + }else{ + disabled.add(mod); + } + }catch(Exception e){ + Log.err("Failed to load mod file {0}. Skipping.", file); + Log.err(e); } } @@ -329,7 +343,7 @@ public class Mods implements Loadable{ /** Loads a mod file+meta, but does not add it to the list. * Note that directories can be loaded as mods.*/ - private LoadedMod loadMod(FileHandle sourceFile) throws Exception{ + private LoadedMod loadMod(FileHandle sourceFile, boolean workshop) throws Exception{ FileHandle zip = sourceFile.isDirectory() ? sourceFile : new ZipFileHandle(sourceFile); if(zip.list().length == 1 && zip.list()[0].isDirectory()){ zip = zip.list()[0]; @@ -395,6 +409,8 @@ public class Mods implements Loadable{ public final String name; /** This mod's metadata. */ public final ModMeta meta; + /** The ID of this mod in the workshop.*/ + public @Nullable String workshopID; public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){ this.root = root; diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 2aceda244f..0950aaf6bb 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -210,6 +210,11 @@ public class DesktopLauncher extends ClientLauncher{ return !steam ? super.getExternalMaps() : SVars.workshop.getMapFiles(); } + @Override + public Array getExternalMods(){ + return !steam ? super.getExternalMods() : SVars.workshop.getModFiles(); + } + @Override public void viewMapListing(Map map){ viewMapListing(map.file.parent().name()); diff --git a/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java b/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java index 578b00de3c..9939ae795c 100644 --- a/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java +++ b/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java @@ -22,29 +22,39 @@ public class SWorkshop implements SteamUGCCallback{ private Map lastMap; private Array mapFiles; - private ObjectMap> detailHandlers = new ObjectMap<>(); + private Array modFiles; + private ObjectMap, SteamResult>> detailHandlers = new ObjectMap<>(); public SWorkshop(){ int items = ugc.getNumSubscribedItems(); SteamPublishedFileID[] ids = new SteamPublishedFileID[items]; ItemInstallInfo info = new ItemInstallInfo(); ugc.getSubscribedItems(ids); - mapFiles = Array.with(ids).map(f -> { + + Array folders = Array.with(ids).map(f -> { ugc.getItemInstallInfo(f, info); return new FileHandle(info.getFolder()); - }).select(f -> f.list().length > 0).map(f -> f.list()[0]); + }).select(f -> f != null && f.list().length > 0); - if(items > 0){ + mapFiles = folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0]); + modFiles = folders.select(f -> f.child("mod.json").exists()); + + if(!mapFiles.isEmpty()){ SAchievement.downloadMapWorkshop.complete(); } - Log.info("Fetching {0} subscribed maps.", items); + Log.info("Fetching {0} subscribed maps.", mapFiles.size); + Log.info("Fetching {0} subscribed mods.", modFiles.size); } public Array getMapFiles(){ return mapFiles; } + public Array getModFiles(){ + return modFiles; + } + public void publishMap(Map map){ if(map.tags.containsKey("steamid")){ Log.info("Map already published, redirecting to ID."); @@ -86,12 +96,13 @@ public class SWorkshop implements SteamUGCCallback{ SteamUGCQuery query = ugc.createQueryUGCDetailsRequest(fid); Log.info("POST " + query); - detailHandlers.put(query, (details, result) -> { + detailHandlers.put(query, (detailsList, result) -> { ui.loadfrag.hide(); - Log.info("Map listing result: " + result + " " + details.getResult() + " " + details.getFileName() + " " + details.getTitle()); + Log.info("Map listing result: " + result + " " + detailsList); if(result == SteamResult.OK){ + SteamUGCDetails details = detailsList.first(); if(details.getResult() == SteamResult.OK){ if(details.getOwnerID().equals(SVars.user.user.getSteamID())){ @@ -160,11 +171,14 @@ public class SWorkshop implements SteamUGCCallback{ if(detailHandlers.containsKey(query)){ if(numResultsReturned > 0){ - SteamUGCDetails details = new SteamUGCDetails(); - ugc.getQueryUGCResult(query, 0, details); + Array details = new Array<>(); + for(int i = 0; i < numResultsReturned; i++){ + details.set(i, new SteamUGCDetails()); + ugc.getQueryUGCResult(query, i, details.get(i)); + } detailHandlers.get(query).accept(details, result); }else{ - detailHandlers.get(query).accept(null, SteamResult.FileNotFound); + detailHandlers.get(query).accept(new Array<>(), SteamResult.FileNotFound); } detailHandlers.remove(query);