286 lines
7.7 KiB
C++
286 lines
7.7 KiB
C++
|
#include <time.h>
|
||
|
#include <fstream>
|
||
|
#include "exceptions.h"
|
||
|
#include "utils.h"
|
||
|
#include "widgets.h"
|
||
|
#include "storage.h"
|
||
|
#include "opensave.h"
|
||
|
#include "unicode.h"
|
||
|
#include "convert.h"
|
||
|
#include "messages.h"
|
||
|
|
||
|
|
||
|
|
||
|
#define MAX_SLOTS 10
|
||
|
|
||
|
|
||
|
class SavedGame
|
||
|
{
|
||
|
private:
|
||
|
std::wstring fileName;
|
||
|
bool exists;
|
||
|
std::wstring name;
|
||
|
|
||
|
public:
|
||
|
SavedGame(const std::wstring &fileName);
|
||
|
SavedGame(const SavedGame &s): fileName(s.fileName), name(s.name) {
|
||
|
exists = s.exists;
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
const std::wstring& getFileName() { return fileName; };
|
||
|
std::wstring getName() { return exists ? name : msg(L"empty"); };
|
||
|
bool isExists() { return exists; };
|
||
|
};
|
||
|
|
||
|
|
||
|
SavedGame::SavedGame(const std::wstring &s): fileName(s)
|
||
|
{
|
||
|
exists = false;
|
||
|
|
||
|
try {
|
||
|
std::ifstream stream(toMbcs(fileName).c_str(), std::ifstream::in |
|
||
|
std::ifstream::binary);
|
||
|
if (stream.fail())
|
||
|
throw Exception(L"Can't open file");
|
||
|
name = readString(stream);
|
||
|
stream.close();
|
||
|
exists = true;
|
||
|
} catch (...) { }
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
class OkCommand: public Command
|
||
|
{
|
||
|
private:
|
||
|
Area &area;
|
||
|
bool *ok;
|
||
|
|
||
|
public:
|
||
|
OkCommand(Area &a, bool *o): area(a) { ok = o; };
|
||
|
|
||
|
virtual void doAction() {
|
||
|
*ok = true;
|
||
|
area.finishEventLoop();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
class SaveCommand: public Command
|
||
|
{
|
||
|
private:
|
||
|
SavedGame &savedGame;
|
||
|
Area *parentArea;
|
||
|
bool *saved;
|
||
|
Font *font;
|
||
|
std::wstring defaultName;
|
||
|
Game *game;
|
||
|
|
||
|
public:
|
||
|
SaveCommand(SavedGame &sg, Font *f, Area *area, bool *s,
|
||
|
const std::wstring &dflt, Game *g): savedGame(sg), defaultName(dflt)
|
||
|
{
|
||
|
parentArea = area;
|
||
|
saved = s;
|
||
|
font = f;
|
||
|
game = g;
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
virtual void doAction() {
|
||
|
Area area;
|
||
|
area.add(parentArea, false);
|
||
|
area.add(new Window(170, 280, 460, 100, L"blue.bmp"));
|
||
|
std::wstring name;
|
||
|
if (savedGame.isExists())
|
||
|
name = savedGame.getName();
|
||
|
else
|
||
|
name = defaultName;
|
||
|
area.add(new Label(font, 180, 300, 255,255,0, msg(L"enterGame")));
|
||
|
area.add(new InputField(340, 300, 280, 26, L"blue.bmp", name, 20,
|
||
|
255,255,0, font));
|
||
|
ExitCommand exitCmd(area);
|
||
|
OkCommand okCmd(area, saved);
|
||
|
area.add(new Button(310, 340, 80, 25, font, 255,255,0, L"blue.bmp",
|
||
|
msg(L"ok"), &okCmd));
|
||
|
area.add(new Button(400, 340, 80, 25, font, 255,255,0, L"blue.bmp",
|
||
|
msg(L"cancel"), &exitCmd));
|
||
|
area.add(new KeyAccel(SDLK_ESCAPE, &exitCmd));
|
||
|
area.add(new KeyAccel(SDLK_RETURN, &okCmd));
|
||
|
area.run();
|
||
|
|
||
|
if (*saved) {
|
||
|
*saved = false;
|
||
|
try {
|
||
|
std::ofstream stream(toMbcs(savedGame.getFileName()).
|
||
|
c_str(), std::ofstream::out | std::ofstream::binary);
|
||
|
if (stream.fail())
|
||
|
throw Exception(L"Error creating save file");
|
||
|
writeString(stream, name);
|
||
|
game->save(stream);
|
||
|
if (stream.fail())
|
||
|
throw Exception(L"Error saving game");
|
||
|
stream.close();
|
||
|
*saved = true;
|
||
|
} catch (...) {
|
||
|
showMessageWindow(&area, L"redpattern.bmp", 300, 80, font,
|
||
|
255,255,255, msg(L"saveError"));
|
||
|
}
|
||
|
parentArea->finishEventLoop();
|
||
|
} else {
|
||
|
parentArea->updateMouse();
|
||
|
parentArea->draw();
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
static std::wstring getSavesPath()
|
||
|
{
|
||
|
#ifndef WIN32
|
||
|
std::wstring path(fromMbcs(getenv("HOME")) +
|
||
|
std::wstring(L"/.einstein/save"));
|
||
|
#else
|
||
|
std::wstring path(getStorage()->get(L"path", L""));
|
||
|
if (path.length() > 0)
|
||
|
path += L"\\";
|
||
|
path += L"save";
|
||
|
#endif
|
||
|
ensureDirExists(path);
|
||
|
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
|
||
|
typedef std::list<SavedGame> SavesList;
|
||
|
|
||
|
|
||
|
static void showListWindow(SavesList &list, Command **commands,
|
||
|
const std::wstring &title, Area &area, Font *font)
|
||
|
{
|
||
|
Font titleFont(L"nova.ttf", 26);
|
||
|
|
||
|
area.add(new Window(250, 90, 300, 420, L"blue.bmp"));
|
||
|
area.add(new Label(&titleFont, 250, 95, 300, 40, Label::ALIGN_CENTER,
|
||
|
Label::ALIGN_MIDDLE, 255,255,0, title));
|
||
|
ExitCommand exitCmd(area);
|
||
|
area.add(new Button(360, 470, 80, 25, font, 255,255,0, L"blue.bmp",
|
||
|
msg(L"close"), &exitCmd));
|
||
|
area.add(new KeyAccel(SDLK_ESCAPE, &exitCmd));
|
||
|
|
||
|
int pos = 150;
|
||
|
int no = 0;
|
||
|
for (SavesList::iterator i = list.begin(); i != list.end(); i++) {
|
||
|
SavedGame &game = *i;
|
||
|
area.add(new Button(260, pos, 280, 25, font, 255,255,255, L"blue.bmp",
|
||
|
game.getName(), commands[no++]));
|
||
|
pos += 30;
|
||
|
}
|
||
|
|
||
|
area.run();
|
||
|
}
|
||
|
|
||
|
|
||
|
bool saveGame(Area *parentArea, Game *game)
|
||
|
{
|
||
|
std::wstring path = getSavesPath();
|
||
|
|
||
|
Area area;
|
||
|
area.add(parentArea, false);
|
||
|
Font font(L"laudcn2.ttf", 14);
|
||
|
bool saved = false;
|
||
|
|
||
|
SavesList list;
|
||
|
Command **commands = new Command*[MAX_SLOTS];
|
||
|
for (int i = 0; i < MAX_SLOTS; i++) {
|
||
|
SavedGame sg(path + L"/" + toString(i) + L".sav");
|
||
|
list.push_back(sg);
|
||
|
commands[i] = new SaveCommand(*(--(list.end())), &font,
|
||
|
&area, &saved, L"game " + toString(i+1), game);
|
||
|
}
|
||
|
|
||
|
showListWindow(list, commands, msg(L"saveGame"), area, &font);
|
||
|
|
||
|
for (int i = 0; i < MAX_SLOTS; i++)
|
||
|
delete commands[i];
|
||
|
delete[] commands;
|
||
|
|
||
|
return saved;
|
||
|
}
|
||
|
|
||
|
|
||
|
class LoadCommand: public Command
|
||
|
{
|
||
|
private:
|
||
|
SavedGame &savedGame;
|
||
|
Area *parentArea;
|
||
|
bool *saved;
|
||
|
Font *font;
|
||
|
std::wstring defaultName;
|
||
|
Game **game;
|
||
|
|
||
|
public:
|
||
|
LoadCommand(SavedGame &sg, Font *f, Area *area, Game **g):
|
||
|
savedGame(sg)
|
||
|
{
|
||
|
parentArea = area;
|
||
|
font = f;
|
||
|
game = g;
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
virtual void doAction() {
|
||
|
try {
|
||
|
std::ifstream stream(toMbcs(savedGame.getFileName()).c_str(),
|
||
|
std::ifstream::in | std::ifstream::binary);
|
||
|
if (stream.fail())
|
||
|
throw Exception(L"Error opening save file");
|
||
|
readString(stream);
|
||
|
Game *g = new Game(stream);
|
||
|
if (stream.fail())
|
||
|
throw Exception(L"Error loading game");
|
||
|
stream.close();
|
||
|
*game = g;
|
||
|
} catch (...) {
|
||
|
showMessageWindow(parentArea, L"redpattern.bmp", 300, 80, font,
|
||
|
255,255,255, L"Error loadng game");
|
||
|
}
|
||
|
parentArea->finishEventLoop();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
Game* loadGame(Area *parentArea)
|
||
|
{
|
||
|
std::wstring path = getSavesPath();
|
||
|
|
||
|
Area area;
|
||
|
area.add(parentArea, false);
|
||
|
Font font(L"laudcn2.ttf", 14);
|
||
|
|
||
|
Game *newGame = NULL;
|
||
|
|
||
|
SavesList list;
|
||
|
Command **commands = new Command*[MAX_SLOTS];
|
||
|
for (int i = 0; i < MAX_SLOTS; i++) {
|
||
|
SavedGame sg(path + L"/" + toString(i) + L".sav");
|
||
|
list.push_back(sg);
|
||
|
if (sg.isExists())
|
||
|
commands[i] = new LoadCommand(*(--(list.end())), &font, &area,
|
||
|
&newGame);
|
||
|
else
|
||
|
commands[i] = NULL;
|
||
|
}
|
||
|
|
||
|
showListWindow(list, commands, msg(L"loadGame"), area, &font);
|
||
|
|
||
|
for (int i = 0; i < MAX_SLOTS; i++)
|
||
|
delete commands[i];
|
||
|
delete[] commands;
|
||
|
|
||
|
return newGame;
|
||
|
}
|
||
|
|