diff options
Diffstat (limited to 'core/src')
7 files changed, 224 insertions, 79 deletions
diff --git a/core/src/com/ilotterytea/maxoning/MaxonGame.java b/core/src/com/ilotterytea/maxoning/MaxonGame.java index 0ad6a8d..f361d20 100644 --- a/core/src/com/ilotterytea/maxoning/MaxonGame.java +++ b/core/src/com/ilotterytea/maxoning/MaxonGame.java @@ -9,8 +9,6 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.ilotterytea.maxoning.screens.SplashScreen; import com.ilotterytea.maxoning.utils.I18N; -import java.io.IOException; - public class MaxonGame extends Game { public SpriteBatch batch; public ShapeRenderer shapeRenderer; diff --git a/core/src/com/ilotterytea/maxoning/player/MaxonSavegame.java b/core/src/com/ilotterytea/maxoning/player/MaxonSavegame.java new file mode 100644 index 0000000..301840b --- /dev/null +++ b/core/src/com/ilotterytea/maxoning/player/MaxonSavegame.java @@ -0,0 +1,40 @@ +package com.ilotterytea.maxoning.player; + +import java.io.Serializable; +import java.util.ArrayList; + +/** + * Save-game data class. + * @author NotDankEnough + * @since Alpha 1.2 (Oct 02, 2022) + */ +public class MaxonSavegame implements Serializable { + /** Earned Squish Points. */ + public int points; + /** Multiplier. */ + public short multiplier; + + /** Home inventory. */ + public ArrayList<Integer> inv; + /** Outside Inventory. */ + public ArrayList<Integer> outInv; + + /** Seed. */ + public long seed; + + /** Player name. */ + public String name; + /** Pet name. */ + public String petName; + /** Pet ID. */ + public byte petId; + + /** Elapsed time from game start. */ + public long elapsedTime; + + /** Last timestamp when save game was used. */ + public long lastTimestamp; + + /** Location. */ + public short roomId; +}
\ No newline at end of file diff --git a/core/src/com/ilotterytea/maxoning/screens/GameScreen.java b/core/src/com/ilotterytea/maxoning/screens/GameScreen.java index a3a551b..8e4538d 100644 --- a/core/src/com/ilotterytea/maxoning/screens/GameScreen.java +++ b/core/src/com/ilotterytea/maxoning/screens/GameScreen.java @@ -20,7 +20,7 @@ import com.ilotterytea.maxoning.anim.SpriteUtils; import com.ilotterytea.maxoning.inputprocessors.CrossProcessor; import com.ilotterytea.maxoning.player.MaxonItem; import com.ilotterytea.maxoning.player.MaxonItemRegister; -import com.ilotterytea.maxoning.player.MaxonPlayer; +import com.ilotterytea.maxoning.player.MaxonSavegame; import com.ilotterytea.maxoning.ui.*; import com.ilotterytea.maxoning.utils.serialization.GameDataSystem; import com.rafaskoberg.gdx.typinglabel.TypingLabel; @@ -32,8 +32,10 @@ import java.util.Map; public class GameScreen implements Screen, InputProcessor { final MaxonGame game; + final int slotId; + final long playTimestamp; - MaxonPlayer player; + MaxonSavegame player; Stage stage; Skin skin, widgetSkin; @@ -53,8 +55,10 @@ public class GameScreen implements Screen, InputProcessor { ArrayList<ArrayList<Sprite>> bgTiles; - public GameScreen(MaxonGame game, MaxonPlayer sav) throws IOException, ClassNotFoundException { + public GameScreen(MaxonGame game, MaxonSavegame sav, int slotId) throws IOException, ClassNotFoundException { this.game = game; + this.slotId = slotId; + this.playTimestamp = System.currentTimeMillis(); player = sav; @@ -68,7 +72,7 @@ public class GameScreen implements Screen, InputProcessor { items = new ArrayList<>(); - for (int id : player.purchasedItems) { + for (int id : player.inv) { items.add(MaxonItemRegister.get(id)); } @@ -98,7 +102,7 @@ public class GameScreen implements Screen, InputProcessor { invItems = new HashMap<>(); - for (Integer id : player.purchasedItems) { + for (Integer id : player.inv) { if (invItems.containsKey(id)) { invItems.put(id, invItems.get(id) + 1); } else { @@ -141,13 +145,13 @@ public class GameScreen implements Screen, InputProcessor { if (player.points > item.price) { player.points -= item.price; player.multiplier += item.multiplier; - player.purchasedItems.add(item.id); + player.inv.add(item.id); items.add(item); invItems.clear(); inventoryTable.clear(); - for (Integer id : player.purchasedItems) { + for (Integer id : player.inv) { if (invItems.containsKey(id)) { invItems.put(id, invItems.get(id) + 1); } else { @@ -246,7 +250,7 @@ public class GameScreen implements Screen, InputProcessor { player.points += multiplier; - final TypingLabel label = new TypingLabel(game.locale.FormattedText("game.newPoint", MaxonConstants.DECIMAL_FORMAT.format(1 * player.multiplier)), skin, "default"); + final TypingLabel label = new TypingLabel(game.locale.FormattedText("game.newPoint", MaxonConstants.DECIMAL_FORMAT.format(player.multiplier)), skin, "default"); label.setPosition( mainTable.getX() + actor.getActorX(), @@ -383,11 +387,9 @@ public class GameScreen implements Screen, InputProcessor { @Override public boolean keyDown(int keycode) { if (Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) { - try { - GameDataSystem.SaveData(player); - } catch (IOException e) { - throw new RuntimeException(e); - } + player.lastTimestamp = System.currentTimeMillis(); + player.elapsedTime = (System.currentTimeMillis() - playTimestamp) + player.elapsedTime; + GameDataSystem.save(player, String.format("0%s.maxon", (slotId >= 0) ? slotId : "latest")); game.setScreen(new MenuScreen(game)); dispose(); @@ -404,9 +406,9 @@ public class GameScreen implements Screen, InputProcessor { cat.nextFrame(); maxon.setDrawable(cat.getDrawable()); - player.points += 1 * player.multiplier; + player.points += player.multiplier; - final TypingLabel label = new TypingLabel(game.locale.FormattedText("game.newPoint", MaxonConstants.DECIMAL_FORMAT.format(1 * player.multiplier)), skin, "default"); + final TypingLabel label = new TypingLabel(game.locale.FormattedText("game.newPoint", MaxonConstants.DECIMAL_FORMAT.format(player.multiplier)), skin, "default"); label.setPosition( mainTable.getX() + actor.getActorX(), diff --git a/core/src/com/ilotterytea/maxoning/screens/MenuScreen.java b/core/src/com/ilotterytea/maxoning/screens/MenuScreen.java index 135d0e9..c796d22 100644 --- a/core/src/com/ilotterytea/maxoning/screens/MenuScreen.java +++ b/core/src/com/ilotterytea/maxoning/screens/MenuScreen.java @@ -2,7 +2,6 @@ package com.ilotterytea.maxoning.screens; import com.badlogic.gdx.*; import com.badlogic.gdx.audio.Music; -import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.*; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureAtlas; @@ -17,12 +16,13 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.viewport.FillViewport; import com.ilotterytea.maxoning.MaxonConstants; import com.ilotterytea.maxoning.MaxonGame; -import com.ilotterytea.maxoning.player.MaxonPlayer; +import com.ilotterytea.maxoning.player.MaxonSavegame; import com.ilotterytea.maxoning.ui.*; import com.ilotterytea.maxoning.utils.math.Math; +import com.ilotterytea.maxoning.utils.serialization.GameDataSystem; +import java.io.File; import java.io.IOException; -import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Calendar; @@ -265,19 +265,18 @@ public class MenuScreen implements Screen { } private void loadSavegamesToTable(Table table) { - FileHandle folder = Gdx.files.external(MaxonConstants.GAME_SAVEGAME_FOLDER); - - try { - for (FileHandle fh : folder.list()) { - final MaxonPlayer sav = (MaxonPlayer) new ObjectInputStream(fh.read()).readObject(); + for (int i = 0; i < 3; i++) { + if (new File(MaxonConstants.GAME_SAVEGAME_FOLDER + String.format("/0%s.maxon", i)).exists()) { + final MaxonSavegame sav = GameDataSystem.load("0" + i + ".maxon"); SaveGameWidget widget = new SaveGameWidget( skin, widgetSkin, sav ); + final int finalI = i; widget.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { try { - game.setScreen(new GameScreen(game, sav)); + game.setScreen(new GameScreen(game, sav, finalI)); } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); } @@ -285,29 +284,39 @@ public class MenuScreen implements Screen { } }); table.add(widget).width(512f).padBottom(8f).row(); - } - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } + } else { + + final MaxonSavegame sav = new MaxonSavegame(); + final SaveGameWidget widget = new SaveGameWidget( + skin, widgetSkin, null + ); + final int finalI = i; + widget.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + sav.petId = 0; + sav.inv = new ArrayList<>(); + sav.multiplier = 5; + sav.points = 0; + sav.roomId = 0; + sav.seed = System.currentTimeMillis(); + sav.name = "SAVE " + (finalI + 1); + sav.elapsedTime = 0; + sav.lastTimestamp = System.currentTimeMillis(); + sav.outInv = new ArrayList<>(); + + GameDataSystem.save(sav, "0" + finalI + ".maxon"); - for (int i = 0; i < 3 - folder.list().length; i++) { - final MaxonPlayer sav = new MaxonPlayer(); - SaveGameWidget widget = new SaveGameWidget( - skin, widgetSkin, null - ); - final int finalI = i; - widget.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - try { - game.setScreen(new GameScreen(game, sav)); - } catch (IOException | ClassNotFoundException e) { - throw new RuntimeException(e); + try { + game.setScreen(new GameScreen(game, sav, finalI)); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + dispose(); } - dispose(); - } - }); - table.add(widget).width(512f).padBottom(8f).row(); + }); + table.add(widget).width(512f).padBottom(8f).row(); + } } } diff --git a/core/src/com/ilotterytea/maxoning/screens/SplashScreen.java b/core/src/com/ilotterytea/maxoning/screens/SplashScreen.java index 31a1023..ccae6b1 100644 --- a/core/src/com/ilotterytea/maxoning/screens/SplashScreen.java +++ b/core/src/com/ilotterytea/maxoning/screens/SplashScreen.java @@ -14,8 +14,11 @@ import com.badlogic.gdx.utils.Timer; import com.badlogic.gdx.utils.viewport.FillViewport; import com.ilotterytea.maxoning.MaxonGame; import com.ilotterytea.maxoning.utils.AssetLoading; +import com.ilotterytea.maxoning.utils.OsUtils; import com.ilotterytea.maxoning.utils.math.Math; +import com.ilotterytea.maxoning.utils.serialization.GameDataSystem; +import java.io.IOException; import java.util.ArrayList; public class SplashScreen implements Screen { @@ -97,7 +100,15 @@ public class SplashScreen implements Screen { private void update() { if (game.assetManager.update()) { AssetLoading.registerItems(game.assetManager, game.locale); - game.setScreen(new MenuScreen(game)); + if (OsUtils.isAndroid || OsUtils.isIos) { + try { + game.setScreen(new GameScreen(game, GameDataSystem.load("latest.sav"), -1)); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + game.setScreen(new MenuScreen(game)); + } dispose(); } } diff --git a/core/src/com/ilotterytea/maxoning/ui/SaveGameWidget.java b/core/src/com/ilotterytea/maxoning/ui/SaveGameWidget.java index cd6fa72..2bb4a81 100644 --- a/core/src/com/ilotterytea/maxoning/ui/SaveGameWidget.java +++ b/core/src/com/ilotterytea/maxoning/ui/SaveGameWidget.java @@ -1,17 +1,18 @@ package com.ilotterytea.maxoning.ui; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.utils.Align; -import com.ilotterytea.maxoning.player.MaxonPlayer; +import com.badlogic.gdx.utils.Null; +import com.ilotterytea.maxoning.player.MaxonSavegame; import com.ilotterytea.maxoning.utils.formatters.NumberFormatter; - public class SaveGameWidget extends Button { public SaveGameWidget( Skin skin, Skin widgetSkin, - MaxonPlayer sav + @Null MaxonSavegame sav ) { // Setting the stack: super(widgetSkin, "slot"); @@ -20,14 +21,27 @@ public class SaveGameWidget extends Button { // // Info row: Table infoTable = new Table(); - // Top left label: - Label topleftLabel = new Label(String.format("%s Squish Points", (sav != null) ? NumberFormatter.format((long) sav.points) : "---"), skin); + // Top left label (name): + Label topleftLabel = new Label((sav != null) ? sav.name : "[EMPTY]", skin); topleftLabel.setAlignment(Align.left); infoTable.add(topleftLabel).width(256f); - // Top right label: + // Top right label (elapsed time): + String time = "--:--"; + + if (sav != null) { + long h = sav.elapsedTime / 1000 / 60 / 60; + long m = sav.elapsedTime / 1000 / 60; + + time = String.format( + "%s:%s", + ((h < 10) ? "0" : "") + h, + ((m < 10) ? "0" : "") + m + ); + } + Label toprightLabel = new Label( - String.format("%s purchased items", (sav != null) ? sav.purchasedItems.size() : "---"), + time, skin ); toprightLabel.setAlignment(Align.right); @@ -36,34 +50,41 @@ public class SaveGameWidget extends Button { // // Description row: Table descTable = new Table(); - // Bottom left label: + // Bottom left label (purchased items): Label bottomleftLabel = new Label( String.format( - "x%s", - (sav != null) ? NumberFormatter.format((long) sav.multiplier) : "?" + "%s purchased items", + (sav != null) ? sav.inv.size() : "?" ), skin ); bottomleftLabel.setAlignment(Align.left); descTable.add(bottomleftLabel).width(256f); - /* NOT IN USE. Bottom right label: + // Bottom right label (points/multiplier): Label pointsLabel = new Label( String.format( "%s$/x%s", - NumberFormatter.format(points), - NumberFormatter.format(multiplier) + (sav != null) ? NumberFormatter.format(sav.points) : "---", + (sav != null) ? NumberFormatter.format(sav.multiplier) : "0" ), skin ); pointsLabel.setAlignment(Align.right); - descTable.add(pointsLabel).width(256f);*/ + descTable.add(pointsLabel).width(256f); // Adding the tables to main table: Table summaryTable = new Table(); summaryTable.add(infoTable).pad(5f).row(); summaryTable.add(descTable).pad(5f).row(); + if (sav == null) { + topleftLabel.setColor(Color.DARK_GRAY); + toprightLabel.setColor(Color.DARK_GRAY); + bottomleftLabel.setColor(Color.DARK_GRAY); + pointsLabel.setColor(Color.DARK_GRAY); + } + super.add(summaryTable); } } diff --git a/core/src/com/ilotterytea/maxoning/utils/serialization/GameDataSystem.java b/core/src/com/ilotterytea/maxoning/utils/serialization/GameDataSystem.java index a10d98a..3e64c45 100644 --- a/core/src/com/ilotterytea/maxoning/utils/serialization/GameDataSystem.java +++ b/core/src/com/ilotterytea/maxoning/utils/serialization/GameDataSystem.java @@ -1,35 +1,99 @@ package com.ilotterytea.maxoning.utils.serialization; +import com.badlogic.gdx.utils.Null; +import com.google.gson.Gson; import com.ilotterytea.maxoning.MaxonConstants; -import com.ilotterytea.maxoning.player.MaxonPlayer; +import com.ilotterytea.maxoning.player.MaxonSavegame; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.*; +import java.util.ArrayList; +/** + * External game data system control. + * @author NotDankEnough + * @since Alpha 1.0 + */ public class GameDataSystem { private static final File dir = new File(MaxonConstants.GAME_SAVEGAME_FOLDER); - private static final File file = new File(dir.getPath() + "/savegame.sav"); + private static final Gson gson = new Gson(); + private static final Logger log = LoggerFactory.getLogger(GameDataSystem.class.getSimpleName()); - public static boolean exists() { return file.exists(); } + /** + * Get all savefiles from savegame directory (/.Maxoning/savegames/) + * @return Array of MaxonSavegames + * @see MaxonSavegame + */ + public static ArrayList<MaxonSavegame> getSavegames() { + ArrayList<MaxonSavegame> saves = new ArrayList<>(); + File[] files = dir.listFiles(); - public static void SaveData(MaxonPlayer player) throws IOException { - if (!dir.exists()) { - dir.mkdirs(); + assert files != null; + for (File file : files) { + try { + + FileInputStream fis = new FileInputStream(file); + ObjectInputStream ois = new ObjectInputStream(fis); + + MaxonSavegame sav = gson.fromJson(ois.readUTF(), MaxonSavegame.class); + saves.add(sav); + + ois.close(); + fis.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } } - FileOutputStream fo = new FileOutputStream(file); - ObjectOutputStream out = new ObjectOutputStream(fo); - out.writeObject(player); - out.close(); + return saves; + } + + /** + * Convert <b>MaxonSavegame</b> class to <b>JSON</b> string and write in UTF-8 encoding (I'm sorry, encryption enjoyers). + * @param savegame Save game object. + * @param file_name File name. + * @see MaxonSavegame + */ + public static void save(@NotNull MaxonSavegame savegame, @NotNull String file_name) { + try { + log.info("Saving the game..."); + FileOutputStream fos = new FileOutputStream(String.format("%s/%s", dir.getAbsolutePath(), file_name)); + ObjectOutputStream oos = new ObjectOutputStream(fos); + + oos.writeUTF(gson.toJson(savegame)); + oos.close(); + log.info(String.format("Success! Savegame located at %s/%s", dir.getAbsolutePath(), file_name)); + } catch (IOException e) { + throw new RuntimeException(e); + } } - public static MaxonPlayer LoadData() throws IOException, ClassNotFoundException { - FileInputStream fi = new FileInputStream(file); - ObjectInputStream oi = new ObjectInputStream(fi); + /** + * Reading a <b>JSON</b> string from the file and convert to <b>MaxonSavegame</b> class. + * @param file_name File name. If null - it will get the first file by last modified time. + * @return Filled <b>MaxonSavegame</b> class + * @see MaxonSavegame + */ + public static MaxonSavegame load(@Null String file_name) { + MaxonSavegame sav = new MaxonSavegame(); + + if (new File(dir.getAbsolutePath() + "/" + file_name).exists()) { + try { + log.info(String.format("Trying to get the savegame at %s/%s...", dir.getAbsolutePath(), file_name)); + FileInputStream fis = new FileInputStream(String.format("%s/%s", dir.getAbsolutePath(), file_name)); + ObjectInputStream oos = new ObjectInputStream(fis); - MaxonPlayer pl = (MaxonPlayer) oi.readObject(); + sav = gson.fromJson(oos.readUTF(), MaxonSavegame.class); + oos.close(); + + log.info(String.format("Successfully loaded the savegame from %s/%s!", dir.getAbsolutePath(), file_name)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } - oi.close(); - fi.close(); - return pl; + return sav; } } |
