diff --git a/AndroidManifest.xml b/AndroidManifest.xml index c941f22f1c..130b4bb602 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,6 +1,6 @@ @@ -28,7 +28,7 @@ diff --git a/assets/banners.png b/assets/banners.png index 1b0923d161..415668b370 100644 Binary files a/assets/banners.png and b/assets/banners.png differ diff --git a/res/values/strings.xml b/res/values/strings.xml index b81e1a4a95..06ccdb07e6 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,6 +1,6 @@ - Pixel Dungeon + Pixel Dungeon Undone diff --git a/src/com/watabou/pixeldungeon/Dungeon.java b/src/com/watabou/pixeldungeon/Dungeon.java index ca15741923..a270fb0f79 100644 --- a/src/com/watabou/pixeldungeon/Dungeon.java +++ b/src/com/watabou/pixeldungeon/Dungeon.java @@ -17,6 +17,8 @@ */ package com.watabou.pixeldungeon; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -61,6 +63,7 @@ import com.watabou.pixeldungeon.scenes.StartScene; import com.watabou.pixeldungeon.ui.QuickSlot; import com.watabou.pixeldungeon.utils.BArray; +import com.watabou.pixeldungeon.utils.FIFO; import com.watabou.pixeldungeon.utils.Utils; import com.watabou.pixeldungeon.windows.WndResurrect; import com.watabou.utils.Bundlable; @@ -95,14 +98,18 @@ public class Dungeon { public static boolean nightMode; public static SparseArray> droppedItems; - + + final static int undoLength = 10; + public static FIFO undoGameBuffer; + public static FIFO undoLevelBuffer; + public static void init() { challenges = PixelDungeon.challenges(); Actor.clear(); - PathFinder.setMapSize( Level.WIDTH, Level.HEIGHT ); + PathFinder.setMapSize(Level.WIDTH, Level.HEIGHT); Scroll.initLabels(); Potion.initColors(); @@ -116,7 +123,10 @@ public static void init() { gold = 0; droppedItems = new SparseArray>(); - + + undoGameBuffer = new FIFO<>(undoLength); + undoLevelBuffer = new FIFO<>(undoLength); + potionOfStrength = 0; scrollsOfUpgrade = 0; scrollsOfEnchantment = 0; @@ -361,64 +371,95 @@ private static String depthFile( HeroClass cl ) { return RG_DEPTH_FILE; } } - + + public static Bundle saveGameBundle () { + Bundle bundle = new Bundle(); + + bundle.put( VERSION, Game.version ); + bundle.put( CHALLENGES, challenges ); + bundle.put( HERO, hero ); + bundle.put( GOLD, gold ); + bundle.put( DEPTH, depth ); + + for (int d : droppedItems.keyArray()) { + bundle.put( String.format( DROPPED, d ), droppedItems.get( d ) ); + } + + bundle.put( POS, potionOfStrength ); + bundle.put( SOU, scrollsOfUpgrade ); + bundle.put( SOE, scrollsOfEnchantment ); + bundle.put( DV, dewVial ); + bundle.put( WT, transmutation ); + + int count = 0; + int ids[] = new int[chapters.size()]; + for (Integer id : chapters) { + ids[count++] = id; + } + bundle.put( CHAPTERS, ids ); + + Bundle quests = new Bundle(); + Ghost .Quest.storeInBundle( quests ); + Wandmaker .Quest.storeInBundle( quests ); + Blacksmith .Quest.storeInBundle( quests ); + Imp .Quest.storeInBundle( quests ); + bundle.put( QUESTS, quests ); + + Room.storeRoomsInBundle( bundle ); + + Statistics.storeInBundle( bundle ); + Journal.storeInBundle( bundle ); + + QuickSlot.save( bundle ); + + Scroll.save( bundle ); + Potion.save( bundle ); + Wand.save( bundle ); + Ring.save( bundle ); + + Bundle badges = new Bundle(); + Badges.saveLocal( badges ); + bundle.put( BADGES, badges ); + + return bundle; + + } + + public static void saveUndo () { + + Actor.fixTime(); + ByteArrayOutputStream bos; + try { + Bundle gameBundle = saveGameBundle(); + + bos = new ByteArrayOutputStream(); + Bundle.write(gameBundle, bos); + undoGameBuffer.add(bos.toByteArray()); + bos.close(); + + Bundle levelBundle = new Bundle(); + levelBundle.put(LEVEL, level); + + bos = new ByteArrayOutputStream(); + Bundle.write(levelBundle, bos); + undoLevelBuffer.add(bos.toByteArray()); + bos.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + public static void saveGame( String fileName ) throws IOException { try { - Bundle bundle = new Bundle(); - - bundle.put( VERSION, Game.version ); - bundle.put( CHALLENGES, challenges ); - bundle.put( HERO, hero ); - bundle.put( GOLD, gold ); - bundle.put( DEPTH, depth ); - - for (int d : droppedItems.keyArray()) { - bundle.put( String.format( DROPPED, d ), droppedItems.get( d ) ); - } - - bundle.put( POS, potionOfStrength ); - bundle.put( SOU, scrollsOfUpgrade ); - bundle.put( SOE, scrollsOfEnchantment ); - bundle.put( DV, dewVial ); - bundle.put( WT, transmutation ); - - int count = 0; - int ids[] = new int[chapters.size()]; - for (Integer id : chapters) { - ids[count++] = id; - } - bundle.put( CHAPTERS, ids ); - - Bundle quests = new Bundle(); - Ghost .Quest.storeInBundle( quests ); - Wandmaker .Quest.storeInBundle( quests ); - Blacksmith .Quest.storeInBundle( quests ); - Imp .Quest.storeInBundle( quests ); - bundle.put( QUESTS, quests ); - - Room.storeRoomsInBundle( bundle ); - - Statistics.storeInBundle( bundle ); - Journal.storeInBundle( bundle ); - - QuickSlot.save( bundle ); - - Scroll.save( bundle ); - Potion.save( bundle ); - Wand.save( bundle ); - Ring.save( bundle ); - - Bundle badges = new Bundle(); - Badges.saveLocal( badges ); - bundle.put( BADGES, badges ); - + Bundle bundle = saveGameBundle(); OutputStream output = Game.instance.openFileOutput( fileName, Game.MODE_PRIVATE ); - Bundle.write( bundle, output ); + Bundle.write(bundle, output); output.close(); } catch (Exception e) { - GamesInProgress.setUnknown( hero.heroClass ); + GamesInProgress.setUnknown(hero.heroClass); } } @@ -455,10 +496,22 @@ public static void loadGame( HeroClass cl ) throws IOException { public static void loadGame( String fileName ) throws IOException { loadGame( fileName, false ); } - + + public static void loadGame( int undoLocation) { + + try { + loadGame(gameBundle(undoLocation), true); + } catch (IOException e) { + e.printStackTrace(); + } + } + public static void loadGame( String fileName, boolean fullLoad ) throws IOException { - - Bundle bundle = gameBundle( fileName ); + loadGame(gameBundle(fileName), fullLoad); + + } + + public static void loadGame( Bundle bundle, boolean fullLoad ) throws IOException { Dungeon.challenges = bundle.getInt( CHALLENGES ); @@ -539,19 +592,25 @@ public static void loadGame( String fileName, boolean fullLoad ) throws IOExcept } } } - - public static Level loadLevel( HeroClass cl ) throws IOException { - + + public static Level loadLevel( InputStream input) throws IOException { Dungeon.level = null; Actor.clear(); - - InputStream input = Game.instance.openFileInput( Utils.format( depthFile( cl ), depth ) ) ; + Bundle bundle = Bundle.read( input ); input.close(); - + return (Level)bundle.get( "level" ); } + public static Level loadLevel( HeroClass cl ) throws IOException { + return loadLevel(Game.instance.openFileInput( Utils.format( depthFile( cl ), depth ) )) ; + } + + public static Level loadLevel( int undoLocation) throws IOException { + return loadLevel(new ByteArrayInputStream( undoLevelBuffer.get(undoLocation))); + } + public static void deleteGame( HeroClass cl, boolean deleteLevels ) { Game.instance.deleteFile( gameFile( cl ) ); @@ -563,17 +622,22 @@ public static void deleteGame( HeroClass cl, boolean deleteLevels ) { } } - GamesInProgress.delete( cl ); + GamesInProgress.delete(cl); } - - public static Bundle gameBundle( String fileName ) throws IOException { - - InputStream input = Game.instance.openFileInput( fileName ); - Bundle bundle = Bundle.read( input ); + + public static Bundle gameBundle( InputStream input ) throws IOException { + Bundle bundle = Bundle.read(input); input.close(); - return bundle; } + + public static Bundle gameBundle( int undoLocation ) throws IOException { + return gameBundle(new ByteArrayInputStream( undoGameBuffer.get(undoLocation) )); + } + + public static Bundle gameBundle( String fileName ) throws IOException { + return gameBundle(Game.instance.openFileInput( fileName )); + } public static void preview( GamesInProgress.Info info, Bundle bundle ) { info.depth = bundle.getInt( DEPTH ); diff --git a/src/com/watabou/pixeldungeon/actors/hero/Hero.java b/src/com/watabou/pixeldungeon/actors/hero/Hero.java index 8aae3b26ae..c932609911 100644 --- a/src/com/watabou/pixeldungeon/actors/hero/Hero.java +++ b/src/com/watabou/pixeldungeon/actors/hero/Hero.java @@ -398,7 +398,7 @@ public boolean act() { return false; } else { - + restoreHealth = false; ready = false; @@ -466,7 +466,8 @@ private void ready() { sprite.idle(); curAction = null; ready = true; - + + Dungeon.saveUndo(); GameScene.ready(); } diff --git a/src/com/watabou/pixeldungeon/actors/mobs/Mimic.java b/src/com/watabou/pixeldungeon/actors/mobs/Mimic.java index 0cfdf5146a..25afa8a672 100644 --- a/src/com/watabou/pixeldungeon/actors/mobs/Mimic.java +++ b/src/com/watabou/pixeldungeon/actors/mobs/Mimic.java @@ -36,6 +36,7 @@ import com.watabou.pixeldungeon.levels.Level; import com.watabou.pixeldungeon.scenes.GameScene; import com.watabou.pixeldungeon.sprites.MimicSprite; +import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; import com.watabou.utils.Random; @@ -64,7 +65,10 @@ public void storeInBundle( Bundle bundle ) { @Override public void restoreFromBundle( Bundle bundle ) { super.restoreFromBundle( bundle ); - items = new ArrayList( (Collection) bundle.getCollection( ITEMS ) ); + items = new ArrayList(); + for (Bundlable bund: bundle.getCollection( ITEMS )) { + items.add((Item) bund); + } adjustStats( bundle.getInt( LEVEL ) ); } diff --git a/src/com/watabou/pixeldungeon/items/Heap.java b/src/com/watabou/pixeldungeon/items/Heap.java index 70c9d8c6ef..e49d55a342 100644 --- a/src/com/watabou/pixeldungeon/items/Heap.java +++ b/src/com/watabou/pixeldungeon/items/Heap.java @@ -360,7 +360,11 @@ public void destroy() { public void restoreFromBundle( Bundle bundle ) { pos = bundle.getInt( POS ); type = Type.valueOf( bundle.getString( TYPE ) ); - items = new LinkedList( (Collection) bundle.getCollection( ITEMS ) ); + + items = new LinkedList(); + for (Bundlable bun : bundle.getCollection( ITEMS )) { + items.add( (Item) bun); + } } @Override diff --git a/src/com/watabou/pixeldungeon/levels/RegularLevel.java b/src/com/watabou/pixeldungeon/levels/RegularLevel.java index fa86652c1f..90b4794e15 100644 --- a/src/com/watabou/pixeldungeon/levels/RegularLevel.java +++ b/src/com/watabou/pixeldungeon/levels/RegularLevel.java @@ -33,6 +33,7 @@ import com.watabou.pixeldungeon.items.scrolls.ScrollOfUpgrade; import com.watabou.pixeldungeon.levels.Room.Type; import com.watabou.pixeldungeon.levels.painters.*; +import com.watabou.utils.Bundlable; import com.watabou.utils.Bundle; import com.watabou.utils.Graph; import com.watabou.utils.Random; @@ -681,8 +682,11 @@ public void storeInBundle( Bundle bundle ) { @Override public void restoreFromBundle( Bundle bundle ) { super.restoreFromBundle( bundle ); - - rooms = new HashSet( (Collection) bundle.getCollection( "rooms" ) ); + rooms = new HashSet(); + for (Bundlable bund: bundle.getCollection( "rooms" ) ) { + rooms.add((Room) bund); + } + for (Room r : rooms) { if (r.type == Type.WEAK_FLOOR) { weakFloorCreated = true; diff --git a/src/com/watabou/pixeldungeon/scenes/InterlevelScene.java b/src/com/watabou/pixeldungeon/scenes/InterlevelScene.java index 4ded60b4be..bb3a3aaa34 100644 --- a/src/com/watabou/pixeldungeon/scenes/InterlevelScene.java +++ b/src/com/watabou/pixeldungeon/scenes/InterlevelScene.java @@ -43,12 +43,13 @@ public class InterlevelScene extends PixelScene { private static final String TXT_RESURRECTING= "Resurrecting..."; private static final String TXT_RETURNING = "Returning..."; private static final String TXT_FALLING = "Falling..."; - + private static final String TXT_UNDOING = "Undoing..."; + private static final String ERR_FILE_NOT_FOUND = "File not found. For some reason."; private static final String ERR_GENERIC = "Something went wrong..." ; public static enum Mode { - DESCEND, ASCEND, CONTINUE, RESURRECT, RETURN, FALL + DESCEND, ASCEND, CONTINUE, RESURRECT, RETURN, FALL, UNDO }; public static Mode mode; @@ -94,6 +95,9 @@ public void create() { case FALL: text = TXT_FALLING; break; + case UNDO: + text = TXT_UNDOING; + break; } message = PixelScene.createText( text, 9 ); @@ -134,6 +138,9 @@ public void run() { case FALL: fall(); break; + case UNDO: + undo(); + break; } if ((Dungeon.depth % 5) == 0) { @@ -260,6 +267,20 @@ private void returnTo() throws Exception { Dungeon.switchLevel( level, Level.resizingNeeded ? level.adjustPos( returnPos ) : returnPos ); } + private void undo() throws Exception { + Actor.fixTime(); + + Dungeon.loadGame( 0); + if (Dungeon.depth == -1) { + Dungeon.depth = Statistics.deepestFloor; + Dungeon.switchLevel( Dungeon.loadLevel( 0 ), -1 ); + } else { + Level level = Dungeon.loadLevel( 0 ); + Dungeon.switchLevel( level, Level.resizingNeeded ? level.adjustPos( Dungeon.hero.pos ) : Dungeon.hero.pos ); + } + } + + private void restore() throws Exception { Actor.fixTime(); diff --git a/src/com/watabou/pixeldungeon/utils/FIFO.java b/src/com/watabou/pixeldungeon/utils/FIFO.java new file mode 100644 index 0000000000..6b87e59afa --- /dev/null +++ b/src/com/watabou/pixeldungeon/utils/FIFO.java @@ -0,0 +1,22 @@ +package com.watabou.pixeldungeon.utils; + +import java.util.LinkedList; + +/** + * Created by shaia on 5/9/15. + */ +public class FIFO extends LinkedList { + + private int limit; + + public FIFO(int limit) { + this.limit = limit; + } + + @Override + public boolean add(E o) { + super.add(o); + while (size() > limit) { super.remove(); } + return true; + } +} diff --git a/src/com/watabou/pixeldungeon/windows/WndGame.java b/src/com/watabou/pixeldungeon/windows/WndGame.java index 06abcd47c7..bfcd0f9cd9 100644 --- a/src/com/watabou/pixeldungeon/windows/WndGame.java +++ b/src/com/watabou/pixeldungeon/windows/WndGame.java @@ -111,12 +111,20 @@ protected void onClick() { } ); - addButton( new RedButton( TXT_RETURN ) { + addButton(new RedButton(TXT_RETURN) { @Override protected void onClick() { hide(); } - } ); + }); + + addButton(new RedButton("Undo") { + @Override + protected void onClick() { + InterlevelScene.mode = InterlevelScene.Mode.UNDO; + Game.switchScene(InterlevelScene.class); + } + }); resize( WIDTH, pos ); } diff --git a/src/org/ayal/pixeldungeonundone/Main.java b/src/org/ayal/pixeldungeonundone/Main.java new file mode 100644 index 0000000000..f0b07f1537 --- /dev/null +++ b/src/org/ayal/pixeldungeonundone/Main.java @@ -0,0 +1,10 @@ +package org.ayal.pixeldungeonundone; + +import com.watabou.pixeldungeon.PixelDungeon; + +/** + * Created by shaia on 5/9/15. + */ +public class Main extends PixelDungeon { + +}