Classic data backup dialog

This commit is contained in:
Anuken 2019-08-13 15:14:03 -04:00
parent f2f6dc89a2
commit 974ab59fd2
23 changed files with 129 additions and 46 deletions

View File

@ -34,6 +34,7 @@ public class AndroidLauncher extends AndroidApplication{
public static final int PERMISSION_REQUEST_CODE = 1; public static final int PERMISSION_REQUEST_CODE = 1;
boolean doubleScaleTablets = true; boolean doubleScaleTablets = true;
FileChooser chooser; FileChooser chooser;
Runnable permCallback;
@Override @Override
protected void onCreate(Bundle savedInstanceState){ protected void onCreate(Bundle savedInstanceState){
@ -66,6 +67,24 @@ public class AndroidLauncher extends AndroidApplication{
} }
} }
@Override
public void requestExternalPerms(Runnable callback){
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
callback.run();
}else{
permCallback = callback;
ArrayList<String> perms = new ArrayList<>();
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
requestPermissions(perms.toArray(new String[0]), PERMISSION_REQUEST_CODE);
}
}
@Override @Override
public void shareFile(FileHandle file){ public void shareFile(FileHandle file){
} }
@ -123,7 +142,11 @@ public class AndroidLauncher extends AndroidApplication{
if(i != PackageManager.PERMISSION_GRANTED) return; if(i != PackageManager.PERMISSION_GRANTED) return;
} }
if(chooser != null){ if(chooser != null){
chooser.show(); Core.app.post(chooser::show);
}
if(permCallback != null){
Core.app.post(permCallback);
permCallback = null;
} }
} }
} }

View File

@ -157,6 +157,8 @@ cancel = Cancel
openlink = Open Link openlink = Open Link
copylink = Copy Link copylink = Copy Link
back = Back back = Back
classic.export = Export Classic Data
classic.export.text = Classic (v3.5 build 40) save or map data has been detected. Would you like to export these saves to your phone's home folder, for use in the Mindustry Classic app?
quit.confirm = Are you sure you want to quit? quit.confirm = Are you sure you want to quit?
quit.confirm.tutorial = Are you sure you know what you're doing?\nThe tutorial can be re-taken in[accent] Settings->Game->Re-Take Tutorial.[] quit.confirm.tutorial = Are you sure you know what you're doing?\nThe tutorial can be re-taken in[accent] Settings->Game->Re-Take Tutorial.[]
loading = [accent]Loading... loading = [accent]Loading...
@ -435,7 +437,7 @@ blocks.shots = Shots
blocks.reload = Shots/Second blocks.reload = Shots/Second
blocks.ammo = Ammo blocks.ammo = Ammo
bar.drilltierreq = Better Drill Required
bar.drillspeed = Drill Speed: {0}/s bar.drillspeed = Drill Speed: {0}/s
bar.efficiency = Efficiency: {0}% bar.efficiency = Efficiency: {0}%
bar.powerbalance = Power: {0}/s bar.powerbalance = Power: {0}/s

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/wave.ogg Normal file

Binary file not shown.

View File

@ -102,6 +102,7 @@ public class UnitTypes implements ContentList{
weapon = new Weapon("bomber"){{ weapon = new Weapon("bomber"){{
reload = 12f; reload = 12f;
ejectEffect = Fx.none; ejectEffect = Fx.none;
shootSound = Sounds.explosion;
bullet = new BombBulletType(2f, 3f, "clear"){ bullet = new BombBulletType(2f, 3f, "clear"){
{ {
hitEffect = Fx.pulverize; hitEffect = Fx.pulverize;
@ -233,6 +234,7 @@ public class UnitTypes implements ContentList{
shotDelay = 3; shotDelay = 3;
ejectEffect = Fx.shellEjectMedium; ejectEffect = Fx.shellEjectMedium;
bullet = Bullets.standardThoriumBig; bullet = Bullets.standardThoriumBig;
shootSound = Sounds.shootBig;
}}; }};
}}; }};
@ -251,6 +253,7 @@ public class UnitTypes implements ContentList{
roundrobin = true; roundrobin = true;
ejectEffect = Fx.shellEjectSmall; ejectEffect = Fx.shellEjectSmall;
bullet = Bullets.standardCopper; bullet = Bullets.standardCopper;
shootSound = Sounds.shoot;
}}; }};
}}; }};
@ -274,7 +277,7 @@ public class UnitTypes implements ContentList{
inaccuracy = 40f; inaccuracy = 40f;
ignoreRotation = true; ignoreRotation = true;
bullet = Bullets.bombExplosive; bullet = Bullets.bombExplosive;
shootSound = Sounds.release; shootSound = Sounds.none;
}}; }};
}}; }};

