Complete refactoring of workshop / Schematic+mod support
This commit is contained in:
@@ -99,6 +99,8 @@ mod.import.github = Import Github Mod
|
|||||||
mod.remove.confirm = This mod will be deleted.
|
mod.remove.confirm = This mod will be deleted.
|
||||||
mod.author = [LIGHT_GRAY]Author:[] {0}
|
mod.author = [LIGHT_GRAY]Author:[] {0}
|
||||||
mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0}
|
mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0}
|
||||||
|
mod.preview.missing = Before publishing this mod in the workshop, you must add an image preview.\nPlace an image named[accent] preview.png[] into the mod's folder and try again.
|
||||||
|
mod.folder.missing = Only mods in folder form can be published on the workshop.\nTo convert any mod into a folder, simply unzip its file into a folder and delete the old zip, then restart your game or reload your mods.
|
||||||
|
|
||||||
about.button = About
|
about.button = About
|
||||||
name = Name:
|
name = Name:
|
||||||
@@ -255,14 +257,13 @@ 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.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.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.invalid = Error loading map: corrupted or invalid map file.
|
||||||
map.update = Update Map
|
workshop.update = Update Item
|
||||||
map.load.error = Error fetching workshop details: {0}
|
workshop.error = Error fetching workshop details: {0}
|
||||||
map.missing = This map has been deleted or moved.\n[lightgray]The workshop listing has now been automatically un-linked from the map.
|
|
||||||
map.publish.confirm = Are you sure you want to publish this map?\n\n[lightgray]Make sure you agree to the Workshop EULA first, or your maps will not show up!
|
map.publish.confirm = Are you sure you want to publish this map?\n\n[lightgray]Make sure you agree to the Workshop EULA first, or your maps will not show up!
|
||||||
map.menu = Select what you would like to do with this map.
|
map.menu = Select what you would like to do with this map.
|
||||||
map.changelog = Changelog (optional):
|
changelog = Changelog (optional):
|
||||||
eula = Steam EULA
|
eula = Steam EULA
|
||||||
map.publish = Map published.
|
missing = This item has been deleted or moved.\n[lightgray]The workshop listing has now been automatically un-linked.
|
||||||
publishing = [accent]Publishing...
|
publishing = [accent]Publishing...
|
||||||
publish.confirm = Are you sure you want to publish this?\n\n[lightgray]Make sure you agree to the Workshop EULA first, or your items will not show up!
|
publish.confirm = Are you sure you want to publish this?\n\n[lightgray]Make sure you agree to the Workshop EULA first, or your items will not show up!
|
||||||
publish.error = Error publishing item: {0}
|
publish.error = Error publishing item: {0}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import io.anuke.arc.function.*;
|
|||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.util.serialization.*;
|
import io.anuke.arc.util.serialization.*;
|
||||||
import io.anuke.mindustry.maps.*;
|
|
||||||
import io.anuke.mindustry.net.*;
|
import io.anuke.mindustry.net.*;
|
||||||
import io.anuke.mindustry.net.Net.*;
|
import io.anuke.mindustry.net.Net.*;
|
||||||
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.ui.dialogs.*;
|
import io.anuke.mindustry.ui.dialogs.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.mobile;
|
import static io.anuke.mindustry.Vars.mobile;
|
||||||
@@ -24,32 +24,18 @@ public interface Platform{
|
|||||||
default void inviteFriends(){}
|
default void inviteFriends(){}
|
||||||
|
|
||||||
/** Steam: Share a map on the workshop.*/
|
/** Steam: Share a map on the workshop.*/
|
||||||
default void publishMap(Map map){}
|
default void publish(Publishable pub){}
|
||||||
|
|
||||||
/** Steam: Return external workshop maps to be loaded.*/
|
|
||||||
default Array<FileHandle> getExternalMaps(){
|
|
||||||
return Array.with();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Steam: Return external workshop mods to be loaded.*/
|
|
||||||
default Array<FileHandle> getExternalMods(){
|
|
||||||
return Array.with();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Steam: Return external workshop schematics to be loaded.*/
|
|
||||||
default Array<FileHandle> getExternalSchematics(){
|
|
||||||
return Array.with();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Steam: View a map listing on the workshop.*/
|
|
||||||
default void viewMapListing(Map map){}
|
|
||||||
|
|
||||||
/** Steam: View a listing on the workshop.*/
|
/** Steam: View a listing on the workshop.*/
|
||||||
default void viewListing(String mapid){}
|
default void viewListing(Publishable pub){}
|
||||||
|
|
||||||
/** Steam: View map workshop info, removing the map ID tag if its listing is deleted.
|
/** Steam: View a listing on the workshop by an ID.*/
|
||||||
* Also presents the option to update the map. */
|
default void viewListingID(String mapid){}
|
||||||
default void viewMapListingInfo(Map map){}
|
|
||||||
|
/** Steam: Return external workshop maps to be loaded.*/
|
||||||
|
default Array<FileHandle> getWorkshopContent(Class<? extends Publishable> type){
|
||||||
|
return new Array<>(0);
|
||||||
|
}
|
||||||
|
|
||||||
/** Steam: Open workshop for maps.*/
|
/** Steam: Open workshop for maps.*/
|
||||||
default void openWorkshop(){}
|
default void openWorkshop(){}
|
||||||
|
|||||||
@@ -149,15 +149,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
if(steam){
|
if(steam){
|
||||||
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.linkSmall, () -> {
|
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.linkSmall, () -> {
|
||||||
Map builtin = maps.all().find(m -> m.name().equals(editor.getTags().get("name", "").trim()));
|
Map builtin = maps.all().find(m -> m.name().equals(editor.getTags().get("name", "").trim()));
|
||||||
|
|
||||||
if(editor.getTags().containsKey("steamid") && builtin != null && !builtin.custom){
|
if(editor.getTags().containsKey("steamid") && builtin != null && !builtin.custom){
|
||||||
platform.viewListing(editor.getTags().get("steamid"));
|
platform.viewListingID(editor.getTags().get("steamid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map map = save();
|
Map map = save();
|
||||||
|
|
||||||
if(editor.getTags().containsKey("steamid") && map != null){
|
if(editor.getTags().containsKey("steamid") && map != null){
|
||||||
platform.viewMapListingInfo(map);
|
platform.viewListing(map);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +174,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.publishMap(map);
|
platform.publish(map);
|
||||||
}).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.getTags().containsKey("steamid") ? editor.getTags().get("author").equals(player.name) ? "$workshop.listing" : "$view.workshop" : "$editor.publish.workshop"));
|
}).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.getTags().containsKey("steamid") ? editor.getTags().get("author").equals(player.name) ? "$workshop.listing" : "$view.workshop" : "$editor.publish.workshop"));
|
||||||
|
|
||||||
menu.cont.row();
|
menu.cont.row();
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import io.anuke.arc.collection.IntIntMap.*;
|
|||||||
import io.anuke.arc.files.*;
|
import io.anuke.arc.files.*;
|
||||||
import io.anuke.arc.util.ArcAnnotate.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.mindustry.*;
|
import io.anuke.mindustry.*;
|
||||||
|
import io.anuke.mindustry.game.Schematics.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
public class Schematic{
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
|
public class Schematic implements Publishable{
|
||||||
public final Array<Stile> tiles;
|
public final Array<Stile> tiles;
|
||||||
public StringMap tags;
|
public StringMap tags;
|
||||||
public int width, height;
|
public int width, height;
|
||||||
@@ -41,8 +44,54 @@ public class Schematic{
|
|||||||
return tags.get("name", "unknown");
|
return tags.get("name", "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWorkshop(){
|
public void save(){
|
||||||
return tags.containsKey("workshop");
|
schematics.saveChanges(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSteamID(){
|
||||||
|
return tags.get("steamid");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSteamID(String id){
|
||||||
|
tags.put("steamid", id);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSteamID(){
|
||||||
|
tags.remove("steamid");
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamTitle(){
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamDescription(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamTag(){
|
||||||
|
return "schematic";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileHandle createSteamFolder(String id){
|
||||||
|
FileHandle directory = tmpDirectory.child("schematic_" + id).child("schematic." + schematicExtension);
|
||||||
|
file.copyTo(directory);
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileHandle createSteamPreview(String id){
|
||||||
|
FileHandle preview = tmpDirectory.child("schematic_preview_" + id + ".png");
|
||||||
|
schematics.savePreview(this, PreviewRes.high, preview);
|
||||||
|
return preview;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Stile{
|
public static class Stile{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class Schematics implements Loadable{
|
|||||||
loadFile(file);
|
loadFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.getExternalSchematics().each(this::loadFile);
|
platform.getWorkshopContent(Schematic.class).each(this::loadFile);
|
||||||
|
|
||||||
Core.app.post(() -> {
|
Core.app.post(() -> {
|
||||||
shadowBuffer = new FrameBuffer(maxSchematicSize + padding + 2, maxSchematicSize + padding + 2);
|
shadowBuffer = new FrameBuffer(maxSchematicSize + padding + 2, maxSchematicSize + padding + 2);
|
||||||
@@ -69,7 +69,13 @@ public class Schematics implements Loadable{
|
|||||||
if(!file.extension().equals(schematicExtension)) return;
|
if(!file.extension().equals(schematicExtension)) return;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
all.add(read(file));
|
Schematic s = read(file);
|
||||||
|
all.add(s);
|
||||||
|
|
||||||
|
//external file from workshop
|
||||||
|
if(!s.file.parent().equals(schematicDirectory)){
|
||||||
|
s.tags.put("steamid", s.file.parent().name());
|
||||||
|
}
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
@@ -79,7 +85,30 @@ public class Schematics implements Loadable{
|
|||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveChanges(Schematic s){
|
||||||
|
if(s.file != null){
|
||||||
|
try{
|
||||||
|
write(s, s.file);
|
||||||
|
}catch(Exception e){
|
||||||
|
ui.showException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void savePreview(Schematic schematic, PreviewRes res, FileHandle file){
|
||||||
|
FrameBuffer buffer = getBuffer(schematic, res);
|
||||||
|
Draw.flush();
|
||||||
|
buffer.begin();
|
||||||
|
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, buffer.getWidth(), buffer.getHeight());
|
||||||
|
file.writePNG(pixmap);
|
||||||
|
buffer.end();
|
||||||
|
}
|
||||||
|
|
||||||
public Texture getPreview(Schematic schematic, PreviewRes res){
|
public Texture getPreview(Schematic schematic, PreviewRes res){
|
||||||
|
return getBuffer(schematic, res).getTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameBuffer getBuffer(Schematic schematic, PreviewRes res){
|
||||||
if(!previews.getOr(schematic, ObjectMap::new).containsKey(res)){
|
if(!previews.getOr(schematic, ObjectMap::new).containsKey(res)){
|
||||||
int resolution = res.resolution;
|
int resolution = res.resolution;
|
||||||
Draw.blend();
|
Draw.blend();
|
||||||
@@ -113,11 +142,6 @@ public class Schematics implements Loadable{
|
|||||||
buffer.beginDraw(Color.clear);
|
buffer.beginDraw(Color.clear);
|
||||||
|
|
||||||
Draw.proj().setOrtho(0, buffer.getHeight(), buffer.getWidth(), -buffer.getHeight());
|
Draw.proj().setOrtho(0, buffer.getHeight(), buffer.getWidth(), -buffer.getHeight());
|
||||||
for(int x = 0; x < schematic.width + padding; x++){
|
|
||||||
for(int y = 0; y < schematic.height + padding; y++){
|
|
||||||
//Draw.rect("metal-floor", x * resolution + resolution/2f, y * resolution + resolution/2f, resolution, resolution);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Tmp.tr1.set(shadowBuffer.getTexture(), 0, 0, schematic.width + padding, schematic.height + padding);
|
Tmp.tr1.set(shadowBuffer.getTexture(), 0, 0, schematic.width + padding, schematic.height + padding);
|
||||||
Draw.color(0f, 0f, 0f, 1f);
|
Draw.color(0f, 0f, 0f, 1f);
|
||||||
@@ -127,8 +151,10 @@ public class Schematics implements Loadable{
|
|||||||
Array<BuildRequest> requests = schematic.tiles.map(t -> new BuildRequest(t.x, t.y, t.rotation, t.block).configure(t.config));
|
Array<BuildRequest> requests = schematic.tiles.map(t -> new BuildRequest(t.x, t.y, t.rotation, t.block).configure(t.config));
|
||||||
|
|
||||||
Draw.flush();
|
Draw.flush();
|
||||||
|
//scale each request to fit schematic
|
||||||
Draw.trans().scale(resolution / tilesize, resolution / tilesize).translate(tilesize*1.5f, tilesize*1.5f);
|
Draw.trans().scale(resolution / tilesize, resolution / tilesize).translate(tilesize*1.5f, tilesize*1.5f);
|
||||||
|
|
||||||
|
//draw requests
|
||||||
requests.each(req -> {
|
requests.each(req -> {
|
||||||
req.animScale = 1f;
|
req.animScale = 1f;
|
||||||
req.block.drawRequestRegion(req, requests::each);
|
req.block.drawRequestRegion(req, requests::each);
|
||||||
@@ -148,7 +174,7 @@ public class Schematics implements Loadable{
|
|||||||
Log.info("Time taken: {0}", Time.elapsed());
|
Log.info("Time taken: {0}", Time.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
return previews.get(schematic).get(res).getTexture();
|
return previews.get(schematic).get(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates an array of build requests from a schematic's data, centered on the provided x+y coordinates. */
|
/** Creates an array of build requests from a schematic's data, centered on the provided x+y coordinates. */
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ public class Tutorial{
|
|||||||
Events.on(BlockInfoEvent.class, event -> events.add("blockinfo"));
|
Events.on(BlockInfoEvent.class, event -> events.add("blockinfo"));
|
||||||
Events.on(DepositEvent.class, event -> events.add("deposit"));
|
Events.on(DepositEvent.class, event -> events.add("deposit"));
|
||||||
Events.on(WithdrawEvent.class, event -> events.add("withdraw"));
|
Events.on(WithdrawEvent.class, event -> events.add("withdraw"));
|
||||||
|
|
||||||
|
for(TutorialStage stage : TutorialStage.values()){
|
||||||
|
stage.load();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** update tutorial state, transition if needed */
|
/** update tutorial state, transition if needed */
|
||||||
@@ -204,13 +208,17 @@ public class Tutorial{
|
|||||||
/** displayed tutorial stage text.*/
|
/** displayed tutorial stage text.*/
|
||||||
public String text(){
|
public String text(){
|
||||||
if(sentences == null){
|
if(sentences == null){
|
||||||
this.line = Core.bundle.has("tutorial." + name() + ".mobile") && mobile ? "tutorial." + name() + ".mobile" : "tutorial." + name();
|
load();
|
||||||
this.sentences = Array.select(Core.bundle.get(line).split("\n"), s -> !s.isEmpty());
|
|
||||||
}
|
}
|
||||||
String line = sentences.get(control.tutorial.sentence);
|
String line = sentences.get(control.tutorial.sentence);
|
||||||
return line.contains("{") ? text.get(line) : line;
|
return line.contains("{") ? text.get(line) : line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load(){
|
||||||
|
this.line = Core.bundle.has("tutorial." + name() + ".mobile") && mobile ? "tutorial." + name() + ".mobile" : "tutorial." + name();
|
||||||
|
this.sentences = Array.select(Core.bundle.get(line).split("\n"), s -> !s.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
/** called every frame when this stage is active.*/
|
/** called every frame when this stage is active.*/
|
||||||
void update(){
|
void update(){
|
||||||
|
|
||||||
|
|||||||
@@ -283,6 +283,11 @@ public class DesktopInput extends InputHandler{
|
|||||||
schemY = rawCursorY;
|
schemY = rawCursorY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Core.input.keyTap(Binding.clear_building)){
|
||||||
|
lastSchematic = null;
|
||||||
|
selectRequests.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if(Core.input.keyRelease(Binding.schematic)){
|
if(Core.input.keyRelease(Binding.schematic)){
|
||||||
lastSchematic = schematics.create(schemX, schemY, rawCursorX, rawCursorY);
|
lastSchematic = schematics.create(schemX, schemY, rawCursorX, rawCursorY);
|
||||||
useSchematic(lastSchematic);
|
useSchematic(lastSchematic);
|
||||||
|
|||||||
@@ -4,14 +4,17 @@ import io.anuke.arc.*;
|
|||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.files.*;
|
import io.anuke.arc.files.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.*;
|
import io.anuke.mindustry.*;
|
||||||
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.io.*;
|
import io.anuke.mindustry.io.*;
|
||||||
import io.anuke.mindustry.maps.filters.*;
|
import io.anuke.mindustry.maps.filters.*;
|
||||||
|
import io.anuke.mindustry.type.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.maps;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class Map implements Comparable<Map>{
|
public class Map implements Comparable<Map>, Publishable{
|
||||||
/** Whether this is a custom map. */
|
/** Whether this is a custom map. */
|
||||||
public final boolean custom;
|
public final boolean custom;
|
||||||
/** Metadata. Author description, display name, etc. */
|
/** Metadata. Author description, display name, etc. */
|
||||||
@@ -131,6 +134,76 @@ public class Map implements Comparable<Map>{
|
|||||||
return tags.containsKey(name);
|
return tags.containsKey(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSteamID(){
|
||||||
|
return tags.get("steamid");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSteamID(String id){
|
||||||
|
tags.put("steamid", id);
|
||||||
|
|
||||||
|
ui.editor.editor.getTags().put("steamid", id);
|
||||||
|
try{
|
||||||
|
ui.editor.save();
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
|
Events.fire(new MapPublishEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSteamID(){
|
||||||
|
tags.remove("steamid");
|
||||||
|
|
||||||
|
ui.editor.editor.getTags().remove("steamid");
|
||||||
|
try{
|
||||||
|
ui.editor.save();
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamTitle(){
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamDescription(){
|
||||||
|
return description();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamTag(){
|
||||||
|
return "map";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileHandle createSteamFolder(String id){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileHandle createSteamPreview(String id){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Array<String> extraTags(){
|
||||||
|
Gamemode mode = Gamemode.attack.valid(this) ? Gamemode.attack : Gamemode.survival;
|
||||||
|
return Array.with(mode.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prePublish(){
|
||||||
|
tags.put("author", player.name);
|
||||||
|
ui.editor.editor.getTags().put("author", tags.get("author"));
|
||||||
|
ui.editor.save();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Map map){
|
public int compareTo(Map map){
|
||||||
int work = -Boolean.compare(workshop, map.workshop);
|
int work = -Boolean.compare(workshop, map.workshop);
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class Maps{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//workshop
|
//workshop
|
||||||
for(FileHandle file : platform.getExternalMaps()){
|
for(FileHandle file : platform.getWorkshopContent(Map.class)){
|
||||||
try{
|
try{
|
||||||
Map map = loadMap(file, false);
|
Map map = loadMap(file, false);
|
||||||
map.workshop = true;
|
map.workshop = true;
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//load workshop mods now
|
//load workshop mods now
|
||||||
for(FileHandle file : platform.getExternalMods()){
|
for(FileHandle file : platform.getWorkshopContent(LoadedMod.class)){
|
||||||
try{
|
try{
|
||||||
LoadedMod mod = loadMod(file, true);
|
LoadedMod mod = loadMod(file, true);
|
||||||
if(mod.enabled()){
|
if(mod.enabled()){
|
||||||
@@ -442,7 +442,7 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Represents a plugin that has been loaded from a jar file.*/
|
/** Represents a plugin that has been loaded from a jar file.*/
|
||||||
public static class LoadedMod{
|
public static class LoadedMod implements Publishable{
|
||||||
/** The location of this mod's zip file/folder on the disk. */
|
/** The location of this mod's zip file/folder on the disk. */
|
||||||
public final FileHandle file;
|
public final FileHandle file;
|
||||||
/** The root zip file; points to the contents of this mod. In the case of folders, this is the same as the mod's file. */
|
/** The root zip file; points to the contents of this mod. In the case of folders, this is the same as the mod's file. */
|
||||||
@@ -453,8 +453,6 @@ 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;
|
||||||
@@ -468,6 +466,63 @@ public class Mods implements Loadable{
|
|||||||
return Core.settings.getBool(name + "-enabled", true);
|
return Core.settings.getBool(name + "-enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSteamID(){
|
||||||
|
return Core.settings.getString(name + "-steamid", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSteamID(String id){
|
||||||
|
Core.settings.put(name + "-steamid", id);
|
||||||
|
Core.settings.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSteamID(){
|
||||||
|
Core.settings.remove(name + "-steamid");
|
||||||
|
Core.settings.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamTitle(){
|
||||||
|
return meta.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamDescription(){
|
||||||
|
return meta.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String steamTag(){
|
||||||
|
return "mod";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileHandle createSteamFolder(String id){
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileHandle createSteamPreview(String id){
|
||||||
|
return file.child("preview.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean prePublish(){
|
||||||
|
if(!file.isDirectory()){
|
||||||
|
ui.showErrorMessage("$mod.folder.missing");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!file.child("preview.png").exists()){
|
||||||
|
ui.showErrorMessage("$mod.preview.missing");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "LoadedMod{" +
|
return "LoadedMod{" +
|
||||||
|
|||||||
40
core/src/io/anuke/mindustry/type/Publishable.java
Normal file
40
core/src/io/anuke/mindustry/type/Publishable.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package io.anuke.mindustry.type;
|
||||||
|
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
|
import io.anuke.arc.files.*;
|
||||||
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
|
import io.anuke.mindustry.*;
|
||||||
|
|
||||||
|
/** Defines a piece of content that can be published on the Workshop. */
|
||||||
|
public interface Publishable{
|
||||||
|
/** @return workshop item ID, or null if this isn't on the workshop. */
|
||||||
|
@Nullable String getSteamID();
|
||||||
|
/** adds a steam ID to this item once it's published. should save the item to make sure this change is persisted. */
|
||||||
|
void addSteamID(String id);
|
||||||
|
/** removes the item ID; called when the item isn't found. */
|
||||||
|
void removeSteamID();
|
||||||
|
/** @return default title of the listing. */
|
||||||
|
String steamTitle();
|
||||||
|
/** @return standard steam listing description, may be null. this is editable by users after release.*/
|
||||||
|
@Nullable String steamDescription();
|
||||||
|
/** @return the tag that this content has. e.g. 'schematic' or 'map'. */
|
||||||
|
String steamTag();
|
||||||
|
/** @return a folder with everything needed for this piece of content in it; does not need to be a copy. */
|
||||||
|
FileHandle createSteamFolder(String id);
|
||||||
|
/** @return a preview file PNG. */
|
||||||
|
FileHandle createSteamPreview(String id);
|
||||||
|
/** @return any extra tags to add to this item.*/
|
||||||
|
default Array<String> extraTags(){
|
||||||
|
return new Array<>(0);
|
||||||
|
}
|
||||||
|
/** @return whether this item is or was once on the workshop.*/
|
||||||
|
default boolean hasSteamID(){
|
||||||
|
return getSteamID() != null && Vars.steam;
|
||||||
|
}
|
||||||
|
/** called before this item is published.
|
||||||
|
* @return true to signify that everything is cool and good, or false to significy that the user has done something wrong.
|
||||||
|
* if false is returned, make sure to show a dialog explaining the error. */
|
||||||
|
default boolean prePublish(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -205,7 +205,7 @@ public class MapsDialog extends FloatingDialog{
|
|||||||
|
|
||||||
table.addImageTextButton(map.workshop && steam ? "$view.workshop" : "$delete", map.workshop && steam ? Icon.linkSmall : Icon.trash16Small, () -> {
|
table.addImageTextButton(map.workshop && steam ? "$view.workshop" : "$delete", map.workshop && steam ? Icon.linkSmall : Icon.trash16Small, () -> {
|
||||||
if(map.workshop && steam){
|
if(map.workshop && steam){
|
||||||
platform.viewMapListing(map);
|
platform.viewListing(map);
|
||||||
}else{
|
}else{
|
||||||
ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name()), () -> {
|
ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name()), () -> {
|
||||||
maps.removeMap(map);
|
maps.removeMap(map);
|
||||||
|
|||||||
@@ -101,14 +101,20 @@ public class ModsDialog extends FloatingDialog{
|
|||||||
setup();
|
setup();
|
||||||
}).height(50f).margin(8f).width(130f);
|
}).height(50f).margin(8f).width(130f);
|
||||||
|
|
||||||
title.addImageButton(mod.workshopID != null ? Icon.linkSmall : Icon.trash16Small, Styles.cleari, () -> {
|
if(steam && !mod.hasSteamID()){
|
||||||
if(mod.workshopID == null){
|
title.addImageButton(Icon.loadMapSmall, Styles.cleari, () -> {
|
||||||
|
platform.publish(mod);
|
||||||
|
}).size(50f);
|
||||||
|
}
|
||||||
|
|
||||||
|
title.addImageButton(mod.hasSteamID() ? Icon.linkSmall : Icon.trash16Small, Styles.cleari, () -> {
|
||||||
|
if(!mod.hasSteamID()){
|
||||||
ui.showConfirm("$confirm", "$mod.remove.confirm", () -> {
|
ui.showConfirm("$confirm", "$mod.remove.confirm", () -> {
|
||||||
mods.removeMod(mod);
|
mods.removeMod(mod);
|
||||||
setup();
|
setup();
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
platform.viewListing(mod.workshopID);
|
platform.viewListing(mod);
|
||||||
}
|
}
|
||||||
}).size(50f);
|
}).size(50f);
|
||||||
}).growX().left().padTop(-14f).padRight(-14f);
|
}).growX().left().padTop(-14f).padRight(-14f);
|
||||||
|
|||||||
@@ -91,12 +91,16 @@ public class SchematicsDialog extends FloatingDialog{
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
buttons.addImageButton(Icon.trash16Small, style, () -> {
|
if(s.hasSteamID()){
|
||||||
ui.showConfirm("$confirm", "$schematic.delete.confirm", () -> {
|
buttons.addImageButton(Icon.linkSmall, style, () -> platform.viewListing(s));
|
||||||
schematics.remove(s);
|
}else{
|
||||||
rebuildPane[0].run();
|
buttons.addImageButton(Icon.trash16Small, style, () -> {
|
||||||
|
ui.showConfirm("$confirm", "$schematic.delete.confirm", () -> {
|
||||||
|
schematics.remove(s);
|
||||||
|
rebuildPane[0].run();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
}).growX().height(50f);
|
}).growX().height(50f);
|
||||||
b.row();
|
b.row();
|
||||||
@@ -180,10 +184,9 @@ public class SchematicsDialog extends FloatingDialog{
|
|||||||
p.table(Tex.button, t -> {
|
p.table(Tex.button, t -> {
|
||||||
TextButtonStyle style = Styles.cleart;
|
TextButtonStyle style = Styles.cleart;
|
||||||
t.defaults().size(280f, 60f).left();
|
t.defaults().size(280f, 60f).left();
|
||||||
if(steam){
|
if(steam && !s.hasSteamID()){
|
||||||
t.addImageTextButton("$schematic.shareworkshop", Icon.wikiSmall, style, () -> {
|
t.addImageTextButton("$schematic.shareworkshop", Icon.wikiSmall, style,
|
||||||
|
() -> platform.publish(s)).marginLeft(12f);
|
||||||
}).marginLeft(12f);
|
|
||||||
t.row();
|
t.row();
|
||||||
}
|
}
|
||||||
t.addImageTextButton("$schematic.copy", Icon.copySmall, style, () -> {
|
t.addImageTextButton("$schematic.copy", Icon.copySmall, style, () -> {
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import io.anuke.mindustry.core.GameState.*;
|
|||||||
import io.anuke.mindustry.desktop.steam.*;
|
import io.anuke.mindustry.desktop.steam.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.game.Version;
|
import io.anuke.mindustry.game.Version;
|
||||||
import io.anuke.mindustry.maps.Map;
|
|
||||||
import io.anuke.mindustry.mod.Mods.*;
|
import io.anuke.mindustry.mod.Mods.*;
|
||||||
import io.anuke.mindustry.net.*;
|
import io.anuke.mindustry.net.*;
|
||||||
import io.anuke.mindustry.net.Net.*;
|
import io.anuke.mindustry.net.Net.*;
|
||||||
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.ui.*;
|
import io.anuke.mindustry.ui.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -249,34 +249,18 @@ public class DesktopLauncher extends ClientLauncher{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<FileHandle> getExternalMaps(){
|
public Array<FileHandle> getWorkshopContent(Class<? extends Publishable> type){
|
||||||
return !steam ? super.getExternalMaps() : SVars.workshop.getMapFiles();
|
return !steam ? super.getWorkshopContent(type) : SVars.workshop.getWorkshopFiles(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<FileHandle> getExternalMods(){
|
public void viewListing(Publishable pub){
|
||||||
return !steam ? super.getExternalMods() : SVars.workshop.getModFiles();
|
SVars.workshop.viewListing(pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<FileHandle> getExternalSchematics(){
|
public void viewListingID(String id){
|
||||||
return !steam ? super.getExternalMods() : SVars.workshop.getSchematicFiles();
|
SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + id);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void viewMapListing(Map map){
|
|
||||||
viewListing(map.file.parent().name());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void viewListing(String mapid){
|
|
||||||
SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + mapid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void viewMapListingInfo(Map map){
|
|
||||||
SVars.workshop.viewMapListingInfo(map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -290,8 +274,8 @@ public class DesktopLauncher extends ClientLauncher{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void publishMap(Map map){
|
public void publish(Publishable pub){
|
||||||
SVars.workshop.publishMap(map);
|
SVars.workshop.publish(pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import io.anuke.arc.files.*;
|
|||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.maps.*;
|
import io.anuke.mindustry.maps.*;
|
||||||
import io.anuke.mindustry.mod.Mods.*;
|
import io.anuke.mindustry.mod.Mods.*;
|
||||||
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.ui.dialogs.*;
|
import io.anuke.mindustry.ui.dialogs.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
@@ -21,12 +21,10 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
public class SWorkshop implements SteamUGCCallback{
|
public class SWorkshop implements SteamUGCCallback{
|
||||||
public final SteamUGC ugc = new SteamUGC(this);
|
public final SteamUGC ugc = new SteamUGC(this);
|
||||||
|
|
||||||
//private Map lastMap;
|
private ObjectMap<Class<? extends Publishable>, Array<FileHandle>> workshopFiles = new ObjectMap<>();
|
||||||
private Array<FileHandle> mapFiles;
|
|
||||||
private Array<FileHandle> modFiles;
|
|
||||||
private Array<FileHandle> schematicFiles;
|
|
||||||
private ObjectMap<SteamUGCQuery, BiConsumer<Array<SteamUGCDetails>, SteamResult>> detailHandlers = new ObjectMap<>();
|
private ObjectMap<SteamUGCQuery, BiConsumer<Array<SteamUGCDetails>, SteamResult>> detailHandlers = new ObjectMap<>();
|
||||||
private Array<Consumer<SteamPublishedFileID>> itemHandlers = new Array<>();
|
private Array<Consumer<SteamPublishedFileID>> itemHandlers = new Array<>();
|
||||||
|
private ObjectMap<SteamPublishedFileID, Runnable> updatedHandlers = new ObjectMap<>();
|
||||||
|
|
||||||
public SWorkshop(){
|
public SWorkshop(){
|
||||||
int items = ugc.getNumSubscribedItems();
|
int items = ugc.getNumSubscribedItems();
|
||||||
@@ -39,88 +37,56 @@ public class SWorkshop implements SteamUGCCallback{
|
|||||||
return new FileHandle(info.getFolder());
|
return new FileHandle(info.getFolder());
|
||||||
}).select(f -> f != null && f.list().length > 0);
|
}).select(f -> f != null && f.list().length > 0);
|
||||||
|
|
||||||
mapFiles = folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0]);
|
workshopFiles.put(Map.class, folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(mapExtension)).map(f -> f.list()[0]));
|
||||||
schematicFiles = folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(schematicExtension)).map(f -> f.list()[0]);
|
workshopFiles.put(Schematic.class, folders.select(f -> f.list().length == 1 && f.list()[0].extension().equals(schematicExtension)).map(f -> f.list()[0]));
|
||||||
modFiles = folders.select(f -> f.child("mod.json").exists());
|
workshopFiles.put(LoadedMod.class, folders.select(f -> f.child("mod.json").exists()));
|
||||||
|
|
||||||
if(!mapFiles.isEmpty()){
|
if(!workshopFiles.get(Map.class).isEmpty()){
|
||||||
SAchievement.downloadMapWorkshop.complete();
|
SAchievement.downloadMapWorkshop.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.info("Fetching {0} subscribed maps.", mapFiles.size);
|
workshopFiles.each((type, list) -> {
|
||||||
Log.info("Fetching {0} subscribed mods.", modFiles.size);
|
Log.info("Fetched content ({0}): {1}", type.getSimpleName(), list.size);
|
||||||
}
|
|
||||||
|
|
||||||
public Array<FileHandle> getMapFiles(){
|
|
||||||
return mapFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Array<FileHandle> getModFiles(){
|
|
||||||
return modFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Array<FileHandle> getSchematicFiles(){
|
|
||||||
return schematicFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishMap(Map map){
|
|
||||||
if(map.tags.containsKey("steamid")){
|
|
||||||
Log.info("Map already published, redirecting to ID.");
|
|
||||||
SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + map.tags.get("steamid"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//update author name when publishing
|
|
||||||
map.tags.put("author", SVars.net.friends.getPersonaName());
|
|
||||||
ui.editor.editor.getTags().put("author", map.tags.get("author"));
|
|
||||||
ui.editor.save();
|
|
||||||
|
|
||||||
showPublish(id -> updateMap(map, id, "<Map Created>"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishSchematic(Schematic schematic){
|
|
||||||
|
|
||||||
showPublish(id -> {
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void publishMod(LoadedMod mod){
|
public Array<FileHandle> getWorkshopFiles(Class<? extends Publishable> type){
|
||||||
|
return workshopFiles.getOr(type, () -> new Array<>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showPublish(Consumer<SteamPublishedFileID> published){
|
/** Publish a new item and submit an update for it.
|
||||||
FloatingDialog dialog = new FloatingDialog("$confirm");
|
* If it is already published, redirects to its page.*/
|
||||||
dialog.setFillParent(false);
|
public void publish(Publishable p){
|
||||||
dialog.cont.add("$publish.confirm").width(600f).wrap();
|
if(p.hasSteamID()){
|
||||||
dialog.addCloseButton();
|
Log.info("Content already published, redirecting to ID.");
|
||||||
dialog.buttons.addImageTextButton("$eula", Icon.linkSmall, () -> {
|
viewListing(p);
|
||||||
SVars.net.friends.activateGameOverlayToWebPage("https://steamcommunity.com/sharedfiles/workshoplegalagreement");
|
return;
|
||||||
}).size(210f, 64f);
|
}
|
||||||
|
|
||||||
dialog.buttons.addImageTextButton("$ok", Icon.checkSmall, () -> {
|
if(!p.prePublish()){
|
||||||
ugc.createItem(SVars.steamID, WorkshopFileType.Community);
|
return;
|
||||||
ui.loadfrag.show("$publishing");
|
}
|
||||||
dialog.hide();
|
|
||||||
itemHandlers.add(published);
|
showPublish(id -> update(p, id, null));
|
||||||
}).size(170f, 64f);
|
|
||||||
dialog.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void viewMapListingInfo(Map map){
|
/** Update an existing item with a changelog. */
|
||||||
String id = map.tags.get("steamid");
|
public void updateItem(Publishable p, String changelog){
|
||||||
|
String id = p.getSteamID();
|
||||||
long handle = Strings.parseLong(id, -1);
|
long handle = Strings.parseLong(id, -1);
|
||||||
SteamPublishedFileID fid = new SteamPublishedFileID(handle);
|
SteamPublishedFileID fid = new SteamPublishedFileID(handle);
|
||||||
|
update(p, fid, changelog);
|
||||||
|
}
|
||||||
|
|
||||||
Log.info("Requesting map listing view; id = " + id);
|
/** Fetches info for an item, checking to make sure that it exists.*/
|
||||||
|
public void viewListing(Publishable p){
|
||||||
|
long handle = Strings.parseLong(p.getSteamID(), -1);
|
||||||
|
SteamPublishedFileID id = new SteamPublishedFileID(handle);
|
||||||
|
|
||||||
ui.loadfrag.show();
|
ui.loadfrag.show();
|
||||||
query(ugc.createQueryUGCDetailsRequest(fid), (detailsList, result) -> {
|
query(ugc.createQueryUGCDetailsRequest(id), (detailsList, result) -> {
|
||||||
ui.loadfrag.hide();
|
ui.loadfrag.hide();
|
||||||
|
|
||||||
Log.info("Map listing result: " + result + " " + detailsList);
|
|
||||||
|
|
||||||
if(result == SteamResult.OK){
|
if(result == SteamResult.OK){
|
||||||
SteamUGCDetails details = detailsList.first();
|
SteamUGCDetails details = detailsList.first();
|
||||||
if(details.getResult() == SteamResult.OK){
|
if(details.getResult() == SteamResult.OK){
|
||||||
@@ -132,57 +98,114 @@ public class SWorkshop implements SteamUGCCallback{
|
|||||||
dialog.addCloseButton();
|
dialog.addCloseButton();
|
||||||
|
|
||||||
dialog.buttons.addImageTextButton("$view.workshop", Icon.linkSmall, () -> {
|
dialog.buttons.addImageTextButton("$view.workshop", Icon.linkSmall, () -> {
|
||||||
platform.viewListing(id);
|
viewListingID(id);
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
}).size(210f, 64f);
|
}).size(210f, 64f);
|
||||||
|
|
||||||
dialog.buttons.addImageTextButton("$map.update", Icon.upgradeSmall, () -> {
|
dialog.buttons.addImageTextButton("$workshop.update", Icon.upgradeSmall, () -> {
|
||||||
new FloatingDialog("$map.update"){{
|
new FloatingDialog("$workshop.update"){{
|
||||||
setFillParent(false);
|
setFillParent(false);
|
||||||
cont.margin(10).add("$map.changelog").padRight(6f);
|
cont.margin(10).add("$changelog").padRight(6f);
|
||||||
cont.row();
|
cont.row();
|
||||||
TextArea field = cont.addArea("", t -> {}).size(500f, 160f).get();
|
TextArea field = cont.addArea("", t -> {}).size(500f, 160f).get();
|
||||||
field.setMaxLength(400);
|
field.setMaxLength(400);
|
||||||
buttons.defaults().size(120, 54).pad(4);
|
buttons.defaults().size(120, 54).pad(4);
|
||||||
buttons.addButton("$ok", () -> {
|
buttons.addButton("$ok", () -> {
|
||||||
ui.loadfrag.show("publishing");
|
ui.loadfrag.show("$publishing");
|
||||||
updateMap(map, details.getPublishedFileID(), field.getText().replace("\r", "\n"));
|
updateItem(p, field.getText().replace("\r", "\n"));
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
hide();
|
hide();
|
||||||
|
|
||||||
Log.info("Update map " + map.name());
|
|
||||||
});
|
});
|
||||||
buttons.addButton("$cancel", this::hide);
|
buttons.addButton("$cancel", this::hide);
|
||||||
}}.show();
|
}}.show();
|
||||||
|
|
||||||
}).size(210f, 64f);
|
}).size(210f, 64f);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + SteamNativeHandle.getNativeHandle(details.getPublishedFileID()));
|
SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + SteamNativeHandle.getNativeHandle(details.getPublishedFileID()));
|
||||||
}
|
}
|
||||||
}else if(details.getResult() == SteamResult.FileNotFound){
|
}else if(details.getResult() == SteamResult.FileNotFound){
|
||||||
//force-remove tags
|
p.removeSteamID();
|
||||||
ui.editor.editor.getTags().remove("steamid");
|
ui.showErrorMessage("$missing");
|
||||||
map.tags.remove("steamid");
|
|
||||||
ui.editor.save();
|
|
||||||
|
|
||||||
ui.showErrorMessage("$map.missing");
|
|
||||||
}else{
|
}else{
|
||||||
ui.showErrorMessage(Core.bundle.format("map.load.error", result.name()));
|
ui.showErrorMessage(Core.bundle.format("workshop.error", result.name()));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showErrorMessage(Core.bundle.format("map.load.error", result.name()));
|
ui.showErrorMessage(Core.bundle.format("workshop.error", result.name()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void query(SteamUGCQuery query, BiConsumer<Array<SteamUGCDetails>, SteamResult> handler){
|
void viewListingID(SteamPublishedFileID id){
|
||||||
Log.info("POST " + query);
|
SVars.net.friends.activateGameOverlayToWebPage("steam://url/CommunityFilePage/" + SteamNativeHandle.getNativeHandle(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(Publishable p, SteamPublishedFileID id, String changelog){
|
||||||
|
String sid = SteamNativeHandle.getNativeHandle(id) + "";
|
||||||
|
|
||||||
|
updateItem(id, h -> {
|
||||||
|
if(p.steamDescription() != null){
|
||||||
|
ugc.setItemDescription(h, p.steamDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<String> tags = p.extraTags();
|
||||||
|
tags.add(p.steamTag());
|
||||||
|
|
||||||
|
ugc.setItemTitle(h, p.steamTitle());
|
||||||
|
ugc.setItemTags(h, tags.toArray(String.class));
|
||||||
|
ugc.setItemPreview(h, p.createSteamPreview(sid).absolutePath());
|
||||||
|
ugc.setItemContent(h, p.createSteamFolder(sid).absolutePath());
|
||||||
|
if(changelog == null){
|
||||||
|
ugc.setItemVisibility(h, PublishedFileVisibility.Private);
|
||||||
|
}
|
||||||
|
ugc.submitItemUpdate(h, changelog == null ? "<Created>" : changelog);
|
||||||
|
}, () -> p.addSteamID(sid));
|
||||||
|
}
|
||||||
|
|
||||||
|
void showPublish(Consumer<SteamPublishedFileID> published){
|
||||||
|
FloatingDialog dialog = new FloatingDialog("$confirm");
|
||||||
|
dialog.setFillParent(false);
|
||||||
|
dialog.cont.add("$publish.confirm").width(600f).wrap();
|
||||||
|
dialog.addCloseButton();
|
||||||
|
dialog.buttons.addImageTextButton("$eula", Icon.linkSmall,
|
||||||
|
() -> SVars.net.friends.activateGameOverlayToWebPage("https://steamcommunity.com/sharedfiles/workshoplegalagreement"))
|
||||||
|
.size(210f, 64f);
|
||||||
|
|
||||||
|
dialog.buttons.addImageTextButton("$ok", Icon.checkSmall, () -> {
|
||||||
|
ugc.createItem(SVars.steamID, WorkshopFileType.Community);
|
||||||
|
ui.loadfrag.show("$publishing");
|
||||||
|
dialog.hide();
|
||||||
|
itemHandlers.add(published);
|
||||||
|
}).size(170f, 64f);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void query(SteamUGCQuery query, BiConsumer<Array<SteamUGCDetails>, SteamResult> handler){
|
||||||
|
Log.info("POST QUERY " + query);
|
||||||
detailHandlers.put(query, handler);
|
detailHandlers.put(query, handler);
|
||||||
ugc.sendQueryUGCRequest(query);
|
ugc.sendQueryUGCRequest(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateItem(SteamPublishedFileID publishedFileID, Consumer<SteamUGCUpdateHandle> tagger, Runnable updated){
|
||||||
|
SteamUGCUpdateHandle h = ugc.startItemUpdate(SVars.steamID, publishedFileID);
|
||||||
|
|
||||||
|
tagger.accept(h);
|
||||||
|
|
||||||
|
ItemUpdateInfo info = new ItemUpdateInfo();
|
||||||
|
|
||||||
|
ui.loadfrag.setProgress(() -> {
|
||||||
|
ItemUpdateStatus status = ugc.getItemUpdateProgress(h, info);
|
||||||
|
ui.loadfrag.setText("$" + status.name().toLowerCase());
|
||||||
|
if(status == ItemUpdateStatus.Invalid){
|
||||||
|
ui.loadfrag.setText("$done");
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
return (float)status.ordinal() / (float)ItemUpdateStatus.values().length;
|
||||||
|
});
|
||||||
|
|
||||||
|
updatedHandlers.put(publishedFileID, updated);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestUGCDetails(SteamUGCDetails details, SteamResult result){
|
public void onRequestUGCDetails(SteamUGCDetails details, SteamResult result){
|
||||||
|
|
||||||
@@ -190,7 +213,7 @@ public class SWorkshop implements SteamUGCCallback{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUGCQueryCompleted(SteamUGCQuery query, int numResultsReturned, int totalMatchingResults, boolean isCachedData, SteamResult result){
|
public void onUGCQueryCompleted(SteamUGCQuery query, int numResultsReturned, int totalMatchingResults, boolean isCachedData, SteamResult result){
|
||||||
Log.info("GET " + query);
|
Log.info("GET QUERY " + query);
|
||||||
|
|
||||||
if(detailHandlers.containsKey(query)){
|
if(detailHandlers.containsKey(query)){
|
||||||
if(numResultsReturned > 0){
|
if(numResultsReturned > 0){
|
||||||
@@ -236,38 +259,6 @@ public class SWorkshop implements SteamUGCCallback{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateMap(Map map, SteamPublishedFileID publishedFileID, String changelog){
|
|
||||||
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("map.msav");
|
|
||||||
map.file.copyTo(mapFile);
|
|
||||||
|
|
||||||
Log.info(mapFile.parent().absolutePath());
|
|
||||||
Log.info(map.previewFile().absolutePath());
|
|
||||||
|
|
||||||
ugc.setItemTitle(h, map.name());
|
|
||||||
ugc.setItemDescription(h, map.description());
|
|
||||||
ugc.setItemTags(h, new String[]{"map", mode.name()});
|
|
||||||
ugc.setItemVisibility(h, PublishedFileVisibility.Private);
|
|
||||||
ugc.setItemPreview(h, map.previewFile().absolutePath());
|
|
||||||
ugc.setItemContent(h, mapFile.parent().absolutePath());
|
|
||||||
ugc.addItemKeyValueTag(h, "mode", mode.name());
|
|
||||||
ugc.submitItemUpdate(h, changelog);
|
|
||||||
|
|
||||||
ItemUpdateInfo info = new ItemUpdateInfo();
|
|
||||||
|
|
||||||
ui.loadfrag.setProgress(() -> {
|
|
||||||
ItemUpdateStatus status = ugc.getItemUpdateProgress(h, info);
|
|
||||||
ui.loadfrag.setText("$" + status.name().toLowerCase());
|
|
||||||
if(status == ItemUpdateStatus.Invalid){
|
|
||||||
ui.loadfrag.setText("$done");
|
|
||||||
return 1f;
|
|
||||||
}
|
|
||||||
return (float)status.ordinal() / (float)ItemUpdateStatus.values().length;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSubmitItemUpdate(SteamPublishedFileID publishedFileID, boolean needsToAcceptWLA, SteamResult result){
|
public void onSubmitItemUpdate(SteamPublishedFileID publishedFileID, boolean needsToAcceptWLA, SteamResult result){
|
||||||
ui.loadfrag.hide();
|
ui.loadfrag.hide();
|
||||||
@@ -278,13 +269,10 @@ public class SWorkshop implements SteamUGCCallback{
|
|||||||
if(needsToAcceptWLA){
|
if(needsToAcceptWLA){
|
||||||
SVars.net.friends.activateGameOverlayToWebPage("https://steamcommunity.com/sharedfiles/workshoplegalagreement");
|
SVars.net.friends.activateGameOverlayToWebPage("https://steamcommunity.com/sharedfiles/workshoplegalagreement");
|
||||||
}
|
}
|
||||||
ui.editor.editor.getTags().put("steamid", SteamNativeHandle.getNativeHandle(publishedFileID) + "");
|
|
||||||
try{
|
if(updatedHandlers.containsKey(publishedFileID)){
|
||||||
ui.editor.save();
|
updatedHandlers.get(publishedFileID).run();
|
||||||
}catch(Exception e){
|
|
||||||
Log.err(e);
|
|
||||||
}
|
}
|
||||||
Events.fire(new MapPublishEvent());
|
|
||||||
}else{
|
}else{
|
||||||
ui.showErrorMessage(Core.bundle.format("publish.error ", result.name()));
|
ui.showErrorMessage(Core.bundle.format("publish.error ", result.name()));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user