Merge branch 'master' into feature-blocklogsandrollback
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
package io.anuke.mindustry;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Pixmap.Filter;
|
||||
import com.badlogic.gdx.graphics.PixmapIO;
|
||||
import io.anuke.mindustry.core.*;
|
||||
import io.anuke.mindustry.io.BlockLoader;
|
||||
import io.anuke.mindustry.io.BundleLoader;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.ucore.modules.ModuleCore;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.effect.Shield;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.net.EditLog;
|
||||
import io.anuke.mindustry.net.ClientDebug;
|
||||
import io.anuke.mindustry.net.ServerDebug;
|
||||
@@ -21,6 +21,7 @@ import io.anuke.ucore.entities.EffectEntity;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.OS;
|
||||
import java.util.Locale;
|
||||
|
||||
public class Vars{
|
||||
@@ -51,12 +52,17 @@ public class Vars{
|
||||
public static final String discordURL = "https://discord.gg/BKADYds";
|
||||
|
||||
public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases";
|
||||
public static final String macAppDir = UCore.getProperty("user.home") + "/Library/Application Support/";
|
||||
//directory for user-created map data
|
||||
public static final FileHandle customMapDirectory = gwt ? null : UCore.isAssets() ?
|
||||
Gdx.files.local("../../desktop/mindustry-maps") : Gdx.files.local("mindustry-maps/");
|
||||
Gdx.files.local("../../desktop/mindustry-maps") :
|
||||
OS.isMac ? (Gdx.files.absolute(macAppDir).child("maps/")) :
|
||||
Gdx.files.local("mindustry-maps/");
|
||||
//save file directory
|
||||
public static final FileHandle saveDirectory = gwt ? null : UCore.isAssets() ?
|
||||
Gdx.files.local("../../desktop/mindustry-saves") : Gdx.files.local("mindustry-saves/");
|
||||
Gdx.files.local("../../desktop/mindustry-saves") :
|
||||
OS.isMac ? (Gdx.files.absolute(macAppDir).child("saves/")) :
|
||||
Gdx.files.local("mindustry-saves/");
|
||||
//scale of the font
|
||||
public static float fontscale = Math.max(Unit.dp.scl(1f)/2f, 0.5f);
|
||||
//camera zoom displayed on startup
|
||||
@@ -99,7 +105,7 @@ public class Vars{
|
||||
|
||||
public static final int tilesize = 8;
|
||||
|
||||
public static final Locale[] locales = {new Locale("en"), new Locale("fr"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl", "PL"),
|
||||
public static final Locale[] locales = {new Locale("en"), new Locale("fr"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl"),
|
||||
new Locale("de"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID"), new Locale("ita"), new Locale("es")};
|
||||
|
||||
public static final Color[] playerColors = {
|
||||
|
||||
@@ -13,7 +13,6 @@ import io.anuke.mindustry.input.AndroidInput;
|
||||
import io.anuke.mindustry.input.DefaultKeybinds;
|
||||
import io.anuke.mindustry.input.DesktopInput;
|
||||
import io.anuke.mindustry.input.InputHandler;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.io.Saves;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.resource.Item;
|
||||
@@ -25,7 +24,9 @@ import io.anuke.ucore.core.Inputs.DeviceType;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Atlas;
|
||||
import io.anuke.ucore.util.InputProxy;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
@@ -102,7 +103,7 @@ public class Control extends Module{
|
||||
|
||||
Sounds.setFalloff(9000f);
|
||||
|
||||
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3");
|
||||
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3", "5.mp3", "6.mp3");
|
||||
|
||||
DefaultKeybinds.load();
|
||||
|
||||
@@ -385,7 +386,7 @@ public class Control extends Module{
|
||||
|
||||
if(respawntime > 0){
|
||||
|
||||
respawntime -= delta();
|
||||
respawntime -= Timers.delta();
|
||||
|
||||
if(respawntime <= 0){
|
||||
player.set(world.getSpawnX(), world.getSpawnY());
|
||||
|
||||
@@ -11,7 +11,6 @@ import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.Net.SendMode;
|
||||
import io.anuke.mindustry.net.NetworkIO;
|
||||
|
||||
@@ -5,7 +5,6 @@ import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.game.EventType.GameOverEvent;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.io.Version;
|
||||
import io.anuke.mindustry.net.*;
|
||||
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package io.anuke.mindustry.io;
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.Base64Coder;
|
||||
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
import io.anuke.ucore.scene.ui.TextField;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -12,26 +14,40 @@ import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class Platform {
|
||||
/**Each separate game platform should set this instance to their own implementation.*/
|
||||
public static Platform instance = new Platform() {};
|
||||
|
||||
/**Format the date using the default date formatter.*/
|
||||
public String format(Date date){return "invalid";}
|
||||
/**Format a number by adding in commas or periods where needed.*/
|
||||
public String format(int number){return "invalid";}
|
||||
/**Show a native error dialog.*/
|
||||
public void showError(String text){}
|
||||
/**Add a text input dialog that should show up after the field is tapped.*/
|
||||
public void addDialog(TextField field){
|
||||
addDialog(field, 16);
|
||||
}
|
||||
/**See addDialog().*/
|
||||
public void addDialog(TextField field, int maxLength){}
|
||||
/**Update discord RPC.*/
|
||||
public void updateRPC(){}
|
||||
/**Called when the game is exited.*/
|
||||
public void onGameExit(){}
|
||||
/**Open donation dialog. Currently android only.*/
|
||||
public void openDonations(){}
|
||||
/**Whether discord RPC is supported.*/
|
||||
public boolean hasDiscord(){return true;}
|
||||
/**Request Android permissions for writing files.*/
|
||||
public void requestWritePerms(){}
|
||||
/**Return the localized name for the locale. This is basically a workaround for GWT not supporting getName().*/
|
||||
public String getLocaleName(Locale locale){
|
||||
return locale.toString();
|
||||
}
|
||||
/**Whether joining games is supported.*/
|
||||
public boolean canJoinGame(){
|
||||
return true;
|
||||
}
|
||||
/**Whether debug mode is enabled.*/
|
||||
public boolean isDebug(){return false;}
|
||||
/**Must be 8 bytes in length.*/
|
||||
public byte[] getUUID(){
|
||||
@@ -46,6 +62,19 @@ public abstract class Platform {
|
||||
}
|
||||
return Base64Coder.decode(uuid);
|
||||
}
|
||||
/**Only used for iOS or android: open the share menu for a map or save.*/
|
||||
public void shareFile(FileHandle file){}
|
||||
|
||||
/**Show a file chooser. Desktop only.
|
||||
*
|
||||
* @param text File chooser title text
|
||||
* @param content Type of files to be loaded
|
||||
* @param cons Selection listener
|
||||
* @param open Whether to open or save files.
|
||||
* @param filetype File extensions to filter.
|
||||
*/
|
||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){}
|
||||
/**Use the default thread provider from the kryonet module for this.*/
|
||||
public ThreadProvider getThreadProvider(){
|
||||
return new ThreadProvider() {
|
||||
@Override public boolean isOnThread() {return true;}
|
||||
@@ -7,7 +7,6 @@ import com.badlogic.gdx.graphics.Colors;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.mapeditor.MapEditorDialog;
|
||||
import io.anuke.mindustry.ui.dialogs.*;
|
||||
import io.anuke.mindustry.ui.fragments.*;
|
||||
|
||||
@@ -46,9 +46,9 @@ public class GestureHandler extends GestureAdapter{
|
||||
public boolean pan(float x, float y, float deltaX, float deltaY){
|
||||
if(control.showCursor() && !Inputs.keyDown("select")) return false;
|
||||
|
||||
if(!control.showCursor() && !(control.input().recipe != null
|
||||
if((!control.showCursor() && !(control.input().recipe != null
|
||||
&& control.input().placeMode.lockCamera && state.inventory.hasItems(control.input().recipe.requirements)) &&
|
||||
!(control.input().recipe == null && control.input().breakMode.lockCamera)){
|
||||
!(control.input().recipe == null && control.input().breakMode.lockCamera)) && !ui.hasMouse(x, y)){
|
||||
float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale;
|
||||
player.x -= dx;
|
||||
player.y += dy;
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.anuke.mindustry.io;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.I18NBundle;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.world.Map;
|
||||
|
||||
@@ -86,7 +86,7 @@ public class Saves {
|
||||
current = slot;
|
||||
}
|
||||
|
||||
public void importSave(FileHandle file) throws IOException{
|
||||
public SaveSlot importSave(FileHandle file) throws IOException{
|
||||
SaveSlot slot = new SaveSlot(nextSlot);
|
||||
slot.importFile(file);
|
||||
nextSlot ++;
|
||||
@@ -94,6 +94,7 @@ public class Saves {
|
||||
saves.add(slot);
|
||||
slot.meta = SaveIO.getData(slot.index);
|
||||
current = slot;
|
||||
return slot;
|
||||
}
|
||||
|
||||
public Array<SaveSlot> getSaveSlots(){
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package io.anuke.mindustry.mapeditor;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.ColorMapper;
|
||||
import io.anuke.mindustry.world.ColorMapper.BlockPair;
|
||||
@@ -42,7 +42,6 @@ public class MapEditorDialog extends Dialog{
|
||||
private MapSaveDialog saveDialog;
|
||||
private MapResizeDialog resizeDialog;
|
||||
private ScrollPane pane;
|
||||
private FileChooser openFile, saveFile;
|
||||
private boolean saved = false;
|
||||
|
||||
private ButtonGroup<ImageButton> blockgroup;
|
||||
@@ -55,42 +54,6 @@ public class MapEditorDialog extends Dialog{
|
||||
dialog = new MapGenerateDialog(editor);
|
||||
view = new MapView(editor);
|
||||
|
||||
openFile = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
|
||||
ui.loadfrag.show();
|
||||
Timers.run(3f, () -> {
|
||||
try{
|
||||
Pixmap pixmap = new Pixmap(file);
|
||||
if(verifySize(pixmap)){
|
||||
editor.setPixmap(pixmap);
|
||||
view.clearStack();
|
||||
}else{
|
||||
ui.showError(Bundles.format("text.editor.badsize", Arrays.toString(MapEditor.validMapSizes)));
|
||||
}
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
});
|
||||
});
|
||||
|
||||
saveFile = new FileChooser("$saveimage", false, file -> {
|
||||
if(!file.extension().toLowerCase().equals(".png")){
|
||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||
}
|
||||
FileHandle result = file;
|
||||
ui.loadfrag.show();
|
||||
Timers.run(3f, () -> {
|
||||
try{
|
||||
Pixmaps.write(editor.pixmap(), result);
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||
if(!mobile) Log.err(e);
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
});
|
||||
});
|
||||
|
||||
loadDialog = new MapLoadDialog(map -> {
|
||||
saveDialog.setFieldText(map.name);
|
||||
ui.loadfrag.show();
|
||||
@@ -237,16 +200,46 @@ public class MapEditorDialog extends Dialog{
|
||||
).text("$text.editor.savemap");
|
||||
|
||||
row();
|
||||
|
||||
//iOS does not support loading raw files.
|
||||
if(!ios) {
|
||||
|
||||
new imagebutton("icon-load-image", isize, () -> {
|
||||
Platform.instance.showFileChooser(Bundles.get("text.loadimage"), "Image Files", MapEditorDialog.this::tryLoadMap, true, "png");
|
||||
}).text("$text.editor.loadimage");
|
||||
|
||||
row();
|
||||
}
|
||||
|
||||
new imagebutton("icon-load-image", isize, () ->
|
||||
openFile.show()
|
||||
).text("$text.editor.loadimage");
|
||||
|
||||
row();
|
||||
|
||||
new imagebutton("icon-save-image", isize, () ->
|
||||
saveFile.show()
|
||||
).text("$text.editor.saveimage");
|
||||
new imagebutton("icon-save-image", isize, () -> {
|
||||
//iOS doesn't really support saving raw files. Sharing is used instead.
|
||||
if(!ios){
|
||||
Platform.instance.showFileChooser(Bundles.get("text.saveimage"), "Image Files", file -> {
|
||||
if(!file.extension().toLowerCase().equals(".png")){
|
||||
file = file.parent().child(file.nameWithoutExtension() + ".png");
|
||||
}
|
||||
FileHandle result = file;
|
||||
ui.loadfrag.show();
|
||||
Timers.run(3f, () -> {
|
||||
try{
|
||||
Pixmaps.write(editor.pixmap(), result);
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||
if(!mobile) Log.err(e);
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
});
|
||||
}, false, "png");
|
||||
}else{
|
||||
try{
|
||||
FileHandle file = Gdx.files.local(("map-" + ((editor.getMap().name == null) ? "unknown" : editor.getMap().name) + ".png"));
|
||||
Pixmaps.write(editor.pixmap(), file);
|
||||
Platform.instance.shareFile(file);
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
|
||||
}
|
||||
}
|
||||
}).text("$text.editor.saveimage");
|
||||
|
||||
row();
|
||||
|
||||
@@ -329,6 +322,25 @@ public class MapEditorDialog extends Dialog{
|
||||
}}.grow().end();
|
||||
}
|
||||
|
||||
public void tryLoadMap(FileHandle file){
|
||||
ui.loadfrag.show();
|
||||
Timers.runTask(3f, () -> {
|
||||
try{
|
||||
Pixmap pixmap = new Pixmap(file);
|
||||
if(verifySize(pixmap)){
|
||||
editor.setPixmap(pixmap);
|
||||
view.clearStack();
|
||||
}else{
|
||||
ui.showError(Bundles.format("text.editor.badsize", Arrays.toString(MapEditor.validMapSizes)));
|
||||
}
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
|
||||
Log.err(e);
|
||||
}
|
||||
ui.loadfrag.hide();
|
||||
});
|
||||
}
|
||||
|
||||
private void doInput(){
|
||||
//tool select
|
||||
for(int i = 0; i < EditorTool.values().length; i ++){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.anuke.mindustry.mapeditor;
|
||||
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.mindustry.world.Map;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.net.Packet.ImportantPacket;
|
||||
import io.anuke.mindustry.net.Packet.UnimportantPacket;
|
||||
import io.anuke.mindustry.net.Streamable.StreamBegin;
|
||||
|
||||
@@ -2,16 +2,20 @@ package io.anuke.mindustry.ui.dialogs;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import io.anuke.mindustry.ui.Links;
|
||||
import io.anuke.mindustry.ui.Links.LinkEntry;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.OS;
|
||||
|
||||
import static io.anuke.mindustry.Vars.ios;
|
||||
import static io.anuke.mindustry.Vars.ui;
|
||||
|
||||
public class AboutDialog extends FloatingDialog {
|
||||
private static ObjectSet<String> bannedItems = ObjectSet.with("google-play", "itch.io", "dev-builds", "trello");
|
||||
|
||||
public AboutDialog(){
|
||||
super("$text.about.button");
|
||||
@@ -25,6 +29,10 @@ public class AboutDialog extends FloatingDialog {
|
||||
ScrollPane pane = new ScrollPane(in, "clear");
|
||||
|
||||
for(LinkEntry link : Links.getLinks()){
|
||||
if((ios || OS.isMac) && bannedItems.contains(link.name)){ //because Apple doesn't like me mentioning things
|
||||
continue;
|
||||
}
|
||||
|
||||
Table table = new Table("button");
|
||||
table.margin(0);
|
||||
table.table(img -> {
|
||||
@@ -59,10 +67,14 @@ public class AboutDialog extends FloatingDialog {
|
||||
content().add(pane).growX();
|
||||
|
||||
buttons().addButton("$text.credits", this::showCredits).size(200f, 64f);
|
||||
buttons().addButton("$text.changelog.title", ui.changelog::show).size(200f, 64f);
|
||||
|
||||
if(!ios && !OS.isMac){
|
||||
buttons().addButton("$text.changelog.title", ui.changelog::show).size(200f, 64f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void showCredits(){
|
||||
public void showCredits(){
|
||||
FloatingDialog dialog = new FloatingDialog("$text.credits");
|
||||
dialog.addCloseButton();
|
||||
dialog.content().add("$text.about");
|
||||
|
||||
@@ -10,6 +10,9 @@ import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Log;
|
||||
import io.anuke.ucore.util.OS;
|
||||
|
||||
import static io.anuke.mindustry.Vars.ios;
|
||||
|
||||
public class ChangelogDialog extends FloatingDialog{
|
||||
private final float vw = 600;
|
||||
@@ -22,13 +25,15 @@ public class ChangelogDialog extends FloatingDialog{
|
||||
|
||||
content().add("$text.changelog.loading");
|
||||
|
||||
Changelogs.getChangelog(result -> {
|
||||
versions = result;
|
||||
Gdx.app.postRunnable(this::setup);
|
||||
}, t -> {
|
||||
Log.err(t);
|
||||
Gdx.app.postRunnable(this::setup);
|
||||
});
|
||||
if(!ios && !OS.isMac) {
|
||||
Changelogs.getChangelog(result -> {
|
||||
versions = result;
|
||||
Gdx.app.postRunnable(this::setup);
|
||||
}, t -> {
|
||||
Log.err(t);
|
||||
Gdx.app.postRunnable(this::setup);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void setup(){
|
||||
@@ -45,12 +50,16 @@ public class ChangelogDialog extends FloatingDialog{
|
||||
table.add("$text.changelog.error.android").padTop(8);
|
||||
}
|
||||
|
||||
if(Vars.ios){
|
||||
if(ios){
|
||||
table.row();
|
||||
table.add("$text.changelog.error.ios").padTop(8);
|
||||
}
|
||||
}else{
|
||||
for(VersionInfo info : versions){
|
||||
String desc = info.description;
|
||||
|
||||
desc = desc.replace("Android", "Mobile");
|
||||
|
||||
Table in = new Table("clear");
|
||||
in.top().left().margin(10);
|
||||
|
||||
@@ -63,7 +72,7 @@ public class ChangelogDialog extends FloatingDialog{
|
||||
in.add("$text.changelog.latest");
|
||||
}
|
||||
in.row();
|
||||
in.labelWrap("[lightgray]" + info.description).width(vw - 20).padTop(12);
|
||||
in.labelWrap("[lightgray]" + desc).width(vw - 20).padTop(12);
|
||||
|
||||
table.add(in).width(vw).pad(8).row();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Pools;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.ucore.UCore;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
@@ -15,12 +16,14 @@ import io.anuke.ucore.scene.event.Touchable;
|
||||
import io.anuke.ucore.scene.ui.*;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.OS;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class FileChooser extends FloatingDialog {
|
||||
private Table files;
|
||||
private FileHandle homeDirectory = Gdx.files.absolute(Gdx.files.getExternalStoragePath());
|
||||
private FileHandle homeDirectory = Gdx.files.absolute(OS.isMac ? UCore.getProperty("user.home") + "/Downloads/" :
|
||||
Gdx.files.getExternalStoragePath());
|
||||
private FileHandle directory = homeDirectory;
|
||||
private ScrollPane pane;
|
||||
private TextField navigation, filefield;
|
||||
@@ -96,6 +99,11 @@ public class FileChooser extends FloatingDialog {
|
||||
updateFiles(true);
|
||||
});
|
||||
|
||||
//Macs are confined to the Downloads/ directory
|
||||
if(OS.isMac){
|
||||
up.setDisabled(true);
|
||||
}
|
||||
|
||||
ImageButton back = new ImageButton("icon-arrow-left");
|
||||
back.resizeImage(isize);
|
||||
|
||||
@@ -166,7 +174,8 @@ public class FileChooser extends FloatingDialog {
|
||||
|
||||
private void updateFiles(boolean push){
|
||||
if(push) stack.push(directory);
|
||||
navigation.setText(directory.toString());
|
||||
//if is mac, don't display extra info since you can only ever go to downloads
|
||||
navigation.setText(OS.isMac ? directory.name() : directory.toString());
|
||||
|
||||
GlyphLayout layout = Pools.obtain(GlyphLayout.class);
|
||||
|
||||
@@ -181,23 +190,25 @@ public class FileChooser extends FloatingDialog {
|
||||
Pools.free(layout);
|
||||
|
||||
files.clearChildren();
|
||||
files.top().left();
|
||||
FileHandle[] names = getFileNames();
|
||||
|
||||
Image upimage = new Image("icon-folder-parent");
|
||||
//macs are confined to the Downloads/ directory
|
||||
if(!OS.isMac) {
|
||||
Image upimage = new Image("icon-folder-parent");
|
||||
TextButton upbutton = new TextButton(".." + directory.toString());
|
||||
upbutton.clicked(() -> {
|
||||
directory = directory.parent();
|
||||
updateFiles(true);
|
||||
});
|
||||
|
||||
TextButton upbutton = new TextButton(".." + directory.toString());
|
||||
upbutton.clicked(()->{
|
||||
directory = directory.parent();
|
||||
updateFiles(true);
|
||||
});
|
||||
|
||||
upbutton.left().add(upimage).padRight(4f).size(14*2);
|
||||
upbutton.getCells().reverse();
|
||||
|
||||
files.top().left().add(upbutton).align(Align.topLeft).fillX().expandX().height(50).pad(2).colspan(2);
|
||||
upbutton.getLabel().setAlignment(Align.left);
|
||||
upbutton.left().add(upimage).padRight(4f).size(14 * 2);
|
||||
upbutton.getLabel().setAlignment(Align.left);
|
||||
upbutton.getCells().reverse();
|
||||
|
||||
files.row();
|
||||
files.add(upbutton).align(Align.topLeft).fillX().expandX().height(50).pad(2).colspan(2);
|
||||
files.row();
|
||||
}
|
||||
|
||||
ButtonGroup<TextButton> group = new ButtonGroup<TextButton>();
|
||||
group.setMinCheckCount(0);
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.io.Version;
|
||||
import io.anuke.mindustry.net.Host;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.anuke.mindustry.ui.dialogs;
|
||||
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.scene.ui.ButtonGroup;
|
||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package io.anuke.mindustry.ui.dialogs;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.io.SaveIO;
|
||||
import io.anuke.mindustry.io.Saves.SaveSlot;
|
||||
import io.anuke.ucore.core.Core;
|
||||
@@ -83,14 +86,24 @@ public class LoadDialog extends FloatingDialog{
|
||||
|
||||
if(!gwt) {
|
||||
t.addImageButton("icon-save", "empty", 14 * 3, () -> {
|
||||
new FileChooser("$text.save.export", false, file -> {
|
||||
try {
|
||||
slot.exportFile(file);
|
||||
setup();
|
||||
} catch (IOException e) {
|
||||
ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
|
||||
}
|
||||
}).show();
|
||||
if(!ios) {
|
||||
Platform.instance.showFileChooser(Bundles.get("text.save.export"), "Mindustry Save", file -> {
|
||||
try {
|
||||
slot.exportFile(file);
|
||||
setup();
|
||||
} catch (IOException e) {
|
||||
ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
|
||||
}
|
||||
}, false, "mins");
|
||||
}else{
|
||||
try {
|
||||
FileHandle file = Gdx.files.local("save-" + slot.getName() + ".mins");
|
||||
slot.exportFile(file);
|
||||
Platform.instance.shareFile(file);
|
||||
}catch (Exception e){
|
||||
ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
|
||||
}
|
||||
}
|
||||
}).size(14 * 3).right();
|
||||
}
|
||||
|
||||
@@ -134,10 +147,10 @@ public class LoadDialog extends FloatingDialog{
|
||||
|
||||
slots.row();
|
||||
|
||||
if(gwt) return;
|
||||
if(gwt || ios) return;
|
||||
|
||||
slots.addImageTextButton("$text.save.import", "icon-add", "clear", 14*3, () -> {
|
||||
new FileChooser("$text.save.import", f -> f.extension().equals("mins"), true, file -> {
|
||||
Platform.instance.showFileChooser(Bundles.get("text.save.import"), "Mindustry Save", file -> {
|
||||
if(SaveIO.isSaveValid(file)){
|
||||
try{
|
||||
control.getSaves().importSave(file);
|
||||
@@ -148,30 +161,34 @@ public class LoadDialog extends FloatingDialog{
|
||||
}else{
|
||||
ui.showError("$text.save.import.invalid");
|
||||
}
|
||||
}).show();
|
||||
}, true, "mins");
|
||||
}).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4);
|
||||
}
|
||||
|
||||
public void runLoadSave(SaveSlot slot){
|
||||
ui.loadfrag.show();
|
||||
|
||||
Timers.runTask(3f, () -> {
|
||||
ui.loadfrag.hide();
|
||||
hide();
|
||||
try{
|
||||
slot.load();
|
||||
state.set(State.playing);
|
||||
ui.paused.hide();
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
ui.paused.hide();
|
||||
state.set(State.menu);
|
||||
logic.reset();
|
||||
ui.showError("$text.save.corrupted");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void modifyButton(TextButton button, SaveSlot slot){
|
||||
button.clicked(() -> {
|
||||
if(!button.childrenPressed()){
|
||||
ui.loadfrag.show();
|
||||
|
||||
Timers.runTask(3f, () -> {
|
||||
ui.loadfrag.hide();
|
||||
hide();
|
||||
try{
|
||||
slot.load();
|
||||
state.set(State.playing);
|
||||
ui.paused.hide();
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
ui.paused.hide();
|
||||
state.set(State.menu);
|
||||
logic.reset();
|
||||
ui.showError("$text.save.corrupted");
|
||||
}
|
||||
});
|
||||
runLoadSave(slot);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetEvents;
|
||||
import io.anuke.ucore.core.Core;
|
||||
|
||||
@@ -2,13 +2,14 @@ package io.anuke.mindustry.ui.fragments;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.io.Version;
|
||||
import io.anuke.mindustry.ui.MenuButton;
|
||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.ucore.scene.builders.imagebutton;
|
||||
import io.anuke.ucore.scene.builders.label;
|
||||
import io.anuke.ucore.scene.builders.table;
|
||||
import io.anuke.ucore.util.OS;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
@@ -44,7 +45,13 @@ public class MenuFragment implements Fragment{
|
||||
|
||||
add(new MenuButton("icon-info", "$text.about.button", ui.about::show));
|
||||
|
||||
add(new MenuButton("icon-menu", "$text.changelog.title", ui.changelog::show));
|
||||
add(new MenuButton("icon-menu", OS.isMac ? "$text.credits" : "$text.changelog.title", () -> {
|
||||
if(OS.isMac){
|
||||
ui.about.showCredits();
|
||||
}else {
|
||||
ui.changelog.show();
|
||||
}
|
||||
}));
|
||||
|
||||
row();
|
||||
|
||||
@@ -57,7 +64,8 @@ public class MenuFragment implements Fragment{
|
||||
|
||||
}else {
|
||||
new table() {{
|
||||
defaults().size(120f).pad(5);
|
||||
float size = 120f;
|
||||
defaults().size(size).pad(5);
|
||||
float isize = 14f * 4;
|
||||
|
||||
new imagebutton("icon-play-2", isize, ui.levels::show).text("$text.play").padTop(4f);
|
||||
@@ -70,13 +78,21 @@ public class MenuFragment implements Fragment{
|
||||
|
||||
row();
|
||||
|
||||
new imagebutton("icon-editor", isize, ui.editor::show).text("$text.editor").padTop(4f);
|
||||
new table(){{
|
||||
|
||||
new imagebutton("icon-tools", isize, ui.settings::show).text("$text.settings").padTop(4f);
|
||||
defaults().size(size).pad(5);
|
||||
|
||||
new imagebutton("icon-info", isize, ui.about::show).text("$text.about.button").padTop(4f);
|
||||
new imagebutton("icon-editor", isize, ui.editor::show).text("$text.editor").padTop(4f);
|
||||
|
||||
new imagebutton("icon-donate", isize, Platform.instance::openDonations).text("$text.donate").padTop(4f);
|
||||
new imagebutton("icon-tools", isize, ui.settings::show).text("$text.settings").padTop(4f);
|
||||
|
||||
new imagebutton("icon-info", isize, ui.about::show).text("$text.about.button").padTop(4f);
|
||||
|
||||
if (!ios) {
|
||||
new imagebutton("icon-donate", isize, Platform.instance::openDonations).text("$text.donate").padTop(4f);
|
||||
}
|
||||
|
||||
}}.colspan(4).end();
|
||||
}}.end();
|
||||
}
|
||||
}}.end();
|
||||
|
||||
@@ -33,6 +33,7 @@ public class PlayerListFragment implements Fragment{
|
||||
public void build(){
|
||||
new table(){{
|
||||
new table("pane"){{
|
||||
touchable(Touchable.enabled);
|
||||
margin(14f);
|
||||
new label(() -> Bundles.format(playerGroup.size() == 1 ? "text.players.single" :
|
||||
"text.players", playerGroup.size()));
|
||||
|
||||
Reference in New Issue
Block a user