135 lines
5.2 KiB
Java
135 lines
5.2 KiB
Java
package com.projectsacrifice.game;
|
|
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
|
|
public final class ProgressStore {
|
|
private static final String FILE = "project_sacrifice_progress_v1";
|
|
public static final int CURRENT_SAVE_VERSION = 3;
|
|
private final SharedPreferences preferences;
|
|
|
|
public ProgressStore(Context context) {
|
|
preferences = context.getSharedPreferences(FILE, Context.MODE_PRIVATE);
|
|
migrateIfSupported();
|
|
}
|
|
|
|
public int unlockedCount() {
|
|
return Math.max(1, Math.min(LevelCatalog.all().size(), preferences.getInt("unlocked", 1)));
|
|
}
|
|
|
|
public boolean isCompleted(int levelNumber) {
|
|
return isCompleted(levelId(levelNumber));
|
|
}
|
|
|
|
public boolean isCompleted(String levelId) {
|
|
return preferences.getBoolean(idKey(levelId, "completed"), false);
|
|
}
|
|
|
|
public int bestDeaths(int levelNumber) {
|
|
return bestDeaths(levelId(levelNumber));
|
|
}
|
|
|
|
public int bestDeaths(String levelId) {
|
|
return preferences.getInt(idKey(levelId, "deaths"), Integer.MAX_VALUE);
|
|
}
|
|
|
|
public long bestTimeMs(int levelNumber) {
|
|
return bestTimeMs(levelId(levelNumber));
|
|
}
|
|
|
|
public long bestTimeMs(String levelId) {
|
|
return preferences.getLong(idKey(levelId, "time"), Long.MAX_VALUE);
|
|
}
|
|
|
|
public boolean collectibleFound(String levelId) {
|
|
return preferences.getBoolean(idKey(levelId, "collectible"), false);
|
|
}
|
|
|
|
public void recordCompletion(int levelNumber, int deaths, long elapsedMs) {
|
|
recordCompletion(LevelCatalog.get(levelNumber - 1), deaths, elapsedMs, false);
|
|
}
|
|
|
|
public void recordCompletion(LevelDefinition level, int deaths, long elapsedMs,
|
|
boolean collectibleFound) {
|
|
if (level == null) throw new IllegalArgumentException("level is required");
|
|
SharedPreferences.Editor editor = preferences.edit();
|
|
editor.putBoolean(idKey(level.levelId, "completed"), true);
|
|
editor.putInt(idKey(level.levelId, "deaths"),
|
|
Math.min(Math.max(0, deaths), bestDeaths(level.levelId)));
|
|
editor.putLong(idKey(level.levelId, "time"),
|
|
Math.min(Math.max(0L, elapsedMs), bestTimeMs(level.levelId)));
|
|
if (collectibleFound || collectibleFound(level.levelId)) {
|
|
editor.putBoolean(idKey(level.levelId, "collectible"), true);
|
|
}
|
|
editor.putInt("unlocked", Math.min(LevelCatalog.all().size(),
|
|
Math.max(unlockedCount(), level.number + 1)));
|
|
editor.apply();
|
|
}
|
|
|
|
public int earnedStars(LevelDefinition level) {
|
|
if (level == null || !isCompleted(level.levelId)) return 0;
|
|
return ChallengeResult.evaluate(level, bestDeaths(level.levelId),
|
|
bestTimeMs(level.levelId), collectibleFound(level.levelId)).stars();
|
|
}
|
|
|
|
public int saveVersion() {
|
|
return preferences.getInt("save_version", 1);
|
|
}
|
|
|
|
private void migrateIfSupported() {
|
|
int version = preferences.getInt("save_version", 1);
|
|
if (version >= 1 && version < CURRENT_SAVE_VERSION) {
|
|
SharedPreferences.Editor editor = preferences.edit();
|
|
if (version < 3) migrateNumericKeys(editor);
|
|
editor.putInt("save_version", CURRENT_SAVE_VERSION).apply();
|
|
}
|
|
}
|
|
|
|
private void migrateNumericKeys(SharedPreferences.Editor editor) {
|
|
for (LevelDefinition level : LevelCatalog.all()) {
|
|
copyBooleanIfPresent(editor, key(level.number, "completed"),
|
|
idKey(level.levelId, "completed"));
|
|
copyIntIfPresent(editor, key(level.number, "deaths"),
|
|
idKey(level.levelId, "deaths"));
|
|
copyLongIfPresent(editor, key(level.number, "time"),
|
|
idKey(level.levelId, "time"));
|
|
}
|
|
}
|
|
|
|
private void copyBooleanIfPresent(SharedPreferences.Editor editor,
|
|
String oldKey, String newKey) {
|
|
if (preferences.contains(oldKey) && !preferences.contains(newKey)) {
|
|
editor.putBoolean(newKey, preferences.getBoolean(oldKey, false));
|
|
}
|
|
}
|
|
|
|
private void copyIntIfPresent(SharedPreferences.Editor editor,
|
|
String oldKey, String newKey) {
|
|
if (preferences.contains(oldKey) && !preferences.contains(newKey)) {
|
|
editor.putInt(newKey, preferences.getInt(oldKey, Integer.MAX_VALUE));
|
|
}
|
|
}
|
|
|
|
private void copyLongIfPresent(SharedPreferences.Editor editor,
|
|
String oldKey, String newKey) {
|
|
if (preferences.contains(oldKey) && !preferences.contains(newKey)) {
|
|
editor.putLong(newKey, preferences.getLong(oldKey, Long.MAX_VALUE));
|
|
}
|
|
}
|
|
|
|
private static String levelId(int levelNumber) {
|
|
if (levelNumber >= 1 && levelNumber <= LevelCatalog.all().size()) {
|
|
return LevelCatalog.get(levelNumber - 1).levelId;
|
|
}
|
|
return LevelDefinition.defaultLevelId(levelNumber);
|
|
}
|
|
|
|
private static String key(int levelNumber, String suffix) {
|
|
return "level_" + levelNumber + "_" + suffix;
|
|
}
|
|
|
|
private static String idKey(String levelId, String suffix) {
|
|
return "level_id_" + levelId + "_" + suffix;
|
|
}
|
|
}
|