v0.4.1: massively improved the efficiency of rankings storage

This commit is contained in:
Evan Debenham 2016-06-28 01:38:29 -04:00
parent 97f354c342
commit 68ea4dd6c1
9 changed files with 161 additions and 38 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shatteredpixel.shatteredpixeldungeon" package="com.shatteredpixel.shatteredpixeldungeon"
android:versionCode="107" android:versionCode="108"
android:versionName="0.4.0" android:versionName="0.4.0"
android:installLocation="auto"> android:installLocation="auto">

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Hunger;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Ooze;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DM300; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DM300;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Goo; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Goo;
@ -33,6 +34,10 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.King;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Tengu; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Tengu;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
import com.shatteredpixel.shatteredpixeldungeon.items.Amulet; import com.shatteredpixel.shatteredpixeldungeon.items.Amulet;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
import com.shatteredpixel.shatteredpixeldungeon.messages.Languages; import com.shatteredpixel.shatteredpixeldungeon.messages.Languages;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@ -56,7 +61,6 @@ public enum Rankings {
public static final int TABLE_SIZE = 11; public static final int TABLE_SIZE = 11;
public static final String RANKINGS_FILE = "rankings.dat"; public static final String RANKINGS_FILE = "rankings.dat";
public static final String DETAILS_FILE = "game_%d.dat";
public ArrayList<Record> records; public ArrayList<Record> records;
public int lastRecord; public int lastRecord;
@ -77,13 +81,9 @@ public enum Rankings {
rec.depth = Dungeon.depth; rec.depth = Dungeon.depth;
rec.score = score( win ); rec.score = score( win );
String gameFile = Messages.format( DETAILS_FILE, SystemTime.now ); INSTANCE.saveGameData(rec);
try {
Dungeon.saveGame( gameFile ); rec.gameID = String.valueOf(SystemTime.now);
rec.gameFile = gameFile;
} catch (IOException e) {
rec.gameFile = "";
}
records.add( rec ); records.add( rec );
@ -93,16 +93,11 @@ public enum Rankings {
int size = records.size(); int size = records.size();
while (size > TABLE_SIZE) { while (size > TABLE_SIZE) {
Record removedGame;
if (lastRecord == size - 1) { if (lastRecord == size - 1) {
removedGame = records.remove( size - 2 ); records.remove( size - 2 );
lastRecord--; lastRecord--;
} else { } else {
removedGame = records.remove( size - 1 ); records.remove( size - 1 );
}
if (removedGame.gameFile.length() > 0) {
Game.instance.deleteFile( removedGame.gameFile );
} }
size = records.size(); size = records.size();
@ -122,6 +117,62 @@ public enum Rankings {
return (Statistics.goldCollected + Dungeon.hero.lvl * (win ? 26 : Dungeon.depth ) * 100) * (win ? 2 : 1); return (Statistics.goldCollected + Dungeon.hero.lvl * (win ? 26 : Dungeon.depth ) * 100) * (win ? 2 : 1);
} }
public static final String HERO = "hero";
public static final String STATS = "stats";
public static final String BADGES = "badges";
public static final String HANDLERS = "handlers";
public void saveGameData(Record rec){
rec.gameData = new Bundle();
//save the hero and belongings
ArrayList<Item> allItems = (ArrayList<Item>) Dungeon.hero.belongings.backpack.items.clone();
//remove items that won't show up in the rankings screen
for (Item item : Dungeon.hero.belongings.backpack.items.toArray( new Item[0])) {
if (!Dungeon.quickslot.contains(item)) Dungeon.hero.belongings.backpack.items.remove(item);
}
rec.gameData.put( HERO, Dungeon.hero );
//save stats
Bundle stats = new Bundle();
Statistics.storeInBundle(stats);
rec.gameData.put( STATS, stats);
//save badges
Bundle badges = new Bundle();
Badges.saveLocal(badges);
rec.gameData.put( BADGES, badges);
//save handler information
Bundle handler = new Bundle();
Scroll.saveSelectively(handler, Dungeon.hero.belongings.backpack.items);
Potion.saveSelectively(handler, Dungeon.hero.belongings.backpack.items);
Ring.saveSelectively(handler, Dungeon.hero.belongings.backpack.items);
rec.gameData.put( HANDLERS, handler);
//restore items now that we're done saving
Dungeon.hero.belongings.backpack.items = allItems;
}
public void loadGameData(Record rec){
Bundle data = rec.gameData;
Dungeon.hero = null;
Dungeon.quickslot.reset();
Bundle handler = data.getBundle(HANDLERS);
Scroll.restore(handler);
Potion.restore(handler);
Ring.restore(handler);
Badges.loadLocal(data.getBundle(BADGES));
Dungeon.hero = (Hero)data.get(HERO);
Statistics.restoreFromBundle(data.getBundle(STATS));
}
private static final String RECORDS = "records"; private static final String RECORDS = "records";
private static final String LATEST = "latest"; private static final String LATEST = "latest";
private static final String TOTAL = "total"; private static final String TOTAL = "total";
@ -148,7 +199,7 @@ public enum Rankings {
return; return;
} }
records = new ArrayList<Rankings.Record>(); records = new ArrayList<>();
try { try {
InputStream input = Game.instance.openFileInput( RANKINGS_FILE ); InputStream input = Game.instance.openFileInput( RANKINGS_FILE );
@ -185,13 +236,18 @@ public enum Rankings {
public String info; public String info;
private static final String REASON = "reason"; private static final String REASON = "reason";
//pre 0.4.1
public String gameFile;
private static final String FILE = "gameFile";
private static final String CAUSE = "cause"; private static final String CAUSE = "cause";
private static final String WIN = "win"; private static final String WIN = "win";
private static final String SCORE = "score"; private static final String SCORE = "score";
private static final String TIER = "tier"; private static final String TIER = "tier";
private static final String LEVEL = "level"; private static final String LEVEL = "level";
private static final String DEPTH = "depth"; private static final String DEPTH = "depth";
private static final String GAME = "gameFile"; private static final String DATA = "gameData";
private static final String ID = "gameID";
public Class cause; public Class cause;
public boolean win; public boolean win;
@ -201,9 +257,10 @@ public enum Rankings {
public int herolevel; public int herolevel;
public int depth; public int depth;
public int score; public Bundle gameData;
public String gameID;
public String gameFile; public int score;
public String desc(){ public String desc(){
if (cause == null) { if (cause == null) {
@ -260,7 +317,12 @@ public enum Rankings {
heroClass = HeroClass.restoreInBundle( bundle ); heroClass = HeroClass.restoreInBundle( bundle );
armorTier = bundle.getInt( TIER ); armorTier = bundle.getInt( TIER );
gameFile = bundle.getString( GAME ); if (bundle.contains(FILE)) {
gameFile = bundle.getString(FILE);
} else {
gameData = bundle.getBundle(DATA);
gameID = bundle.getString(ID);
}
depth = bundle.getInt( DEPTH ); depth = bundle.getInt( DEPTH );
herolevel = bundle.getInt( LEVEL ); herolevel = bundle.getInt( LEVEL );
@ -281,7 +343,8 @@ public enum Rankings {
bundle.put( LEVEL, herolevel ); bundle.put( LEVEL, herolevel );
bundle.put( DEPTH, depth ); bundle.put( DEPTH, depth );
bundle.put( GAME, gameFile ); bundle.put( DATA, gameData );
bundle.put( ID, gameID);
} }
} }

View File

@ -24,8 +24,10 @@ import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
public class ItemStatusHandler<T extends Item> { public class ItemStatusHandler<T extends Item> {
@ -80,8 +82,22 @@ public class ItemStatusHandler<T extends Item> {
} }
} }
public void saveSelectively( Bundle bundle, ArrayList<Item> itemsToSave ){
List<Class<? extends T>> items = Arrays.asList(this.items);
for (Item item : itemsToSave){
if (items.contains(item.getClass())){
Class<? extends T> cls = items.get(items.indexOf(item.getClass()));
String itemName = cls.toString();
bundle.put( itemName + PFX_LABEL, itemLabels.get( cls ) );
bundle.put( itemName + PFX_KNOWN, known.contains( cls ) );
}
}
}
private void restore( Bundle bundle, ArrayList<String> labelsLeft ) { private void restore( Bundle bundle, ArrayList<String> labelsLeft ) {
ArrayList<Class<? extends T>> unlabelled = new ArrayList<>();
for (int i=0; i < items.length; i++) { for (int i=0; i < items.length; i++) {
Class<? extends T> item = items[i]; Class<? extends T> item = items[i];
@ -99,14 +115,22 @@ public class ItemStatusHandler<T extends Item> {
} else { } else {
int index = Random.Int( labelsLeft.size() ); unlabelled.add(items[i]);
itemLabels.put( item, labelsLeft.get( index ) ); }
labelsLeft.remove( index ); }
if (bundle.contains( itemName + PFX_KNOWN ) && bundle.getBoolean( itemName + PFX_KNOWN )) { for (Class<? extends T> item : unlabelled){
known.add( item );
} String itemName = item.toString();
int index = Random.Int( labelsLeft.size() );
itemLabels.put( item, labelsLeft.get( index ) );
labelsLeft.remove( index );
if (bundle.contains( itemName + PFX_KNOWN ) && bundle.getBoolean( itemName + PFX_KNOWN )) {
known.add( item );
} }
} }
} }

View File

@ -107,6 +107,10 @@ public class Potion extends Item {
handler.save( bundle ); handler.save( bundle );
} }
public static void saveSelectively( Bundle bundle, ArrayList<Item> items ) {
handler.saveSelectively( bundle, items );
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) { public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<>( (Class<? extends Potion>[])potions, colors, bundle ); handler = new ItemStatusHandler<>( (Class<? extends Potion>[])potions, colors, bundle );

View File

@ -26,7 +26,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.ShadowParticle;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler; import com.shatteredpixel.shatteredpixeldungeon.items.ItemStatusHandler;
import com.shatteredpixel.shatteredpixeldungeon.items.KindofMisc; import com.shatteredpixel.shatteredpixeldungeon.items.KindofMisc;
@ -36,6 +35,7 @@ import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
public class Ring extends KindofMisc { public class Ring extends KindofMisc {
@ -90,6 +90,10 @@ public class Ring extends KindofMisc {
handler.save( bundle ); handler.save( bundle );
} }
public static void saveSelectively( Bundle bundle, ArrayList<Item> items ) {
handler.saveSelectively( bundle, items );
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) { public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<>( (Class<? extends Ring>[])rings, gems, bundle ); handler = new ItemStatusHandler<>( (Class<? extends Ring>[])rings, gems, bundle );

View File

@ -96,6 +96,10 @@ public abstract class Scroll extends Item {
handler.save( bundle ); handler.save( bundle );
} }
public static void saveSelectively( Bundle bundle, ArrayList<Item> items ) {
handler.saveSelectively( bundle, items );
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void restore( Bundle bundle ) { public static void restore( Bundle bundle ) {
handler = new ItemStatusHandler<>( (Class<? extends Scroll>[])scrolls, runes, bundle ); handler = new ItemStatusHandler<>( (Class<? extends Scroll>[])scrolls, runes, bundle );

View File

@ -294,8 +294,8 @@ public class RankingsScene extends PixelScene {
@Override @Override
protected void onClick() { protected void onClick() {
if (rec.gameFile.length() > 0) { if (rec.gameData != null) {
parent.add( new WndRanking( rec.gameFile ) ); parent.add( new WndRanking( rec ) );
} else { } else {
parent.add( new WndError( Messages.get(RankingsScene.class, "no_info") ) ); parent.add( new WndError( Messages.get(RankingsScene.class, "no_info") ) );
} }

View File

@ -22,6 +22,8 @@ package com.shatteredpixel.shatteredpixeldungeon.scenes;
import android.opengl.GLES20; import android.opengl.GLES20;
import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Rankings;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites; import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites;
import com.shatteredpixel.shatteredpixeldungeon.effects.Fireball; import com.shatteredpixel.shatteredpixeldungeon.effects.Fireball;
@ -144,6 +146,27 @@ public class WelcomeScene extends PixelScene {
} }
private void updateVersion(int previousVersion){ private void updateVersion(int previousVersion){
//rankings conversion
if (previousVersion < 108){
Rankings.INSTANCE.load();
for (Rankings.Record rec : Rankings.INSTANCE.records){
try{
Dungeon.loadGame(rec.gameFile, false);
rec.gameID = rec.gameFile.replaceAll("\\D", "");
Rankings.INSTANCE.saveGameData(rec);
} catch (Exception e){
rec.gameID = rec.gameFile.replaceAll("\\D", "");
rec.gameData = null;
}
String file = rec.gameFile;
rec.gameFile = "";
Game.instance.deleteFile(file);
}
Rankings.INSTANCE.save();
}
ShatteredPixelDungeon.version(ShatteredPixelDungeon.versionCode); ShatteredPixelDungeon.version(ShatteredPixelDungeon.versionCode);
} }

View File

@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Rankings;
import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
@ -55,7 +56,7 @@ public class WndRanking extends WndTabbed {
private Image busy; private Image busy;
public WndRanking( final String gameFile ) { public WndRanking( final Rankings.Record rec ) {
super(); super();
resize( WIDTH, HEIGHT ); resize( WIDTH, HEIGHT );
@ -65,8 +66,8 @@ public class WndRanking extends WndTabbed {
public void run() { public void run() {
try { try {
Badges.loadGlobal(); Badges.loadGlobal();
Dungeon.loadGame( gameFile ); Rankings.INSTANCE.loadGameData( rec );
} catch (Exception e ) { } catch ( Exception e ) {
error = Messages.get(WndRanking.class, "error"); error = Messages.get(WndRanking.class, "error");
} }
} }