Workshop mod loading

This commit is contained in:
Anuken
2019-10-04 15:06:29 -04:00
parent f7b6cea21b
commit df3f23731b
4 changed files with 56 additions and 16 deletions

View File

@@ -31,6 +31,11 @@ public interface Platform{
return Array.with(); return Array.with();
} }
/** Steam: Return external workshop mods to be loaded.*/
default Array<FileHandle> getExternalMods(){
return Array.with();
}
/** Steam: View a map listing on the workshop.*/ /** Steam: View a map listing on the workshop.*/
default void viewMapListing(Map map){} default void viewMapListing(Map map){}

View File

@@ -61,7 +61,7 @@ public class Mods implements Loadable{
file.copyTo(dest); file.copyTo(dest);
try{ try{
loaded.add(loadMod(file)); loaded.add(loadMod(file, false));
requiresReload = true; requiresReload = true;
}catch(IOException e){ }catch(IOException e){
dest.delete(); 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; if(!file.extension().equals("jar") && !file.extension().equals("zip") && !(file.isDirectory() && file.child("mod.json").exists())) continue;
try{ try{
LoadedMod mod = loadMod(file); LoadedMod mod = loadMod(file, false);
if(mod.enabled()){ if(mod.enabled()){
loaded.add(mod); loaded.add(mod);
}else{ }else{
disabled.add(mod); disabled.add(mod);
} }
}catch(IllegalArgumentException ignored){
}catch(Exception e){ }catch(Exception e){
Log.err("Failed to load plugin file {0}. Skipping.", file); Log.err("Failed to load mod file {0}. Skipping.", file);
e.printStackTrace(); 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. /** Loads a mod file+meta, but does not add it to the list.
* Note that directories can be loaded as mods.*/ * 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); FileHandle zip = sourceFile.isDirectory() ? sourceFile : new ZipFileHandle(sourceFile);
if(zip.list().length == 1 && zip.list()[0].isDirectory()){ if(zip.list().length == 1 && zip.list()[0].isDirectory()){
zip = zip.list()[0]; zip = zip.list()[0];
@@ -395,6 +409,8 @@ public class Mods implements Loadable{
public final String name; public final String name;
/** This mod's metadata. */ /** This mod's metadata. */
public final ModMeta meta; 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){ public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){
this.root = root; this.root = root;

View File

@@ -210,6 +210,11 @@ public class DesktopLauncher extends ClientLauncher{
return !steam ? super.getExternalMaps() : SVars.workshop.getMapFiles(); return !steam ? super.getExternalMaps() : SVars.workshop.getMapFiles();
} }
@Override
public Array<FileHandle> getExternalMods(){
return !steam ? super.getExternalMods() : SVars.workshop.getModFiles();
}
@Override @Override
public void viewMapListing(Map map){ public void viewMapListing(Map map){
viewMapListing(map.file.parent().name()); viewMapListing(map.file.parent().name());

View File

@@ -22,29 +22,39 @@ public class SWorkshop implements SteamUGCCallback{
private Map lastMap; private Map lastMap;
private Array<FileHandle> mapFiles; private Array<FileHandle> mapFiles;
private ObjectMap<SteamUGCQuery, BiConsumer<SteamUGCDetails, SteamResult>> detailHandlers = new ObjectMap<>(); private Array<FileHandle> modFiles;
private ObjectMap<SteamUGCQuery, BiConsumer<Array<SteamUGCDetails>, SteamResult>> detailHandlers = new ObjectMap<>();
public SWorkshop(){ public SWorkshop(){
int items = ugc.getNumSubscribedItems(); int items = ugc.getNumSubscribedItems();
SteamPublishedFileID[] ids = new SteamPublishedFileID[items]; SteamPublishedFileID[] ids = new SteamPublishedFileID[items];
ItemInstallInfo info = new ItemInstallInfo(); ItemInstallInfo info = new ItemInstallInfo();
ugc.getSubscribedItems(ids); ugc.getSubscribedItems(ids);
mapFiles = Array.with(ids).map(f -> {
Array<FileHandle> folders = Array.with(ids).map(f -> {
ugc.getItemInstallInfo(f, info); ugc.getItemInstallInfo(f, info);
return new FileHandle(info.getFolder()); 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(); 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<FileHandle> getMapFiles(){ public Array<FileHandle> getMapFiles(){
return mapFiles; return mapFiles;
} }
public Array<FileHandle> getModFiles(){
return modFiles;
}
public void publishMap(Map map){ public void publishMap(Map map){
if(map.tags.containsKey("steamid")){ if(map.tags.containsKey("steamid")){
Log.info("Map already published, redirecting to ID."); Log.info("Map already published, redirecting to ID.");
@@ -86,12 +96,13 @@ public class SWorkshop implements SteamUGCCallback{
SteamUGCQuery query = ugc.createQueryUGCDetailsRequest(fid); SteamUGCQuery query = ugc.createQueryUGCDetailsRequest(fid);
Log.info("POST " + query); Log.info("POST " + query);
detailHandlers.put(query, (details, result) -> { detailHandlers.put(query, (detailsList, result) -> {
ui.loadfrag.hide(); 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){ if(result == SteamResult.OK){
SteamUGCDetails details = detailsList.first();
if(details.getResult() == SteamResult.OK){ if(details.getResult() == SteamResult.OK){
if(details.getOwnerID().equals(SVars.user.user.getSteamID())){ if(details.getOwnerID().equals(SVars.user.user.getSteamID())){
@@ -160,11 +171,14 @@ public class SWorkshop implements SteamUGCCallback{
if(detailHandlers.containsKey(query)){ if(detailHandlers.containsKey(query)){
if(numResultsReturned > 0){ if(numResultsReturned > 0){
SteamUGCDetails details = new SteamUGCDetails(); Array<SteamUGCDetails> details = new Array<>();
ugc.getQueryUGCResult(query, 0, details); 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); detailHandlers.get(query).accept(details, result);
}else{ }else{
detailHandlers.get(query).accept(null, SteamResult.FileNotFound); detailHandlers.get(query).accept(new Array<>(), SteamResult.FileNotFound);
} }
detailHandlers.remove(query); detailHandlers.remove(query);