From 7aa71a720158a9ac1b819c552bb7ce5cb0563b48 Mon Sep 17 00:00:00 2001 From: Anuken Date: Tue, 10 Sep 2019 14:25:34 -0400 Subject: [PATCH] Steam workshop publishing --- .../AssetsAnnotationProcessor.java | 2 +- core/assets/bundles/bundle.properties | 4 +- .../mindustry/editor/MapEditorDialog.java | 19 +++++++- core/src/io/anuke/mindustry/game/Rules.java | 5 ++ .../mindustry/desktop/steam/SWorkshop.java | 48 ++++++++++++++++--- 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/annotations/src/main/java/io/anuke/annotations/AssetsAnnotationProcessor.java b/annotations/src/main/java/io/anuke/annotations/AssetsAnnotationProcessor.java index 382d95a5c8..e61c769f2c 100644 --- a/annotations/src/main/java/io/anuke/annotations/AssetsAnnotationProcessor.java +++ b/annotations/src/main/java/io/anuke/annotations/AssetsAnnotationProcessor.java @@ -58,7 +58,7 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{ MethodSpec.Builder icload = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC); String resources = path + "/assets-raw/sprites/ui"; Files.walk(Paths.get(resources)).forEach(p -> { - if(Files.isDirectory(p)) return; + if(Files.isDirectory(p) || p.getFileName().toString().equals(".DS_Store")) return; String filename = p.getFileName().toString(); filename = filename.substring(0, filename.indexOf(".")); diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f0b96d37f8..a59c83667a 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -191,7 +191,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 @@ -199,6 +199,7 @@ map.nospawn = This map does not have any cores for the player to spawn in! Add a map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] non-orange[] cores to this map in the editor. map.nospawn.attack = This map does not have any enemy cores for player to attack! Add[SCARLET] red[] cores to this map in the editor. map.invalid = Error loading map: corrupted or invalid map file. +map.publish.error = Error publishing map: {0} editor.brush = Brush editor.openin = Open In Editor editor.oregen = Ore Generation @@ -210,6 +211,7 @@ editor.waves = Waves: editor.rules = Rules: editor.generation = Generation: editor.ingame = Edit In-Game +editor.publish.workshop = Publish On Workshop editor.newmap = New Map waves.title = Waves waves.remove = Remove diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index aa3f923ef0..81240f340b 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -151,7 +151,18 @@ public class MapEditorDialog extends Dialog implements Disposable{ menu.cont.row(); - menu.cont.addImageTextButton("$editor.ingame", Icon.arrowSmall, this::playtest).padTop(-5).size(swidth * 2f + 10, 60f); + if(steam){ + menu.cont.addImageTextButton("$editor.publish.workshop", Icon.arrowSmall, () -> { + Map map = save(); + if(map != null){ + platform.publishMap(map); + } + }).padTop(-3).size(swidth * 2f + 10, 60f); + + menu.cont.row(); + } + + menu.cont.addImageTextButton("$editor.ingame", Icon.arrowSmall, this::playtest).padTop(-3).size(swidth * 2f + 10, 60f); menu.cont.row(); @@ -265,13 +276,15 @@ public class MapEditorDialog extends Dialog implements Disposable{ }); } - private void save(){ + private Map save(){ String name = editor.getTags().get("name", "").trim(); editor.getTags().put("rules", JsonIO.write(state.rules)); editor.getTags().remove("width"); editor.getTags().remove("height"); player.dead = true; + Map returned = null; + if(name.isEmpty()){ infoDialog.show(); Core.app.post(() -> ui.showErrorMessage("$editor.save.noname")); @@ -282,11 +295,13 @@ public class MapEditorDialog extends Dialog implements Disposable{ }else{ maps.saveMap(editor.getTags()); ui.showInfoFade("$editor.saved"); + returned = map; } } menu.hide(); saved = true; + return returned; } /** Called when a built-in map save is attempted.*/ diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index 014a918904..0d85482976 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -74,4 +74,9 @@ public class Rules{ public Rules copy(){ return JsonIO.copy(this); } + + /** Returns the gamemode that best fits these rules.*/ + public Gamemode mode(){ + return Gamemode.bestFit(this); + } } diff --git a/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java b/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java index cb8adb38ed..282fe18b78 100644 --- a/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java +++ b/desktop/src/io/anuke/mindustry/desktop/steam/SWorkshop.java @@ -2,12 +2,21 @@ package io.anuke.mindustry.desktop.steam; import com.codedisaster.steamworks.*; import com.codedisaster.steamworks.SteamRemoteStorage.*; +import io.anuke.arc.*; +import io.anuke.arc.files.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.maps.*; +import static io.anuke.mindustry.Vars.*; + public class SWorkshop implements SteamUGCCallback{ public final SteamUGC ugc = new SteamUGC(this); + private Map lastMap; + public void publishMap(Map map){ + this.lastMap = map; ugc.createItem(SVars.steamID, WorkshopFileType.GameManagedItem); } @@ -33,18 +42,43 @@ public class SWorkshop implements SteamUGCCallback{ @Override public void onCreateItem(SteamPublishedFileID publishedFileID, boolean needsToAcceptWLA, SteamResult result){ - //TODO - if(result == SteamResult.OK){ - - }else{ - //TODO show "failed to create" dialog - //ui.showError(""); + if(lastMap == null){ + Log.err("No map to publish?"); + return; } + + Map map = lastMap; + + if(result == SteamResult.OK){ + SteamUGCUpdateHandle h = ugc.startItemUpdate(SVars.steamID, publishedFileID); + + Gamemode mode = Gamemode.attack.valid(map) ? Gamemode.attack : Gamemode.survival; + FileHandle mapFile = tmpDirectory.child("map_" + publishedFileID.toString()).child("preview.png"); + lastMap.file.copyTo(mapFile); + + ugc.setItemTitle(h, map.name()); + ugc.setItemDescription(h, map.description()); + ugc.setItemTags(h, new String[]{"map", mode.name()}); + ugc.setItemVisibility(h, PublishedFileVisibility.Public); + ugc.setItemPreview(h, map.previewFile().absolutePath()); + ugc.setItemContent(h, mapFile.parent().absolutePath()); + ugc.addItemKeyValueTag(h, "mode", mode.name()); + ugc.submitItemUpdate(h, "Map created"); + }else{ + ui.showErrorMessage(Core.bundle.format("map.publish.error ", result.name())); + } + + lastMap = null; } @Override public void onSubmitItemUpdate(SteamPublishedFileID publishedFileID, boolean needsToAcceptWLA, SteamResult result){ - + if(result == SteamResult.OK){ + //redirect user to page for further updates + SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + publishedFileID.toString()); + }else{ + ui.showErrorMessage(Core.bundle.format("map.publish.error ", result.name())); + } } @Override