View File

@ -1,7 +1,7 @@
package io.anuke.mindustry.core; package io.anuke.mindustry.core;
import io.anuke.arc.Application.*;
import io.anuke.arc.*; import io.anuke.arc.*;
import io.anuke.arc.files.*;
import io.anuke.arc.graphics.*; import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.input.*; import io.anuke.arc.input.*;
@ -39,11 +39,11 @@ public class Control implements ApplicationListener{
public final Saves saves; public final Saves saves;
public final MusicControl music; public final MusicControl music;
public final Tutorial tutorial; public final Tutorial tutorial;
public InputHandler input;
private Interval timer = new Interval(2); private Interval timer = new Interval(2);
private boolean hiscore = false; private boolean hiscore = false;
private boolean wasPaused = false; private boolean wasPaused = false;
private InputHandler input;
public Control(){ public Control(){
batch = new SpriteBatch(); batch = new SpriteBatch();
@ -117,6 +117,7 @@ public class Control implements ApplicationListener{
hiscore = true; hiscore = true;
world.getMap().setHighScore(state.wave); world.getMap().setHighScore(state.wave);
} }
Sounds.wave.play();
}); });
Events.on(GameOverEvent.class, event -> { Events.on(GameOverEvent.class, event -> {
@ -177,8 +178,39 @@ public class Control implements ApplicationListener{
ui.hudfrag.showToast(Core.bundle.format("zone.config.complete", e.zone.configureWave)); ui.hudfrag.showToast(Core.bundle.format("zone.config.complete", e.zone.configureWave));
}); });
if(Core.app.getType() == ApplicationType.Android){ if(android){
Sounds.empty.loop(0f, 1f, 0f); Sounds.empty.loop(0f, 1f, 0f);
checkClassicData();
}
}
//checks for existing 3.5 app data, android only
public void checkClassicData(){
try{
if(files.local("mindustry-maps").exists() || files.local("mindustry-saves").exists()){
settings.getBoolOnce("classic-backup-check", () -> {
app.post(() -> app.post(() -> ui.showConfirm("$classic.export", "$classic.export.text", () -> {
try{
Platform.instance.requestExternalPerms(() -> {
FileHandle external = files.external("MindustryClassic");
if(files.local("mindustry-maps").exists()){
files.local("mindustry-maps").copyTo(external);
}
if(files.local("mindustry-saves").exists()){
files.local("mindustry-saves").copyTo(external);
}
});
}catch(Exception e){
e.printStackTrace();
ui.showError(Strings.parseException(e, true));
}
})));
});
}
}catch(Throwable t){
t.printStackTrace();
} }
} }
@ -202,10 +234,6 @@ public class Control implements ApplicationListener{
Core.input.addProcessor(input); Core.input.addProcessor(input);
} }
public InputHandler input(){
return input;
}
public void playMap(Map map, Rules rules){ public void playMap(Map map, Rules rules){
ui.loadAnd(() -> { ui.loadAnd(() -> {
logic.reset(); logic.reset();

View File

@ -39,6 +39,11 @@ public abstract class Platform{
}); });
} }
/** Request external read/write perms. Run callback when complete.*/
public void requestExternalPerms(Runnable callback){
callback.run();
}
/** Update discord RPC. */ /** Update discord RPC. */
public void updateRPC(){ public void updateRPC(){
} }

View File

@ -214,7 +214,7 @@ public class UI implements ApplicationListener{
Core.scene.add(menuGroup); Core.scene.add(menuGroup);
Core.scene.add(hudGroup); Core.scene.add(hudGroup);
control.input().getFrag().build(hudGroup); control.input.getFrag().build(hudGroup);
hudfrag.build(hudGroup); hudfrag.build(hudGroup);
menufrag.build(menuGroup); menufrag.build(menuGroup);
chatfrag.container().build(hudGroup); chatfrag.container().build(hudGroup);

View File

@ -1,5 +1,6 @@
package io.anuke.mindustry.entities.traits; package io.anuke.mindustry.entities.traits;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.Core; import io.anuke.arc.Core;
import io.anuke.arc.Events; import io.anuke.arc.Events;
import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Array;
@ -206,7 +207,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
* Return the build requests currently active, or the one at the top of the queue. * Return the build requests currently active, or the one at the top of the queue.
* May return null. * May return null.
*/ */
default BuildRequest buildRequest(){ default @Nullable BuildRequest buildRequest(){
return buildQueue().size == 0 ? null : buildQueue().first(); return buildQueue().size == 0 ? null : buildQueue().first();
} }

View File

@ -19,7 +19,7 @@ import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.input.*;
import io.anuke.mindustry.input.InputHandler.PlaceDraw; import io.anuke.mindustry.input.InputHandler.PlaceDraw;
import io.anuke.mindustry.io.TypeIO; import io.anuke.mindustry.io.TypeIO;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
@ -70,7 +70,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
private Tile mining; private Tile mining;
private Vector2 movement = new Vector2(); private Vector2 movement = new Vector2();
private boolean moved; private boolean moved;
private SoundLoop sound = new SoundLoop(Sounds.thruster, 2f); private SoundLoop boostSound = new SoundLoop(Sounds.thruster, 2f), buildSound = new SoundLoop(Sounds.build, 0.75f);
//endregion //endregion
@ -133,7 +133,8 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
@Override @Override
public void removed(){ public void removed(){
sound.stop(); boostSound.stop();
buildSound.stop();
} }
@Override @Override
@ -513,7 +514,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
destructTime = 0f; destructTime = 0f;
} }
sound.update(x, y, isBoosting && !isDead() && !mech.flying); boostSound.update(x, y, isBoosting && !isDead() && !mech.flying);
BuildRequest request = buildRequest();
buildSound.update(request == null ? x : request.x * tilesize, request == null ? y : request.y * tilesize, isBuilding() && (Mathf.within(request.x * tilesize, request.y * tilesize, x, y, placeDistance) || state.isEditor()));
if(isDead()){ if(isDead()){
isBoosting = false; isBoosting = false;
@ -606,7 +609,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
movement.x += xa * speed; movement.x += xa * speed;
} }
Vector2 vec = Core.input.mouseWorld(control.input().getMouseX(), control.input().getMouseY()); Vector2 vec = Core.input.mouseWorld(control.input.getMouseX(), control.input.getMouseY());
pointerX = vec.x; pointerX = vec.x;
pointerY = vec.y; pointerY = vec.y;
updateShooting(); updateShooting();
@ -629,7 +632,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
rotation = Mathf.slerpDelta(rotation, mech.flying ? velocity.angle() : movement.angle(), 0.13f * baseLerp); rotation = Mathf.slerpDelta(rotation, mech.flying ? velocity.angle() : movement.angle(), 0.13f * baseLerp);
} }
}else{ }else{
float angle = control.input().mouseAngle(x, y); float angle = control.input.mouseAngle(x, y);
this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f * baseLerp); this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f * baseLerp);
} }
} }
@ -758,8 +761,8 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
} }
}else if(isShooting()){ }else if(isShooting()){
Vector2 vec = Core.input.mouseWorld(control.input().getMouseX(), Vector2 vec = Core.input.mouseWorld(control.input.getMouseX(),
control.input().getMouseY()); control.input.getMouseY());
pointerX = vec.x; pointerX = vec.x;
pointerY = vec.y; pointerY = vec.y;

View File

@ -33,6 +33,7 @@ public class SoundLoop{
if(volume <= 0.001f){ if(volume <= 0.001f){
sound.stop(id); sound.stop(id);
id = -1; id = -1;
return;
} }
} }
sound.setPan(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume); sound.setPan(id, sound.calcPan(x, y), sound.calcVolume(x, y) * volume * baseVolume);

