Magic_Ling_Pixel_Dungeon/src/com/shatteredpixel/shatteredpixeldungeon/Rankings.java

285 lines
7.5 KiB
Java
Raw Normal View History

2014-07-27 13:39:07 +00:00
/*
* Pixel Dungeon
2015-06-12 20:44:04 +00:00
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2015 Evan Debenham
2014-07-27 13:39:07 +00:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon;
2014-07-27 13:39:07 +00:00
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.watabou.noosa.Game;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
import com.watabou.utils.SystemTime;
2014-07-27 13:39:07 +00:00
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public enum Rankings {
INSTANCE;
public static final int TABLE_SIZE = 11;
2014-07-27 13:39:07 +00:00
public static final String RANKINGS_FILE = "rankings.dat";
public static final String DETAILS_FILE = "game_%d.dat";
public ArrayList<Record> records;
public int lastRecord;
public int totalNumber;
2015-02-04 21:21:42 +00:00
public int wonNumber;
public void submit( boolean win, Class cause ) {
load();
2014-07-27 13:39:07 +00:00
Record rec = new Record();
rec.cause = cause;
2014-07-27 13:39:07 +00:00
rec.win = win;
rec.heroClass = Dungeon.hero.heroClass;
rec.armorTier = Dungeon.hero.tier();
rec.herolevel = Dungeon.hero.lvl;
rec.depth = Dungeon.depth;
2014-07-27 13:39:07 +00:00
rec.score = score( win );
String gameFile = Messages.format( DETAILS_FILE, SystemTime.now );
2014-07-27 13:39:07 +00:00
try {
Dungeon.saveGame( gameFile );
rec.gameFile = gameFile;
} catch (IOException e) {
rec.gameFile = "";
}
records.add( rec );
Collections.sort( records, scoreComparator );
lastRecord = records.indexOf( rec );
int size = records.size();
while (size > TABLE_SIZE) {
2014-07-27 13:39:07 +00:00
Record removedGame;
if (lastRecord == size - 1) {
removedGame = records.remove( size - 2 );
lastRecord--;
} else {
removedGame = records.remove( size - 1 );
}
if (removedGame.gameFile.length() > 0) {
Game.instance.deleteFile( removedGame.gameFile );
}
size = records.size();
2014-07-27 13:39:07 +00:00
}
totalNumber++;
2015-02-04 21:21:42 +00:00
if (win) {
wonNumber++;
}
2014-07-27 13:39:07 +00:00
Badges.validateGamesPlayed();
save();
}
2014-07-27 13:39:07 +00:00
private int score( boolean win ) {
return (Statistics.goldCollected + Dungeon.hero.lvl * (win ? 26 : Dungeon.depth ) * 100) * (win ? 2 : 1);
2014-07-27 13:39:07 +00:00
}
private static final String RECORDS = "records";
private static final String LATEST = "latest";
private static final String TOTAL = "total";
2015-02-04 21:21:42 +00:00
private static final String WON = "won";
2014-07-27 13:39:07 +00:00
public void save() {
Bundle bundle = new Bundle();
bundle.put( RECORDS, records );
bundle.put( LATEST, lastRecord );
bundle.put( TOTAL, totalNumber );
2015-02-04 21:21:42 +00:00
bundle.put( WON, wonNumber );
2014-07-27 13:39:07 +00:00
try {
OutputStream output = Game.instance.openFileOutput( RANKINGS_FILE, Game.MODE_PRIVATE );
Bundle.write( bundle, output );
output.close();
} catch (IOException e) {
2014-07-27 13:39:07 +00:00
}
}
public void load() {
if (records != null) {
return;
}
records = new ArrayList<Rankings.Record>();
try {
InputStream input = Game.instance.openFileInput( RANKINGS_FILE );
Bundle bundle = Bundle.read( input );
input.close();
for (Bundlable record : bundle.getCollection( RECORDS )) {
records.add( (Record)record );
}
2014-07-27 13:39:07 +00:00
lastRecord = bundle.getInt( LATEST );
totalNumber = bundle.getInt( TOTAL );
if (totalNumber == 0) {
totalNumber = records.size();
}
2015-02-04 21:21:42 +00:00
wonNumber = bundle.getInt( WON );
if (wonNumber == 0) {
for (Record rec : records) {
if (rec.win) {
wonNumber++;
}
}
}
} catch (IOException e) {
2015-02-04 21:21:42 +00:00
2014-07-27 13:39:07 +00:00
}
}
2014-07-27 13:39:07 +00:00
public static class Record implements Bundlable {
//pre 0.3.4
public String info;
2014-07-27 13:39:07 +00:00
private static final String REASON = "reason";
private static final String CAUSE = "cause";
2014-07-27 13:39:07 +00:00
private static final String WIN = "win";
private static final String SCORE = "score";
private static final String TIER = "tier";
private static final String LEVEL = "level";
private static final String DEPTH = "depth";
2014-07-27 13:39:07 +00:00
private static final String GAME = "gameFile";
public Class cause;
2014-07-27 13:39:07 +00:00
public boolean win;
public HeroClass heroClass;
public int armorTier;
public int herolevel;
public int depth;
2014-07-27 13:39:07 +00:00
public int score;
public String gameFile;
public String desc(){
if (cause == null && (info == null || info.equals("")))
return "Killed by Something";
else if (cause == null){
return info; //pre 0.3.4 saves
} else {
String result = Messages.get(cause, "rankings_desc", (Messages.get(cause, "name")));
if (result.contains("!!!NO TEXT FOUND!!!")){
return "Killed By Something";
} else {
return result;
}
}
}
2014-07-27 13:39:07 +00:00
@Override
public void restoreFromBundle( Bundle bundle ) {
//pre-0.3.4
2014-07-27 13:39:07 +00:00
info = bundle.getString( REASON );
cause = bundle.getClass( CAUSE );
2014-07-27 13:39:07 +00:00
win = bundle.getBoolean( WIN );
score = bundle.getInt( SCORE );
heroClass = HeroClass.restoreInBundle( bundle );
armorTier = bundle.getInt( TIER );
gameFile = bundle.getString( GAME );
//Here lies a collection of messy logic, some to account for transferring pre-0.2.3 rankings to the new
//system, some to account for errors in that process which were patched.
//commented here is info about what was added when, and why, eventually after almost everyone has
//dropped 0.2.2 this can be phased out.
//0.2.3, adds depth and parses info, works almost perfectly, except for the edge case in the next comment.
if (!bundle.contains(DEPTH)){
try {
depth = Integer.parseInt(info.replaceAll("[\\D]", ""));
} catch (Exception e) {
depth = 0;
}
info = info.split("on level")[0].trim();
} else
depth = bundle.getInt( DEPTH );
//0.2.3d, fixes a case where a player who died to dm-300 would have a recorded depth of 30015.
if (depth == 30015) depth = 15;
//basically every patch until 0.2.3d, extracts the hero's level from the bundle structure.
//the second condition in the if is important, helps account for bugged rankings from pre 0.2.3d
if (!bundle.contains(LEVEL) || bundle.getInt(LEVEL) == 0 && ShatteredPixelDungeon.version() < 30) {
try {
InputStream input = Game.instance.openFileInput(gameFile);
Bundle gameBundle = Bundle.read(input);
input.close();
herolevel = gameBundle.getBundle("hero").getInt("lvl");
} catch (Exception e) {
herolevel = 0;
}
} else
herolevel = bundle.getInt( LEVEL );
2014-07-27 13:39:07 +00:00
}
@Override
public void storeInBundle( Bundle bundle ) {
if (info != null && !info.equals("")) bundle.put( REASON, info );
else bundle.put( CAUSE, cause );
2014-07-27 13:39:07 +00:00
bundle.put( WIN, win );
bundle.put( SCORE, score );
heroClass.storeInBundle( bundle );
bundle.put( TIER, armorTier );
bundle.put( LEVEL, herolevel );
bundle.put( DEPTH, depth );
2014-07-27 13:39:07 +00:00
bundle.put( GAME, gameFile );
}
}
private static final Comparator<Record> scoreComparator = new Comparator<Rankings.Record>() {
@Override
public int compare( Record lhs, Record rhs ) {
return (int)Math.signum( rhs.score - lhs.score );
}
};
}