From 2424afa1fbb239fbfb5d61753ffad9aa13add7ca Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 17 Sep 2019 21:55:57 -0400 Subject: [PATCH] Workshop implementation progress --- core/assets/bundles/bundle.properties | 2 +- .../io/anuke/mindustry/ClientLauncher.java | 1 + .../anuke/mindustry/editor/MapLoadDialog.java | 2 +- core/src/io/anuke/mindustry/maps/Map.java | 6 +++ core/src/io/anuke/mindustry/maps/Maps.java | 52 ++++++++++--------- .../io/anuke/mindustry/net/CrashSender.java | 4 +- .../ui/dialogs/CustomGameDialog.java | 4 +- .../mindustry/ui/dialogs/MapPlayDialog.java | 2 +- .../mindustry/ui/dialogs/MapsDialog.java | 6 +-- .../mindustry/desktop/DesktopLauncher.java | 23 +++++++- .../mindustry/desktop/steam/SWorkshop.java | 17 ++++-- 11 files changed, 78 insertions(+), 41 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 5a92f0002f..5345273c4e 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -202,7 +202,7 @@ wave.enemy = [lightgray]{0} Enemy Remaining loadimage = Load Image saveimage = Save Image unknown = Unknown -custom = Custom +custom = Custom builtin = Built-In map.delete.confirm = Are you sure you want to delete this map? This action cannot be undone! map.random = [accent]Random Map diff --git a/core/src/io/anuke/mindustry/ClientLauncher.java b/core/src/io/anuke/mindustry/ClientLauncher.java index e63fc9ac01..fe15d49d88 100644 --- a/core/src/io/anuke/mindustry/ClientLauncher.java +++ b/core/src/io/anuke/mindustry/ClientLauncher.java @@ -40,6 +40,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform batch = new SpriteBatch(); assets = new AssetManager(); assets.setLoader(Texture.class, "." + mapExtension, new MapPreviewLoader()); + assets.load("sprites/error.png", Texture.class); atlas = TextureAtlas.blankAtlas(); Vars.net = new Net(platform.getNet()); diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java index 6cfaaeca7a..c0567a724c 100644 --- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java @@ -54,7 +54,7 @@ public class MapLoadDialog extends FloatingDialog{ for(Map map : maps.all()){ TextButton button = new TextButton(map.name(), Styles.togglet); - button.add(new BorderImage(map.texture, 2f).setScaling(Scaling.fit)).size(16 * 4f); + button.add(new BorderImage(map.safeTexture(), 2f).setScaling(Scaling.fit)).size(16 * 4f); button.getCells().reverse(); button.clicked(() -> selected = map); button.getLabelCell().grow().left().padLeft(5f); diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index 92789727dc..df0a2d711f 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -20,6 +20,8 @@ public class Map implements Comparable{ public final FileHandle file; /** Format version. */ public final int version; + /** Whether this map is managed, e.g. downloaded from the Steam workshop.*/ + public boolean workshop; /** Map width/height, shorts. */ public int width, height; /** Preview texture. */ @@ -57,6 +59,10 @@ public class Map implements Comparable{ return Core.settings.getInt("hiscore" + file.nameWithoutExtension(), 0); } + public Texture safeTexture(){ + return texture == null ? Core.assets.get("sprites/error.png") : texture; + } + public FileHandle previewFile(){ return Vars.mapPreviewDirectory.child(file.nameWithoutExtension() + ".png"); } diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 7336e63114..dd45cc9e6f 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -81,6 +81,7 @@ public class Maps{ /** Load all maps. Should be called at application start. */ public void load(){ + //defaults; must work try{ for(String name : defaultMapNames){ FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension); @@ -90,7 +91,27 @@ public class Maps{ throw new RuntimeException(e); } - loadCustomMaps(); + //custom + for(FileHandle file : customMapDirectory.list()){ + try{ + if(file.extension().equalsIgnoreCase(mapExtension)){ + loadMap(file, true); + } + }catch(Exception e){ + Log.err("Failed to load custom map file '{0}'!", file); + Log.err(e); + } + } + + //workshop + for(FileHandle file : platform.getExternalMaps()){ + try{ + loadMap(file, false).workshop = true; + }catch(Exception e){ + Log.err("Failed to load workshop map file '{0}'!", file); + Log.err(e); + } + } } public void reload(){ @@ -174,14 +195,6 @@ public class Maps{ } } - /** Creates a legacy map by converting it to a non-legacy map and pasting it in a temp directory. - * Should be followed up by {@link #importMap(FileHandle)} .*/ - public Map makeLegacyMap(FileHandle file) throws IOException{ - FileHandle dst = tmpDirectory.child("conversion_map." + mapExtension); - LegacyMapIO.convertMap(file, dst); - return MapIO.createMap(dst, true); - } - /** Import a map, then save it. This updates all values and stored data necessary. */ public void importMap(FileHandle file) throws IOException{ FileHandle dest = findFile(); @@ -203,7 +216,6 @@ public class Maps{ if(error[0] != null){ throw new IOException(error[0]); } - } /** Attempts to run the following code; @@ -312,9 +324,11 @@ public class Maps{ public void loadPreviews(){ for(Map map : maps){ + Log.info("Generating preview for {0}", map.name()); //try to load preview if(map.previewFile().exists()){ - //this may fail, but calls createNewPreview + Log.info("> exists"); + //this may fail, but calls queueNewPreview Core.assets.load(new AssetDescriptor<>(map.previewFile().path() + "." + mapExtension, Texture.class, new MapPreviewParameter(map))).loaded = t -> map.texture = (Texture)t; try{ @@ -324,6 +338,7 @@ public class Maps{ queueNewPreview(map); } }else{ + Log.info("> doesn't exist, queuing"); queueNewPreview(map); } } @@ -332,7 +347,8 @@ public class Maps{ private void createAllPreviews(){ Core.app.post(() -> { for(Map map : previewList){ - createNewPreview(map, e -> Core.app.post(() -> map.texture = new Texture("sprites/error.png"))); + Log.info("> > GEN NEW preview for {0}", map.name()); + createNewPreview(map, e -> Core.app.post(() -> map.texture = Core.assets.get("sprites/error.png"))); } previewList.clear(); }); @@ -407,16 +423,4 @@ public class Maps{ return map; } - private void loadCustomMaps(){ - for(FileHandle file : customMapDirectory.list()){ - try{ - if(file.extension().equalsIgnoreCase(mapExtension)){ - loadMap(file, true); - } - }catch(Exception e){ - Log.err("Failed to load custom map file '{0}'!", file); - Log.err(e); - } - } - } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/net/CrashSender.java b/core/src/io/anuke/mindustry/net/CrashSender.java index 6970e9521b..cc29071615 100644 --- a/core/src/io/anuke/mindustry/net/CrashSender.java +++ b/core/src/io/anuke/mindustry/net/CrashSender.java @@ -25,8 +25,8 @@ public class CrashSender{ try{ exception.printStackTrace(); - //don't create crash logs for me (anuke) or custom builds, as it's expected - if(System.getProperty("user.name").equals("anuke") || Version.build == -1) return; + //don't create crash logs for custom builds, as it's expected + if(Version.build == -1) return; //attempt to load version regardless if(Version.number == 0){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index efbdfa65df..74eb693fec 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -48,7 +48,7 @@ public class CustomGameDialog extends FloatingDialog{ maps.row(); } - ImageButton image = new ImageButton(new TextureRegion(map.texture), Styles.cleari); + ImageButton image = new ImageButton(new TextureRegion(map.safeTexture()), Styles.cleari); image.margin(5); image.top(); @@ -72,7 +72,7 @@ public class CustomGameDialog extends FloatingDialog{ image.add(img).size(images); - BorderImage border = new BorderImage(map.texture, 3f); + BorderImage border = new BorderImage(map.safeTexture(), 3f); border.setScaling(Scaling.fit); image.replaceImage(border); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java index c55b4f6fb8..b3da2b2f3f 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java @@ -69,7 +69,7 @@ public class MapPlayDialog extends FloatingDialog{ cont.row(); cont.addImageTextButton("$customize", Icon.toolsSmall, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230); cont.row(); - cont.add(new BorderImage(map.texture, 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit); + cont.add(new BorderImage(map.safeTexture(), 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit); //only maps with survival are valid for high scores if(Gamemode.survival.valid(map)){ cont.row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index e58af17752..66de040bb2 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -143,9 +143,9 @@ public class MapsDialog extends FloatingDialog{ button.row(); button.addImage().growX().pad(4).color(Pal.gray); button.row(); - button.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize - 20f); + button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f); button.row(); - button.add(map.custom ? "$custom" : "$builtin").color(Color.gray).padTop(3); + button.add(map.custom ? "$custom" : map.workshop ? "$workshop" : "$builtin").color(Color.gray).padTop(3); i++; } @@ -166,7 +166,7 @@ public class MapsDialog extends FloatingDialog{ float mapsize = Core.graphics.isPortrait() ? 160f : 300f; Table table = dialog.cont; - table.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize); + table.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize); table.table(Styles.black, desc -> { desc.top(); diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 59b665b31b..d4cb2582c2 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -7,6 +7,7 @@ import io.anuke.arc.Files.*; import io.anuke.arc.backends.sdl.*; import io.anuke.arc.backends.sdl.jni.*; import io.anuke.arc.collection.*; +import io.anuke.arc.files.*; import io.anuke.arc.function.*; import io.anuke.arc.input.*; import io.anuke.arc.math.*; @@ -48,11 +49,12 @@ public class DesktopLauncher extends ClientLauncher{ setWindowIcon(FileType.Internal, "icons/icon_64.png"); }}); }catch(Throwable e){ - DesktopLauncher.handleCrash(e); + handleCrash(e); } } public DesktopLauncher(String[] args){ + Log.setUseColors(false); Version.init(); boolean useSteam = Version.modifier.equals("steam"); testMobile = Array.with(args).contains("-testMobile"); @@ -72,6 +74,16 @@ public class DesktopLauncher extends ClientLauncher{ if(useSteam){ if(showConsole){ + StringBuilder base = new StringBuilder(); + Log.setLogger(new LogHandler(){ + @Override + public void print(String text, Object... args){ + String out = Log.format(text, false, args); + + base.append(out).append("\n"); + } + }); + Events.on(ClientLoadEvent.class, event -> { Label[] label = {null}; boolean[] visible = {false}; @@ -86,6 +98,7 @@ public class DesktopLauncher extends ClientLauncher{ t.toFront(); }); t.table(Styles.black3, f -> label[0] = f.add("").get()).visible(() -> visible[0]); + label[0].getText().append(base); }); Log.setLogger(new LogHandler(){ @@ -177,12 +190,18 @@ public class DesktopLauncher extends ClientLauncher{ boolean fbgp = badGPU; CrashSender.send(e, file -> { + Throwable cause = Strings.getFinalCause(e); if(!fbgp){ - dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + (e.getMessage() == null ? "" : "\n" + e.getMessage()))); + dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + cause.getClass().getSimpleName().replace("Exception", "") + (cause.getMessage() == null ? "" : ":\n" + cause.getMessage()))); } }); } + @Override + public Array getExternalMaps(){ + return !steam ? super.getExternalMaps() : SVars.workshop.getMapFiles(); + } + @Override public NetProvider getNet(){ return steam ? SVars.net : new ArcNetImpl(); diff --git a/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java b/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java index 07273818d2..fd9f360084 100644 --- a/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java +++ b/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java @@ -4,6 +4,7 @@ import com.codedisaster.steamworks.*; import com.codedisaster.steamworks.SteamRemoteStorage.*; import com.codedisaster.steamworks.SteamUGC.*; import io.anuke.arc.*; +import io.anuke.arc.collection.*; import io.anuke.arc.files.*; import io.anuke.arc.util.*; import io.anuke.mindustry.game.EventType.*; @@ -18,17 +19,23 @@ public class SWorkshop implements SteamUGCCallback{ public final SteamUGC ugc = new SteamUGC(this); private Map lastMap; + private Array mapFiles; public SWorkshop(){ int items = ugc.getNumSubscribedItems(); SteamPublishedFileID[] ids = new SteamPublishedFileID[items]; + ItemInstallInfo info = new ItemInstallInfo(); ugc.getSubscribedItems(ids); - for(int i = 0; i < items; i++){ - SteamPublishedFileID id = ids[i]; - ItemInstallInfo info = new ItemInstallInfo(); - ugc.getItemInstallInfo(id, info); + mapFiles = 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]); - } + Log.info("Fetching {0} subscribed maps.", items); + } + + public Array getMapFiles(){ + return mapFiles; } public void publishMap(Map map){