package me.desht.chesscraft;
import me.desht.chesscraft.chess.BoardView;
import me.desht.chesscraft.chess.BoardViewManager;
import me.desht.chesscraft.chess.ChessGame;
import me.desht.chesscraft.chess.ChessGameManager;
import me.desht.chesscraft.exceptions.ChessException;
import me.desht.dhutils.Debugger;
import me.desht.dhutils.LogUtils;
import me.desht.dhutils.MiscUtil;
import me.desht.dhutils.PersistableLocation;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
public class ChessPersistence {
public void save() {
savePersistedData();
}
public void reload() {
List<BoardView> views = new ArrayList<BoardView>(BoardViewManager.getManager().listBoardViews());
for (BoardView view : views) {
// this will also do a temporary delete on any games
BoardViewManager.getManager().deleteBoardView(view.getName(), false);
}
loadPersistedData();
ChessGameManager.getManager().checkForUUIDMigration();
}
public static List<Object> freezeLocation(Location l) {
List<Object> list = new ArrayList<Object>();
list.add(l.getWorld().getName());
list.add(l.getBlockX());
list.add(l.getBlockY());
list.add(l.getBlockZ());
return list;
}
public static Location thawLocation(List<?> list) {
World w = Bukkit.getServer().getWorld((String) list.get(0));
return w == null ? null : new Location(w, (Integer) list.get(1), (Integer) list.get(2), (Integer) list.get(3));
}
private void savePersistedData() {
saveGames();
saveBoards();
YamlConfiguration conf = new YamlConfiguration();
for (Entry<UUID,String> e : ChessGameManager.getManager().getCurrentGames().entrySet()) {
conf.set("current_games." + e.getKey(), e.getValue());
}
Location loc = BoardViewManager.getManager().getGlobalTeleportOutDest();
if (loc != null) {
conf.set("teleport_out_dest", new PersistableLocation(loc));
}
try {
conf.save(DirectoryStructure.getPersistFile());
} catch (IOException e1) {
LogUtils.severe("Can't save persist.yml", e1);
}
}
private void loadPersistedData() {
int nLoaded = 0;
// load the boards, and any games on those boards
for (File f : DirectoryStructure.getBoardPersistDirectory().listFiles(DirectoryStructure.ymlFilter)) {
nLoaded += loadBoard(f) ? 1 : 0;
}
for (BoardView bv : BoardViewManager.getManager().listBoardViews()) {
Debugger.getInstance().debug(2, "repainting controls for board " + bv.getName());
bv.getControlPanel().repaintControls();
}
Debugger.getInstance().debug("loaded " + nLoaded + " saved boards.");
// load other misc data which isn't tied to any board or game
File persistFile = DirectoryStructure.getPersistFile();
if (persistFile.exists()) {
try {
YamlConfiguration conf = MiscUtil.loadYamlUTF8(DirectoryStructure.getPersistFile());
ConfigurationSection current = conf.getConfigurationSection("current_games");
if (current != null) {
for (String playerId : current.getKeys(false)) {
try {
if (MiscUtil.looksLikeUUID(playerId)) {
ChessGameManager.getManager().setCurrentGame(UUID.fromString(playerId), current.getString(playerId));
}
} catch (ChessException e) {
LogUtils.warning("can't set current game for player " + playerId + ": " + e.getMessage());
}
}
}
if (conf.contains("teleport_out_dest")) {
PersistableLocation pLoc = (PersistableLocation) conf.get("teleport_out_dest");
BoardViewManager.getManager().setGlobalTeleportOutDest(pLoc.getLocation());
}
} catch (Exception e) {
LogUtils.severe("Unexpected Error while loading " + DirectoryStructure.getPersistFile().getName());
LogUtils.severe("Message: " + e.getMessage());
}
}
}
/**
* Load one board file, plus the game on that board, if there is one.
*
* @param f the file to load from
* @return true if the board was loaded, false otherwise
*/
public boolean loadBoard(File f) {
Debugger.getInstance().debug("loading board: " + f);
try {
Configuration conf = MiscUtil.loadYamlUTF8(f);
BoardView bv;
if (conf.contains("board")) {
bv = (BoardView) conf.get("board");
} else if (conf.getKeys(false).size() > 0) {
bv = new BoardView(conf);
savePersistable("board", bv);
LogUtils.info("migrated v4-format board save " + f.getName() + " to v5-format");
} else {
// empty config returned - probably due to corrupted save file of some kind
return false;
}
if (bv.isWorldAvailable()) {
BoardViewManager.getManager().registerView(bv);
// load the board's game too, if there is one
if (!bv.getSavedGameName().isEmpty()) {
File gameFile = new File(DirectoryStructure.getGamesPersistDirectory(), bv.getSavedGameName() + ".yml");
ChessGame game = loadGame(gameFile);
if (game != null) {
bv.setGame(game);
}
}
return true;
} else {
BoardViewManager.getManager().deferLoading(bv.getWorldName(), f);
LogUtils.info("board loading for board '" + bv.getName() + "' deferred (world '" + bv.getWorldName() + "' not available)");
return false;
}
} catch (Exception e) {
LogUtils.severe("can't load saved board from " + f.getName() + ": " + e.getMessage(), e);
// TODO: restore terrain, if applicable?
return false;
}
}
private ChessGame loadGame(File f) {
Debugger.getInstance().debug("loading game: " + f);
try {
Configuration conf = MiscUtil.loadYamlUTF8(f);
ChessGame game = null;
if (conf.contains("game")) {
game = (ChessGame) conf.get("game");
} else if (conf.getKeys(false).size() > 0) {
game = new ChessGame(conf);
savePersistable("game", game);
LogUtils.info("migrated v4-format game save " + f.getName() + " to v5-format");
}
if (game != null) {
ChessGameManager.getManager().registerGame(game);
}
return game;
} catch (Exception e) {
LogUtils.severe("can't load saved game from " + f.getName() + ": " + e.getMessage(), e);
return null;
}
}
private void saveBoards() {
for (BoardView b : BoardViewManager.getManager().listBoardViews()) {
savePersistable("board", b);
}
}
private void saveGames() {
for (ChessGame game : ChessGameManager.getManager().listGames()) {
savePersistable("game", game);
}
}
public void savePersistable(String tag, ChessPersistable object) {
YamlConfiguration conf = new YamlConfiguration();
conf.set(tag, object);
File file = new File(object.getSaveDirectory(), makeSafeFileName(object.getName()) + ".yml");
try {
conf.save(file);
} catch (IOException e1) {
LogUtils.severe("Can't save " + tag + " " + object.getName(), e1);
}
}
public void unpersist(ChessPersistable object) {
File f = new File(object.getSaveDirectory(), makeSafeFileName(object.getName()) + ".yml");
if (!f.delete()) {
LogUtils.warning("Can't delete save file " + f);
}
}
public static void requireSection(ConfigurationSection c, String key) throws ChessException {
if (!c.contains(key))
throw new ChessException("missing required section '" + key + "'");
}
public static String makeSafeFileName(String name) {
return name == null ? "" : name.replace("/", "-").replace("\\", "-").replace("?", "-").replace(":", ";").replace("%", "-").replace("|", ";").replace("\"", "'").replace("<", ",").replace(">", ".").replace("+", "=").replace("[", "(").replace("]", ")");
}
}