diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 4690a1c9a6..311ed7074d 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -201,7 +201,7 @@ setting.difficulty.normal=normal setting.difficulty.hard=hard setting.difficulty.insane=insane setting.difficulty.purge=purge -setting.difficulty.name=Difficulty +setting.difficulty.name=Difficulty: setting.screenshake.name=Screen Shake setting.smoothcam.name=Smooth Camera setting.indicators.name=Enemy Indicators diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 06f121405a..27e307faa2 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -65,6 +65,7 @@ public class Control extends Module{ float extrawavetime; int enemies = 0; GameMode mode = GameMode.waves; + Difficulty difficulty = Difficulty.normal; Tile core; Array spawnpoints = new Array<>(); @@ -434,7 +435,11 @@ public class Control extends Module{ } public Difficulty getDifficulty(){ - return Difficulty.values()[Settings.getInt("difficulty")]; + return difficulty; + } + + public void setDifficulty(Difficulty d){ + this.difficulty = d; } public boolean isHighScore(){ diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index fcce85ac85..768268c2a2 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -8,6 +8,7 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.io.versions.Save12; import io.anuke.mindustry.io.versions.Save13; import io.anuke.mindustry.io.versions.Save14; +import io.anuke.mindustry.io.versions.Save15; import io.anuke.ucore.UCore; import io.anuke.ucore.core.Settings; @@ -18,7 +19,8 @@ public class SaveIO{ public static final Array versionArray = Array.with( new Save12(), new Save13(), - new Save14() + new Save14(), + new Save15() ); static{ diff --git a/core/src/io/anuke/mindustry/io/versions/Save15.java b/core/src/io/anuke/mindustry/io/versions/Save15.java index ef19964a16..c630d645b0 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save15.java +++ b/core/src/io/anuke/mindustry/io/versions/Save15.java @@ -1,13 +1,34 @@ package io.anuke.mindustry.io.versions; +import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.IntMap; +import com.badlogic.gdx.utils.TimeUtils; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.entities.enemies.Enemy; +import io.anuke.mindustry.entities.enemies.EnemyType; +import io.anuke.mindustry.game.Difficulty; +import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.io.SaveFileVersion; +import io.anuke.mindustry.resource.Item; +import io.anuke.mindustry.resource.Upgrade; +import io.anuke.mindustry.resource.Weapon; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.WorldGenerator; +import io.anuke.mindustry.world.blocks.Blocks; +import io.anuke.mindustry.world.blocks.types.BlockPart; +import io.anuke.mindustry.world.blocks.types.Rock; +import io.anuke.ucore.core.Core; +import io.anuke.ucore.entities.Entities; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Arrays; + +import static io.anuke.mindustry.Vars.android; public class Save15 extends SaveFileVersion { - private Save14 save = new Save14(); public Save15(){ super(15); @@ -15,11 +36,318 @@ public class Save15 extends SaveFileVersion { @Override public void read(DataInputStream stream) throws IOException { - + + int version = stream.readInt(); + /*long loadTime = */ + stream.readLong(); + + if(version != this.version){ + throw new RuntimeException("Save file version mismatch!"); + } + + //general state + byte mode = stream.readByte(); + byte mapid = stream.readByte(); + + int wave = stream.readInt(); + float wavetime = stream.readFloat(); + byte difficulty = stream.readByte(); + + Vars.control.setDifficulty(Difficulty.values()[difficulty]); + + //block header + + int blocksize = stream.readInt(); + + IntMap map = new IntMap<>(); + + for(int i = 0; i < blocksize; i ++){ + String name = readString(stream); + int id = stream.readShort(); + + map.put(id, Block.getByName(name)); + } + + float playerx = stream.readFloat(); + float playery = stream.readFloat(); + + int playerhealth = stream.readInt(); + + Vars.player.x = playerx; + Vars.player.y = playery; + Vars.player.health = playerhealth; + Vars.control.setMode(GameMode.values()[mode]); + Core.camera.position.set(playerx, playery, 0); + + //weapons + + Vars.control.getWeapons().clear(); + Vars.control.getWeapons().add(Weapon.blaster); + Vars.player.weaponLeft = Vars.player.weaponRight = Weapon.blaster; + + int weapons = stream.readByte(); + + for(int i = 0; i < weapons; i ++){ + Vars.control.addWeapon((Weapon) Upgrade.getByID(stream.readByte())); + } + + Vars.ui.hudfrag.updateWeapons(); + + //inventory + + int totalItems = stream.readByte(); + + Arrays.fill(Vars.control.getItems(), 0); + + for(int i = 0; i < totalItems; i ++){ + Item item = Item.getByID(stream.readByte()); + int amount = stream.readInt(); + Vars.control.getItems()[item.id] = amount; + } + + Vars.ui.hudfrag.updateItems(); + + //enemies + + Entities.clear(); + + int enemies = stream.readInt(); + + Array enemiesToUpdate = new Array<>(); + + for(int i = 0; i < enemies; i ++){ + byte type = stream.readByte(); + int lane = stream.readByte(); + float x = stream.readFloat(); + float y = stream.readFloat(); + byte tier = stream.readByte(); + int health = stream.readShort(); + + try{ + Enemy enemy = new Enemy(EnemyType.getByID(type)); + enemy.lane = lane; + enemy.health = health; + enemy.x = x; + enemy.y = y; + enemy.tier = tier; + enemy.add(Vars.control.enemyGroup); + enemiesToUpdate.add(enemy); + }catch (Exception e){ + throw new RuntimeException(e); + } + } + + Vars.control.setWaveData(enemies, wave, wavetime); + + if(!android) + Vars.player.add(); + + //map + + int seed = stream.readInt(); + + Vars.world.loadMap(Vars.world.maps().getMap(mapid), seed); + Vars.renderer.clearTiles(); + + for(Enemy enemy : enemiesToUpdate){ + enemy.node = -2; + } + + int rocks = stream.readInt(); + + for(int x = 0; x < Vars.world.width(); x ++){ + for(int y = 0; y < Vars.world.height(); y ++){ + Tile tile = Vars.world.tile(x, y); + + //remove breakables like rocks + if(tile.breakable()){ + Vars.world.tile(x, y).setBlock(Blocks.air); + } + } + } + + for(int i = 0; i < rocks; i ++){ + int pos = stream.readInt(); + Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + if(tile == null) continue; + Block result = WorldGenerator.rocks.get(tile.floor()); + if(result != null) tile.setBlock(result); + } + + int tiles = stream.readInt(); + + for(int i = 0; i < tiles; i ++){ + int pos = stream.readInt(); + int blockid = stream.readInt(); + + Tile tile = Vars.world.tile(pos % Vars.world.width(), pos / Vars.world.width()); + tile.setBlock(map.get(blockid)); + + if(blockid == Blocks.blockpart.id){ + tile.link = stream.readByte(); + } + + if(tile.entity != null){ + byte rotation = stream.readByte(); + short health = stream.readShort(); + int items = stream.readByte(); + + tile.entity.health = health; + tile.setRotation(rotation); + + for(int j = 0; j < items; j ++){ + int itemid = stream.readByte(); + int itemamount = stream.readInt(); + tile.entity.items[itemid] = itemamount; + } + + tile.entity.read(stream); + } + } } @Override public void write(DataOutputStream stream) throws IOException { + //--META-- + stream.writeInt(version); //version id + stream.writeLong(TimeUtils.millis()); //last saved + //--GENERAL STATE-- + stream.writeByte(Vars.control.getMode().ordinal()); //gamemode + stream.writeByte(Vars.world.getMap().id); //map ID + + stream.writeInt(Vars.control.getWave()); //wave + stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown + stream.writeByte(Vars.control.getDifficulty().ordinal()); + + //--BLOCK HEADER-- + + stream.writeInt(Block.getAllBlocks().size); + + for(int i = 0; i < Block.getAllBlocks().size; i ++){ + Block block = Block.getAllBlocks().get(i); + writeString(stream, block.name); + stream.writeShort(block.id); + } + + stream.writeFloat(Vars.player.x); //player x/y + stream.writeFloat(Vars.player.y); + + stream.writeInt(Vars.player.health); //player health + + stream.writeByte(Vars.control.getWeapons().size - 1); //amount of weapons + + //start at 1, because the first weapon is always the starter - ignore that + for(int i = 1; i < Vars.control.getWeapons().size; i ++){ + stream.writeByte(Vars.control.getWeapons().get(i).id); //weapon ordinal + } + + //--INVENTORY-- + + int l = Vars.control.getItems().length; + int itemsize = 0; + + for(int i = 0; i < l; i ++){ + if(Vars.control.getItems()[i] > 0){ + itemsize ++; + } + } + + stream.writeByte(itemsize); //amount of items + + for(int i = 0; i < l; i ++){ + if(Vars.control.getItems()[i] > 0){ + stream.writeByte(i); //item ID + stream.writeInt(Vars.control.getItems()[i]); //item amount + } + } + + //--ENEMIES-- + + Array enemies = Vars.control.enemyGroup.all(); + + stream.writeInt(enemies.size); //enemy amount + + for(int i = 0; i < enemies.size; i ++){ + Enemy enemy = enemies.get(i); + stream.writeByte(enemy.type.id); //type + stream.writeByte(enemy.lane); //lane + stream.writeFloat(enemy.x); //x + stream.writeFloat(enemy.y); //y + stream.writeByte(enemy.tier); //tier + stream.writeShort(enemy.health); //health + } + + //--MAP DATA-- + + //seed + stream.writeInt(Vars.world.getSeed()); + + int totalblocks = 0; + int totalrocks = 0; + + for(int x = 0; x < Vars.world.width(); x ++){ + for(int y = 0; y < Vars.world.height(); y ++){ + Tile tile = Vars.world.tile(x, y); + + if(tile.breakable()){ + if(tile.block() instanceof Rock){ + totalrocks ++; + }else{ + totalblocks ++; + } + } + } + } + + //amount of rocks + stream.writeInt(totalrocks); + + //write all rocks + for(int x = 0; x < Vars.world.width(); x ++) { + for (int y = 0; y < Vars.world.height(); y++) { + Tile tile = Vars.world.tile(x, y); + + if (tile.block() instanceof Rock) { + stream.writeInt(tile.packedPosition()); + } + } + } + + //write all blocks + stream.writeInt(totalblocks); + + for(int x = 0; x < Vars.world.width(); x ++){ + for(int y = 0; y < Vars.world.height(); y ++){ + Tile tile = Vars.world.tile(x, y); + + if(tile.breakable() && !(tile.block() instanceof Rock)){ + + stream.writeInt(x + y*Vars.world.width()); //tile pos + stream.writeInt(tile.block().id); //block ID + + if(tile.block() instanceof BlockPart) stream.writeByte(tile.link); + + if(tile.entity != null){ + stream.writeByte(tile.getRotation()); //rotation + stream.writeShort(tile.entity.health); //health + byte amount = 0; + for(int i = 0; i < tile.entity.items.length; i ++){ + if(tile.entity.items[i] > 0) amount ++; + } + stream.writeByte(amount); //amount of items + + for(int i = 0; i < tile.entity.items.length; i ++){ + if(tile.entity.items[i] > 0){ + stream.writeByte(i); //item ID + stream.writeInt(tile.entity.items[i]); //item amount + } + } + + tile.entity.write(stream); + } + } + } + } } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java index 798fde68d1..f219129e1f 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LevelDialog.java @@ -1,20 +1,22 @@ package io.anuke.mindustry.ui.dialogs; import com.badlogic.gdx.graphics.g2d.TextureRegion; - import io.anuke.mindustry.Vars; +import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.world.Map; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.scene.event.ClickListener; import io.anuke.ucore.scene.event.InputEvent; +import io.anuke.ucore.scene.event.Touchable; import io.anuke.ucore.scene.ui.*; import io.anuke.ucore.scene.ui.layout.Stack; import io.anuke.ucore.scene.ui.layout.Table; -import io.anuke.ucore.scene.event.ClickListener; import io.anuke.ucore.scene.utils.Elements; import io.anuke.ucore.util.Bundles; +import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Tmp; public class LevelDialog extends FloatingDialog{ @@ -56,7 +58,34 @@ public class LevelDialog extends FloatingDialog{ content().add(selmode); content().row(); - + + Difficulty[] ds = Difficulty.values(); + + float s = 50f; + + Table sdif = new Table(); + + sdif.add("$setting.difficulty.name").padRight(15f); + + sdif.defaults().height(s+4); + sdif.addImageButton("icon-arrow-left", 10*3, () -> { + Vars.control.setDifficulty(ds[Mathf.mod(Vars.control.getDifficulty().ordinal() - 1, ds.length)]); + }).width(s); + + sdif.addButton("", () -> { + + }).update(t -> { + t.setText(Vars.control.getDifficulty().toString()); + t.setTouchable(Touchable.disabled); + }).width(180f); + + sdif.addImageButton("icon-arrow-right", 10*3, () -> { + Vars.control.setDifficulty(ds[Mathf.mod(Vars.control.getDifficulty().ordinal() + 1, ds.length)]); + }).width(s); + + content().add(sdif); + content().row(); + int i = 0; for(Map map : Vars.world.maps().list()){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index e6008ebefa..cf1bd4187c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -7,7 +7,6 @@ import com.badlogic.gdx.utils.Align; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.net.Net; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Settings; @@ -107,7 +106,7 @@ public class SettingsMenuDialog extends SettingsDialog{ void addSettings(){ sound.volumePrefs(); - game.sliderPref("difficulty", 1, 0, Difficulty.values().length-1, i -> Difficulty.values()[i].toString()); + //game.sliderPref("difficulty", 1, 0, Difficulty.values().length-1, i -> Difficulty.values()[i].toString()); game.screenshakePref(); game.checkPref("smoothcam", true); game.checkPref("effects", true);