View File

@ -105,6 +105,7 @@ public class Tutorial{
void draw(){ void draw(){
outline("category-production"); outline("category-production");
outline("block-mechanical-drill"); outline("block-mechanical-drill");
outline("confirmplace");
} }
}, },
blockinfo(() -> event("blockinfo")){ blockinfo(() -> event("blockinfo")){

View File

@ -27,7 +27,7 @@ public class OverlayRenderer{
private float buildFadeTime; private float buildFadeTime;
public void drawBottom(){ public void drawBottom(){
InputHandler input = control.input(); InputHandler input = control.input;
if(!input.isDrawing() || player.isDead()) return; if(!input.isDrawing() || player.isDead()) return;
@ -64,7 +64,7 @@ public class OverlayRenderer{
if(player.isDead()) return; //dead players don't draw if(player.isDead()) return; //dead players don't draw
InputHandler input = control.input(); InputHandler input = control.input;
//draw config selected block //draw config selected block
if(input.frag.config.isShown()){ if(input.frag.config.isShown()){

View File

@ -289,7 +289,7 @@ public class MobileInput extends InputHandler implements GestureListener{
removals.addAll(selection); removals.addAll(selection);
selection.clear(); selection.clear();
selecting = false; selecting = false;
}).visible(() -> !selection.isEmpty()); }).visible(() -> !selection.isEmpty()).name("confirmplace");
Core.scene.table(t -> { Core.scene.table(t -> {
t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking) && !state.is(State.menu)); t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking) && !state.is(State.menu));

View File

@ -54,7 +54,7 @@ public class Weapon{
/** whether shooter rotation is ignored when shooting. */ /** whether shooter rotation is ignored when shooting. */
public boolean ignoreRotation = false; public boolean ignoreRotation = false;
public Sound shootSound = Sounds.shoot; public Sound shootSound = Sounds.pew;
public TextureRegion region; public TextureRegion region;

View File

@ -193,6 +193,20 @@ public class SettingsMenuDialog extends SettingsDialog{
} }
}); });
if(android && (Core.files.local("mindustry-maps").exists() || Core.files.local("mindustry-saves").exists())){
game.pref(new Setting(){
@Override
public void add(SettingsTable table){
table.addButton("$classic.export", () -> {
control.checkClassicData();
}).size(220f, 60f).pad(6).left();
table.add();
table.row();
hide();
}
});
}
graphics.sliderPref("uiscale", 100, 25, 400, 25, s -> { graphics.sliderPref("uiscale", 100, 25, 400, 25, s -> {
if(Core.graphics.getFrameId() > 10){ if(Core.graphics.getFrameId() > 10){
Log.info("changed"); Log.info("changed");

View File

@ -53,7 +53,7 @@ public class PlacementFragment extends Fragment{
public PlacementFragment(){ public PlacementFragment(){
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
Core.app.post(() -> { Core.app.post(() -> {
control.input().block = null; control.input.block = null;
rebuild(); rebuild();
}); });
}); });
@ -119,7 +119,7 @@ public class PlacementFragment extends Fragment{
full.bottom().right().visible(() -> ui.hudfrag.shown()); full.bottom().right().visible(() -> ui.hudfrag.shown());
full.table(frame -> { full.table(frame -> {
InputHandler input = control.input(); InputHandler input = control.input;
//rebuilds the category table with the correct recipes //rebuilds the category table with the correct recipes
Runnable rebuildCategory = () -> { Runnable rebuildCategory = () -> {
@ -336,8 +336,8 @@ public class PlacementFragment extends Fragment{
} }
//block currently selected //block currently selected
if(control.input().block != null){ if(control.input.block != null){
toDisplay = control.input().block; toDisplay = control.input.block;
} }
//block hovered on in build menu //block hovered on in build menu

View File

@ -28,7 +28,7 @@ public class ItemSelection{
for(Item item : items){ for(Item item : items){
if(!data.isUnlocked(item) && world.isZone()) continue; if(!data.isUnlocked(item) && world.isZone()) continue;
ImageButton button = cont.addImageButton("whiteui", "clear-toggle-trans", 24, () -> control.input().frag.config.hideConfig()).group(group).get(); ImageButton button = cont.addImageButton("whiteui", "clear-toggle-trans", 24, () -> control.input.frag.config.hideConfig()).group(group).get();
button.changed(() -> consumer.accept(button.isChecked() ? item : null)); button.changed(() -> consumer.accept(button.isChecked() ? item : null));
button.getStyle().imageUp = new TextureRegionDrawable(item.icon(Icon.medium)); button.getStyle().imageUp = new TextureRegionDrawable(item.icon(Icon.medium));
button.update(() -> button.setChecked(holder.get() == item)); button.update(() -> button.setChecked(holder.get() == item));

View File

@ -1,21 +1,18 @@
package io.anuke.mindustry.world.blocks.power; package io.anuke.mindustry.world.blocks.power;
import io.anuke.arc.Core; import io.anuke.arc.*;
import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.*;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.*;
import io.anuke.mindustry.world.meta.StatUnit;
import java.io.*; import java.io.*;
@ -130,6 +127,8 @@ public class ImpactReactor extends PowerGenerator{
if(entity.warmup < 0.4f) return; if(entity.warmup < 0.4f) return;
Sounds.explosionbig.at(tile);
Effects.shake(6f, 16f, tile.worldx(), tile.worldy()); Effects.shake(6f, 16f, tile.worldx(), tile.worldy());
Effects.effect(Fx.impactShockwave, tile.worldx(), tile.worldy()); Effects.effect(Fx.impactShockwave, tile.worldx(), tile.worldy());
for(int i = 0; i < 6; i++){ for(int i = 0; i < 6; i++){

View File

@ -10,6 +10,7 @@ import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.type.Liquid;
@ -118,6 +119,8 @@ public class NuclearReactor extends PowerGenerator{
public void onDestroyed(Tile tile){ public void onDestroyed(Tile tile){
super.onDestroyed(tile); super.onDestroyed(tile);
Sounds.explosionbig.at(tile);
NuclearReactorEntity entity = tile.entity(); NuclearReactorEntity entity = tile.entity();
int fuel = entity.items.get(consumes.<ConsumeItems>get(ConsumeType.item).items[0].item); int fuel = entity.items.get(consumes.<ConsumeItems>get(ConsumeType.item).items[0].item);

View File

@ -83,10 +83,10 @@ public class LiquidSource extends Block{
for(int i = 0; i < items.size; i++){ for(int i = 0; i < items.size; i++){
final int f = i; final int f = i;
ImageButton button = cont.addImageButton("clear", "clear-toggle-trans", 24, () -> control.input().frag.config.hideConfig()).size(38).group(group).get(); ImageButton button = cont.addImageButton("clear", "clear-toggle-trans", 24, () -> control.input.frag.config.hideConfig()).size(38).group(group).get();
button.changed(() -> { button.changed(() -> {
Call.setLiquidSourceLiquid(null, tile, button.isChecked() ? items.get(f) : null); Call.setLiquidSourceLiquid(null, tile, button.isChecked() ? items.get(f) : null);
control.input().frag.config.hideConfig(); control.input.frag.config.hideConfig();
lastLiquid = items.get(f); lastLiquid = items.get(f);
}); });
button.getStyle().imageUp = new TextureRegionDrawable(items.get(i).iconRegion); button.getStyle().imageUp = new TextureRegionDrawable(items.get(i).iconRegion);