Finished most of new save system, added new localized strings

This commit is contained in:
Anuken
2017-12-29 15:54:59 -05:00
parent 6774ea67ce
commit 036a246769
37 changed files with 681 additions and 379 deletions

View File

@@ -86,7 +86,7 @@ _(not necessarily planned!)_
- Spawn points changed into enemy bases with hostile turrets - Spawn points changed into enemy bases with hostile turrets
- Unit production - Unit production
### Optmiziation ### Optimization
- Look into uses for `IntMap` - Look into uses for `IntMap`
- Spread updating over multiple frames for large groups of specific tile entities (?) - Spread updating over multiple frames for large groups of specific tile entities (?)
- Optimize enemy + bullet code and check quadtree leaf parameters - Optimize enemy + bullet code and check quadtree leaf parameters

View File

@@ -1,5 +1,6 @@
package io.anuke.mindustry; package io.anuke.mindustry;
import java.text.DateFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@@ -21,7 +22,6 @@ import io.anuke.ucore.scene.ui.layout.Unit;
public class AndroidLauncher extends AndroidApplication{ public class AndroidLauncher extends AndroidApplication{
boolean doubleScaleTablets = true; boolean doubleScaleTablets = true;
@SuppressLint("SimpleDateFormat")
@Override @Override
protected void onCreate(Bundle savedInstanceState){ protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -30,7 +30,7 @@ public class AndroidLauncher extends AndroidApplication{
Mindustry.hasDiscord = isPackageInstalled("com.discord"); Mindustry.hasDiscord = isPackageInstalled("com.discord");
Mindustry.platforms = new PlatformFunction(){ Mindustry.platforms = new PlatformFunction(){
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm"); DateFormat format = SimpleDateFormat.getDateTimeInstance();
@Override @Override
public String format(Date date){ public String format(Date date){

View File

@@ -9,8 +9,8 @@ import io.anuke.mindustry.AndroidTextFieldDialog.TextPromptListener;
import io.anuke.ucore.scene.event.InputEvent; import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.InputListener; import io.anuke.ucore.scene.event.InputListener;
import io.anuke.ucore.scene.ui.TextField; import io.anuke.ucore.scene.ui.TextField;
import io.anuke.ucore.scene.utils.ChangeListener; import io.anuke.ucore.scene.event.ChangeListener;
import io.anuke.ucore.scene.utils.ClickListener; import io.anuke.ucore.scene.event.ClickListener;
public class TextFieldDialogListener extends ClickListener{ public class TextFieldDialogListener extends ClickListener{
private TextField field; private TextField field;

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

View File

@@ -11,14 +11,31 @@ text.level.mode=Gamemode:
text.savegame=Save Game text.savegame=Save Game
text.loadgame=Load Game text.loadgame=Load Game
text.quit=Quit text.quit=Quit
text.tutorial.back=< Prev
text.tutorial.next=Next >
text.save.new=New Save
text.save.overwrite=Are you sure you want to overwrite\nthis save slot? text.save.overwrite=Are you sure you want to overwrite\nthis save slot?
text.overwrite=Overwrite text.overwrite=Overwrite
text.saveload=[accent]Saving... text.saveload=[accent]Saving...
text.savefail=Failed to save game! text.savefail=Failed to save game!
text.selectslot=Select a save slot. text.save.delete.confirm=Are you sure you want to delete this save?
text.save.delete=Delete
text.save.export=Export Save
text.save.import.invalid=[orange]This save is invalid!
text.save.import.fail=[crimson]Failed to import save: [orange]{0}
text.save.export.fail=[crimson]Failed to export save: [orange]{0}
text.save.import=Import Save
text.save.newslot=Save name:
text.save.rename=Rename
text.save.rename.text=New name:
text.selectslot=Select a save.
text.slot=[accent]Slot {0} text.slot=[accent]Slot {0}
text.save.corrupted=[orange]Save file corrupted or invalid! text.save.corrupted=[orange]Save file corrupted or invalid!
text.empty=<empty> text.empty=<empty>
text.on=On
text.off=Off
text.save.autosave=Autosave: {0}
text.save.map=Map: {0}
text.save.wave=Wave {0} text.save.wave=Wave {0}
text.save.date=Last Saved: {0} text.save.date=Last Saved: {0}
text.confirm=Confirm text.confirm=Confirm

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -13,6 +13,7 @@ com.badlogic.gdx.graphics.Color: {
red: {a: 1, b: 0, g: 0, r: 1 }, red: {a: 1, b: 0, g: 0, r: 1 },
blue: {a: 1, b: 1, g: 0, r: 0 }, blue: {a: 1, b: 1, g: 0, r: 0 },
grey: {a: 1, b: 0.32, g: 0.32, r: 0.32 }, grey: {a: 1, b: 0.32, g: 0.32, r: 0.32 },
lightgray: {a: 1, b: 0.3, g: 0.3, r: 0.3 },
orange: {hex: "#FFA500"}, orange: {hex: "#FFA500"},
accent: {hex: "f4ba6e"}, accent: {hex: "f4ba6e"},
vis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 }, vis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 },
@@ -21,8 +22,12 @@ com.badlogic.gdx.graphics.Color: {
link-label: {a: 1, b: 0.886, g: 0.631, r: 0.105 } link-label: {a: 1, b: 0.886, g: 0.631, r: 0.105 }
}, },
io.anuke.ucore.scene.Skin$TintedDrawable: { io.anuke.ucore.scene.Skin$TintedDrawable: {
dialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.9} } dialogDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.9} },
loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} } invis: {name: white, color: {r: 0, g: 0, b: 0, a: 0} }
loadDim: {name: white, color: {r: 0, g: 0, b: 0, a: 0.8} },
clear: {name: white, color: {r: 0.1, g: 0.1, b: 0.1, a: 0.7}},
clear-over: {name: white, color: {r: 1, g: 1, b: 1, a: 0.2} },
clear-down: {name: white, color: {r: 1, g: 1, b: 1, a: 0.4} }
}, },
io.anuke.ucore.scene.ui.Button$ButtonStyle: { io.anuke.ucore.scene.ui.Button$ButtonStyle: {
default: {down: button-down, up: button }, default: {down: button-down, up: button },
@@ -31,11 +36,14 @@ io.anuke.ucore.scene.ui.Button$ButtonStyle: {
}, },
io.anuke.ucore.scene.ui.TextButton$TextButtonStyle: { io.anuke.ucore.scene.ui.TextButton$TextButtonStyle: {
default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button, transition: 0 }, default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: grey, down: button-down, up: button, transition: 0 },
clear: {down: clear-down, up: clear, over: clear-over, font: default-font, fontColor: white, disabledFontColor: grey },
empty: {font: default-font},
toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey } toggle: {font: default-font, fontColor: white, checked: button-down, down: button-down, up: button, over: button-over, disabled: button, disabledFontColor: grey }
}, },
io.anuke.ucore.scene.ui.ImageButton$ImageButtonStyle: { io.anuke.ucore.scene.ui.ImageButton$ImageButtonStyle: {
default: {down: button-down, up: button, over: button-over }, default: {down: button-down, up: button, over: button-over },
empty: {}, empty: { imageDownColor: accent, imageUpColor: white},
emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: lightgray},
static: {up: button }, static: {up: button },
static-down: {up: button-down }, static-down: {up: button-down },
toggle: {checked: button-down, down: button-down, up: button }, toggle: {checked: button-down, down: button-down, up: button },
@@ -51,14 +59,15 @@ io.anuke.ucore.scene.ui.ScrollPane$ScrollPaneStyle: {
default: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical}, default: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
horizontal: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal}, horizontal: {background: border, vScroll: scroll, vScrollKnob: scroll-knob-vertical, hScroll: scroll-horizontal, hScrollKnob: scroll-knob-horizontal},
volume: {background: button-map, vScroll: scroll, vScrollKnob: scroll-knob-vertical}, volume: {background: button-map, vScroll: scroll, vScrollKnob: scroll-knob-vertical},
clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical} clear: {vScroll: scroll, vScrollKnob: scroll-knob-vertical},
clear-black: {vScroll: scroll, vScrollKnob: scroll-knob-vertical-black}
}, },
io.anuke.ucore.scene.ui.Window$WindowStyle: { io.anuke.ucore.scene.ui.Window$WindowStyle: {
default: {titleFont: default-font, background: window, titleFontColor: orange }, default: {titleFont: default-font, background: window, titleFontColor: accent },
dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: accent } dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: accent }
}, },
io.anuke.ucore.scene.ui.KeybindDialog$KeybindDialogStyle: { io.anuke.ucore.scene.ui.KeybindDialog$KeybindDialogStyle: {
default: {keyColor: red, keyNameColor: white, paneStyle: clear}, default: {keyColor: accent, keyNameColor: white, paneStyle: clear},
}, },
io.anuke.ucore.scene.ui.Slider$SliderStyle: { io.anuke.ucore.scene.ui.Slider$SliderStyle: {
default-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down}, default-horizontal: {background: slider, knob: slider-knob, knobOver: slider-knob-over, knobDown: slider-knob-down},
@@ -74,7 +83,7 @@ io.anuke.ucore.scene.ui.TextField$TextFieldStyle: {
default: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: button, cursor: cursor, messageFont: default-font, messageFontColor: grey } default: {font: default-font, fontColor: white, disabledFontColor: grey, selection: selection, background: button, cursor: cursor, messageFont: default-font, messageFontColor: grey }
} }
io.anuke.ucore.scene.ui.CheckBox$CheckBoxStyle: { io.anuke.ucore.scene.ui.CheckBox$CheckBoxStyle: {
default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: grey } default: {checkboxOn: check-on, checkboxOff: check-off, checkboxOnOver: check-on-over, checkboxOver: check-over, font: default-font, fontColor: white, disabledFontColor: grey }
}, },
io.anuke.ucore.scene.ui.List$ListStyle: { io.anuke.ucore.scene.ui.List$ListStyle: {
default: {fontColorUnselected: white, fontColorSelected: white, font: default-font } default: {fontColorUnselected: white, fontColorSelected: white, font: default-font }

View File

@@ -58,7 +58,7 @@ public class Vars{
public static float baseControllerSpeed = 11f; public static float baseControllerSpeed = 11f;
public static final int saveSlots = 10; public static final int saveSlots = 16;
//amount of drops that are left when breaking a block //amount of drops that are left when breaking a block
public static final float breakDropAmount = 0.5f; public static final float breakDropAmount = 0.5f;

View File

@@ -23,6 +23,7 @@ import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.input.AndroidInput; import io.anuke.mindustry.input.AndroidInput;
import io.anuke.mindustry.input.DesktopInput; import io.anuke.mindustry.input.DesktopInput;
import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.io.Saves;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.resource.Weapon;
@@ -64,7 +65,9 @@ public class Control extends Module{
Array<SpawnPoint> spawnpoints = new Array<>(); Array<SpawnPoint> spawnpoints = new Array<>();
boolean shouldUpdateItems = false; boolean shouldUpdateItems = false;
boolean wasPaused = false; boolean wasPaused = false;
Saves saves;
float respawntime; float respawntime;
InputHandler input; InputHandler input;
@@ -76,6 +79,8 @@ public class Control extends Module{
if(Mindustry.args.contains("-debug", false)) if(Mindustry.args.contains("-debug", false))
Vars.debug = true; Vars.debug = true;
saves = new Saves();
Inputs.useControllers(false); Inputs.useControllers(false);
log("Total blocks loaded: " + Block.getAllBlocks().size); log("Total blocks loaded: " + Block.getAllBlocks().size);
@@ -177,7 +182,8 @@ public class Control extends Module{
); );
for(int i = 0; i < Vars.saveSlots; i ++){ for(int i = 0; i < Vars.saveSlots; i ++){
Settings.defaults("saveslot" + i, "empty"); Settings.defaults("save-" + i + "-autosave", true);
Settings.defaults("save-" + i + "-name", "untitled");
} }
Settings.loadAll("io.anuke.moment"); Settings.loadAll("io.anuke.moment");
@@ -189,7 +195,12 @@ public class Control extends Module{
player = new Player(); player = new Player();
spawns = WaveCreator.getSpawns(); spawns = WaveCreator.getSpawns();
//WaveCreator.testWaves(1, 30);
saves.load();
}
public Saves getSaves(){
return saves;
} }
public boolean showCursor(){ public boolean showCursor(){

View File

@@ -49,12 +49,12 @@ public class Tutorial{
row(); row();
prev = new button("< Prev", ()->{ prev = new button("$text.tutorial.back", ()->{
if(!prev.isDisabled()) if(!prev.isDisabled())
move(false); move(false);
}).left().get(); }).left().get();
next = new button("Next >", ()->{ next = new button("$text.tutorial.next", ()->{
if(!next.isDisabled()) if(!next.isDisabled())
move(true); move(true);
}).right().get(); }).right().get();

View File

@@ -30,12 +30,14 @@ import io.anuke.mindustry.world.blocks.types.Configurable;
import io.anuke.ucore.UCore; import io.anuke.ucore.UCore;
import io.anuke.ucore.core.*; import io.anuke.ucore.core.*;
import io.anuke.ucore.core.Inputs.DeviceType; import io.anuke.ucore.core.Inputs.DeviceType;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.function.Listenable; import io.anuke.ucore.function.Listenable;
import io.anuke.ucore.function.VisibilityProvider; import io.anuke.ucore.function.VisibilityProvider;
import io.anuke.ucore.modules.SceneModule; import io.anuke.ucore.modules.SceneModule;
import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.Skin; import io.anuke.ucore.scene.Skin;
import io.anuke.ucore.scene.builders.build; import io.anuke.ucore.scene.builders.build;
import io.anuke.ucore.scene.builders.field;
import io.anuke.ucore.scene.builders.label; import io.anuke.ucore.scene.builders.label;
import io.anuke.ucore.scene.builders.table; import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.event.Touchable; import io.anuke.ucore.scene.event.Touchable;
@@ -367,12 +369,28 @@ public class UI extends SceneModule{
public void hideConfig(){ public void hideConfig(){
configtable.setVisible(false); configtable.setVisible(false);
} }
public void showTextInput(String title, String text, String def, Consumer<String> confirmed){
new Dialog(title, "dialog"){{
content().margin(30);
content().add(text).padRight(6f);
TextField field = content().addField(def, t->{}).size(170f, 50f).get();
field.setTextFieldFilter((f, c) -> field.getText().length() < 12);
Mindustry.platforms.addDialog(field);
buttons().defaults().size(120, 54).pad(4);
buttons().addButton("$text.ok", () -> {
confirmed.accept(field.getText());
hide();
}).disabled(b -> field.getText().isEmpty());
buttons().addButton("$text.cancel", this::hide);
}}.show();
}
public void showError(String text){ public void showError(String text){
new Dialog("$text.error.title", "dialog"){{ new Dialog("$text.error.title", "dialog"){{
content().margin(15); content().margin(15);
content().add(text); content().add(text);
getButtonTable().addButton("$text.ok", this::hide).size(90, 50).pad(4); buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
}}.show(); }}.show();
} }
@@ -380,7 +398,7 @@ public class UI extends SceneModule{
new Dialog("$text.error.title", "dialog"){{ new Dialog("$text.error.title", "dialog"){{
content().margin(15); content().margin(15);
content().add(text); content().add(text);
getButtonTable().addButton("$text.quit", Gdx.app::exit).size(90, 50).pad(4); buttons().addButton("$text.quit", Gdx.app::exit).size(90, 50).pad(4);
}}.show(); }}.show();
} }

View File

@@ -115,7 +115,11 @@ public class SaveIO{
} }
public static boolean isSaveValid(int slot){ public static boolean isSaveValid(int slot){
try(DataInputStream stream = new DataInputStream(fileFor(slot).read())){ return isSaveValid(fileFor(slot));
}
public static boolean isSaveValid(FileHandle file){
try(DataInputStream stream = new DataInputStream(file.read())){
int version = stream.readInt(); //read version int version = stream.readInt(); //read version
stream.readLong(); //read last saved time stream.readLong(); //read last saved time
stream.readByte(); //read the gamemode stream.readByte(); //read the gamemode
@@ -340,6 +344,7 @@ public class SaveIO{
Vars.control.getWeapons().clear(); Vars.control.getWeapons().clear();
Vars.control.getWeapons().add(Weapon.blaster); Vars.control.getWeapons().add(Weapon.blaster);
Vars.player.weapon = Weapon.blaster;
int weapons = stream.readByte(); int weapons = stream.readByte();

View File

@@ -1,10 +1,107 @@
package io.anuke.mindustry.io; package io.anuke.mindustry.io;
import com.badlogic.gdx.utils.IntArray; import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.world.GameMode;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.core.Settings;
import java.lang.reflect.Array; import java.io.IOException;
public class Saves { public class Saves {
private int lastSlot; private int nextSlot;
private IntArray saves; private Array<SaveSlot> saves = new Array<>();
public void load(){
saves.clear();
for(int i = 0; i < Vars.saveSlots; i ++){
if(SaveIO.isSaveValid(i)){
saves.add(new SaveSlot(i));
nextSlot = i + 1;
}
}
}
public boolean canAddSave(){
return nextSlot <= Vars.saveSlots;
}
public void addSave(String name){
SaveSlot slot = new SaveSlot(nextSlot);
nextSlot ++;
slot.setName(name);
saves.add(slot);
SaveIO.saveToSlot(slot.index);
}
public Array<SaveSlot> getSaveSlots(){
return saves;
}
public class SaveSlot{
public final int index;
public SaveSlot(int index){
this.index = index;
}
public String getDate(){
return SaveIO.getTimeString(index);
}
public Map getMap(){
return SaveIO.getMap(index);
}
public String getName(){
return Settings.getString("save-"+index+"-name");
}
public void setName(String name){
Settings.putString("save-"+index+"-name", name);
Settings.save();
}
public int getWave(){
return SaveIO.getWave(index);
}
public GameMode getMode(){
return SaveIO.getMode(index);
}
public boolean isAutosave(){
return Settings.getBool("save-"+index+"-autosave");
}
public void setAutosave(boolean save){
Settings.putBool("save-"+index + "-autosave", save);
Settings.save();
}
public void importFile(FileHandle file) throws IOException{
try{
file.copyTo(SaveIO.fileFor(index));
}catch (Exception e){
throw new IOException(e);
}
}
public void exportFile(FileHandle file) throws IOException{
try{
if(!file.extension().equals("mins")){
file = file.parent().child(file.nameWithoutExtension() + ".mins");
}
SaveIO.fileFor(index).copyTo(file);
}catch (Exception e){
throw new IOException(e);
}
}
public void delete(){
SaveIO.fileFor(index).delete();
load();
}
}
} }

View File

@@ -233,7 +233,7 @@ public class MapEditorDialog extends Dialog{
ImageButton undo = tools.addIButton("icon-undo", 16*2f, () -> view.undo()).get(); ImageButton undo = tools.addIButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addIButton("icon-redo", 16*2f, () -> view.redo()).get(); ImageButton redo = tools.addIButton("icon-redo", 16*2f, () -> view.redo()).get();
tools.addIButton("toggle", "icon-grid", 16*2f, () -> view.setGrid(!view.isGrid())).get(); tools.addIButton("icon-grid", "toggle", 16*2f, () -> view.setGrid(!view.isGrid())).get();
undo.setDisabled(() -> !view.getStack().canUndo()); undo.setDisabled(() -> !view.getStack().canUndo());
redo.setDisabled(() -> !view.getStack().canRedo()); redo.setDisabled(() -> !view.getStack().canRedo());

View File

@@ -53,7 +53,7 @@ public enum Weapon{
Effects.effect(Fx.shoot2, p.x + vector.x, p.y+vector.y); Effects.effect(Fx.shoot2, p.x + vector.x, p.y+vector.y);
} }
}, },
flamer(5, BulletType.flame, stack(Item.steel, 60), stack(Item.coal, 60)){ flamer(5, BulletType.flame, stack(Item.steel, 60), stack(Item.iron, 120)){
{ {
shootsound = "flame2"; shootsound = "flame2";

View File

@@ -59,7 +59,7 @@ public class FileChooser extends FloatingDialog{
if(!open) Mindustry.platforms.addDialog(filefield); if(!open) Mindustry.platforms.addDialog(filefield);
filefield.setDisabled(open); filefield.setDisabled(open);
ok = new TextButton(open ? "$text.save" : "$text.save"); ok = new TextButton(open ? "$text.load" : "$text.save");
ok.clicked(() -> { ok.clicked(() -> {
if(ok.isDisabled()) return; if(ok.isDisabled()) return;

View File

@@ -12,7 +12,7 @@ import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.ui.*; import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Stack; import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.utils.ClickListener; import io.anuke.ucore.scene.event.ClickListener;
import io.anuke.ucore.scene.utils.Elements; import io.anuke.ucore.scene.utils.Elements;
import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Tmp; import io.anuke.ucore.util.Tmp;

View File

@@ -1,21 +1,28 @@
package io.anuke.mindustry.ui; package io.anuke.mindustry.ui;
import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.io.Saves.SaveSlot;
import io.anuke.ucore.UCore;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.ui.Label; import io.anuke.ucore.scene.builders.button;
import io.anuke.ucore.scene.builders.dialog;
import io.anuke.ucore.scene.ui.Dialog;
import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Strings;
import java.io.IOException;
public class LoadDialog extends FloatingDialog{ public class LoadDialog extends FloatingDialog{
ScrollPane pane; ScrollPane pane;
Table slots;
public LoadDialog() { public LoadDialog() {
this("$text.loadgame"); this("$text.loadgame");
@@ -33,37 +40,112 @@ public class LoadDialog extends FloatingDialog{
addCloseButton(); addCloseButton();
} }
private void setup(){ protected void setup(){
content().clear(); content().clear();
content().add("$text.selectslot").padBottom(2); slots = new Table();
content().row(); pane = new ScrollPane(slots, "clear-black");
Table slots = new Table();
pane = new ScrollPane(slots);
pane.setFadeScrollBars(false); pane.setFadeScrollBars(false);
pane.setScrollingDisabled(true, false);
slots.marginRight(24); slots.marginRight(24);
for(int i = 0; i < Vars.saveSlots; i++){ Timers.runTask(2f, () -> Core.scene.setScrollFocus(pane));
TextButton button = new TextButton(Bundles.format("text.slot", (i + 1))); Array<SaveSlot> array = Vars.control.getSaves().getSaveSlots();
button.margin(12);
for(SaveSlot slot : array){
TextButton button = new TextButton("[accent]" + slot.getName(), "clear");
button.getLabelCell().growX().left();
button.getLabelCell().padBottom(8f);
button.getLabelCell().top().left().growX(); button.getLabelCell().top().left().growX();
button.row(); button.defaults().left();
Label info = new Label("[gray]" + (!SaveIO.isSaveValid(i) ? Bundles.get("text.empty") : SaveIO.getMode(i) + ", " button.table(t -> {
+ Bundles.get("map."+SaveIO.getMap(i).name+".name", SaveIO.getMap(i).name) + ", " + Bundles.format("text.save.wave", SaveIO.getWave(i)) + "\n" t.right();
+ Bundles.format("text.save.date", SaveIO.getTimeString(i))));
info.setAlignment(Align.center, Align.center);
button.add(info).padBottom(3).padTop(7); t.addIButton("icon-floppy", "emptytoggle", 14*3, () -> {
button.row(); slot.setAutosave(!slot.isAutosave());
button.row(); }).checked(slot.isAutosave()).right();
modifyButton(button, i);
slots.add(button).size(404, 104).pad(4); t.addIButton("icon-trash", "empty", 14*3, () -> {
Vars.ui.showConfirm("$text.confirm", "$text.save.delete.confirm", () -> {
slot.delete();
setup();
});
}).size(14*3).right();
t.addIButton("icon-dots", "empty", 14*3, () -> {
FloatingDialog dialog = new FloatingDialog("Save Options");
dialog.addCloseButton();
dialog.content().defaults().left().uniformX().size(230f, 60f);
dialog.content().addImageTextButton("$text.save.rename", "icon-rename", 14*3, () -> {
Vars.ui.showTextInput("$text.save.rename", "$text.save.rename.text", slot.getName(), text -> {
slot.setName(text);
dialog.hide();
setup();
});
});
dialog.content().row();
dialog.content().addImageTextButton("$text.save.import", "icon-save", 14*3, () -> {
new FileChooser("$text.save.import", f -> f.extension().equals("mins"), true, file -> {
if(SaveIO.isSaveValid(file)){
try{
slot.importFile(file);
setup();
}catch (IOException e){
Vars.ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
}
}else{
Vars.ui.showError("$text.save.import.invalid");
}
dialog.hide();
}).show();
});
dialog.content().row();
dialog.content().addImageTextButton("$text.save.export", "icon-load", 14*3, () -> {
new FileChooser("$text.save.export", false, file -> {
try{
slot.exportFile(file);
setup();
}catch (IOException e){
Vars.ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
}
dialog.hide();
}).show();
});
dialog.show();
}).size(14*3).right();
}).padRight(-10).growX();
String color = "[lightgray]";
button.defaults().padBottom(3);
button.row();
button.add(Bundles.format("text.save.map", color+slot.getMap().localized()));
button.row();
button.add(Bundles.get("text.level.mode") + " " +color+ slot.getMode());
button.row();
button.add(Bundles.format("text.save.wave", color+slot.getWave()));
button.row();
button.label(() -> Bundles.format("text.save.autosave", color + Bundles.get(slot.isAutosave() ? "text.on" : "text.off")));
button.row();
button.add();
button.add(Bundles.format("text.save.date", color+slot.getDate()));
button.row();
modifyButton(button, slot);
slots.add(button).uniformX().fillX().pad(4).padRight(-4).margin(10f).marginLeft(20f).marginRight(20f);
slots.row(); slots.row();
} }
@@ -71,17 +153,16 @@ public class LoadDialog extends FloatingDialog{
} }
public void modifyButton(TextButton button, int slot){ public void modifyButton(TextButton button, SaveSlot slot){
button.setDisabled(!SaveIO.isSaveValid(slot));
button.clicked(() -> { button.clicked(() -> {
if(!button.isDisabled()){ if(!button.childrenPressed()){
Vars.ui.showLoading(); Vars.ui.showLoading();
Timers.runTask(3f, () -> { Timers.runTask(3f, () -> {
Vars.ui.hideLoading(); Vars.ui.hideLoading();
hide(); hide();
try{ try{
SaveIO.loadFromSlot(slot); SaveIO.loadFromSlot(slot.index);
GameState.set(State.playing); GameState.set(State.playing);
Vars.ui.hideMenu(); Vars.ui.hideMenu();
}catch(Exception e){ }catch(Exception e){
@@ -90,7 +171,6 @@ public class LoadDialog extends FloatingDialog{
GameState.set(State.menu); GameState.set(State.menu);
Vars.control.reset(); Vars.control.reset();
Vars.ui.showError("$text.save.corrupted"); Vars.ui.showError("$text.save.corrupted");
return;
} }
}); });
} }

View File

@@ -4,8 +4,12 @@ import com.badlogic.gdx.utils.reflect.ClassReflection;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.io.SaveIO;
import io.anuke.mindustry.io.Saves;
import io.anuke.mindustry.io.Saves.SaveSlot;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.builders.button;
import io.anuke.ucore.scene.ui.ConfirmDialog; import io.anuke.ucore.scene.ui.ConfirmDialog;
import io.anuke.ucore.scene.ui.Dialog;
import io.anuke.ucore.scene.ui.TextButton; import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Cell; import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.util.Bundles; import io.anuke.ucore.util.Bundles;
@@ -17,21 +21,31 @@ public class SaveDialog extends LoadDialog{
} }
@Override @Override
public void modifyButton(TextButton button, int slot){ protected void setup(){
super.setup();
if(!Vars.control.getSaves().canAddSave()){
return;
}
slots.row();
slots.addImageTextButton("$text.save.new", "icon-add", "clear", 14*3, () -> {
Vars.ui.showTextInput("$text.save", "$text.save.newslot", "", text -> {
Vars.control.getSaves().addSave(text);
setup();
});
}).fillX().margin(10f).height(70f).pad(4f).padRight(-4);
}
@Override
public void modifyButton(TextButton button, SaveSlot slot){
button.clicked(() -> { button.clicked(() -> {
if(SaveIO.isSaveValid(slot)){ if(button.childrenPressed()) return;
new ConfirmDialog("$text.overwrite", "$text.save.overwrite", () -> {
save(slot); Vars.ui.showConfirm("$text.overwrite", "$text.save.overwrite", () -> {
}){ save(slot.index);
{ });
content().margin(16);
for(Cell<?> cell : getButtonTable().getCells())
cell.size(110, 45).pad(4);
}
}.show();
}else{
save(slot);
}
}); });
} }

View File

@@ -220,7 +220,7 @@ public class Tile{
public void changed(){ public void changed(){
if(entity != null){ if(entity != null){
if(entity.added) entity.remove(); entity.remove();
entity = null; entity = null;
} }

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.desktop;
import java.awt.Desktop; import java.awt.Desktop;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.text.DateFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
@@ -30,7 +31,7 @@ public class DesktopLauncher {
config.setWindowIcon("sprites/icon.png"); config.setWindowIcon("sprites/icon.png");
Mindustry.platforms = new PlatformFunction(){ Mindustry.platforms = new PlatformFunction(){
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm"); DateFormat format = SimpleDateFormat.getDateTimeInstance();
@Override @Override
public String format(Date date){ public String format(Date date){