added caching of data files to speed game loading
This commit is contained in:
parent
f69fe0564c
commit
565603f5de
13 changed files with 262 additions and 86 deletions
|
@ -1123,24 +1123,26 @@ void calculate_healing(display& disp, const gamemap& map,
|
|||
}
|
||||
|
||||
h->second = 0;
|
||||
} else if(h->second < 0) {
|
||||
if(show_healing) {
|
||||
sound::play_sound("groan.wav");
|
||||
disp.float_label(h->first,lexical_cast<std::string>(h->second*-1),255,0,0);
|
||||
} else {
|
||||
if(h->second > 0 && h->second > u.max_hitpoints()-u.hitpoints()) {
|
||||
h->second = u.max_hitpoints()-u.hitpoints();
|
||||
if(h->second <= 0)
|
||||
continue;
|
||||
}
|
||||
} else if(h->second > 0) {
|
||||
if(show_healing) {
|
||||
sound::play_sound("heal.wav");
|
||||
disp.float_label(h->first,lexical_cast<std::string>(h->second),0,255,0);
|
||||
|
||||
if(h->second < 0) {
|
||||
if(show_healing) {
|
||||
sound::play_sound("groan.wav");
|
||||
disp.float_label(h->first,lexical_cast<std::string>(h->second*-1),255,0,0);
|
||||
}
|
||||
} else if(h->second > 0) {
|
||||
if(show_healing) {
|
||||
sound::play_sound("heal.wav");
|
||||
disp.float_label(h->first,lexical_cast<std::string>(h->second),0,255,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(h->second > 0 && h->second > u.max_hitpoints()-u.hitpoints()) {
|
||||
h->second = u.max_hitpoints()-u.hitpoints();
|
||||
if(h->second <= 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
while(h->second > 0) {
|
||||
const Uint16 heal_colour = disp.rgb(0,0,200);
|
||||
u.heal(1);
|
||||
|
|
105
src/config.cpp
105
src/config.cpp
|
@ -69,43 +69,35 @@ struct close_FILE
|
|||
void read_file_internal(const std::string& fname, std::string& res)
|
||||
{
|
||||
const int size = file_size(fname);
|
||||
if(size == -1) {
|
||||
if(size < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
res.resize(size);
|
||||
std::vector<char> v;
|
||||
v.reserve(size);
|
||||
|
||||
const util::scoped_resource<FILE*,close_FILE> file(fopen(fname.c_str(),"rb"));
|
||||
if(file == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int block_size = 4096;
|
||||
char buf[block_size];
|
||||
const int block_size = 65536;
|
||||
|
||||
std::string::iterator i = res.begin();
|
||||
while(v.size() < size) {
|
||||
const size_t expected = minimum<size_t>(block_size,size - v.size());
|
||||
|
||||
for(;;) {
|
||||
const size_t nbytes = fread(buf,1,block_size,file);
|
||||
|
||||
//make sure the string is big enough
|
||||
const int size_diff = (res.end() - i) - nbytes;
|
||||
if(size_diff < 0) {
|
||||
res.resize(res.size() - size_diff);
|
||||
i = res.end() - nbytes;
|
||||
}
|
||||
|
||||
std::copy(buf,buf+nbytes,i);
|
||||
i += nbytes;
|
||||
|
||||
if(nbytes < block_size) {
|
||||
if(i != res.end()) {
|
||||
res.erase(i,res.end());
|
||||
if(expected > 0) {
|
||||
v.resize(v.size() + expected);
|
||||
const size_t nbytes = fread(&v[v.size() - expected],1,expected,file);
|
||||
if(nbytes < expected) {
|
||||
v.resize(v.size() - (expected - nbytes));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
res.resize(v.size());
|
||||
std::copy(v.begin(),v.end(),res.begin());
|
||||
}
|
||||
|
||||
} //end anon namespace
|
||||
|
@ -134,13 +126,21 @@ std::string read_file(const std::string& fname)
|
|||
//throws io_exception if an error occurs
|
||||
void write_file(const std::string& fname, const std::string& data)
|
||||
{
|
||||
std::ofstream file(fname.c_str());
|
||||
if(!file.good()) {
|
||||
std::cerr << "error writing to file: '" << fname << "'\n";
|
||||
throw io_exception("Error writing to file: " + fname);
|
||||
const util::scoped_resource<FILE*,close_FILE> file(fopen(fname.c_str(),"wb"));
|
||||
if(file.get() == NULL) {
|
||||
throw io_exception("Could not open file for writing: '" + fname + "'");
|
||||
}
|
||||
for(std::string::const_iterator i = data.begin(); i != data.end(); ++i) {
|
||||
file << *i;
|
||||
|
||||
const size_t block_size = 4096;
|
||||
char buf[block_size];
|
||||
|
||||
for(size_t i = 0; i < data.size(); i += block_size) {
|
||||
const size_t bytes = minimum<size_t>(block_size,data.size() - i);
|
||||
std::copy(data.begin() + i, data.begin() + i + bytes,buf);
|
||||
const size_t res = fwrite(buf,1,bytes,file.get());
|
||||
if(res != bytes) {
|
||||
throw io_exception("Error writing to file: '" + fname + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -787,15 +787,22 @@ std::string config::write() const
|
|||
// it is mapped to the first available character. Any attribute found is always followed
|
||||
// by a nul-delimited string which is the value for the attribute.
|
||||
//
|
||||
// once the number of words in the schema exceeds 'compress_extended_word', the schema
|
||||
// will begin using two-byte word codes. Any word code which has a character above
|
||||
// 'compress_extended_word' is assumed to be part of a two-byte word code, and the second
|
||||
// byte will be read as part of that word code
|
||||
//
|
||||
// the schema objects are designed to be persisted. That is, in a network game, both peers
|
||||
// can store their schema objects, and so rather than sending schema data each time, the peers
|
||||
// use and build their schemas as the game progresses, adding a new word to the schema anytime
|
||||
// it is required.
|
||||
namespace {
|
||||
const unsigned char compress_open_element = 0, compress_close_element = 1,
|
||||
compress_schema_item = 2, compress_literal_word = 3,
|
||||
compress_first_word = 4, compress_last_word = 255;
|
||||
const size_t compress_max_words = compress_last_word - compress_first_word + 1;
|
||||
const unsigned int compress_open_element = 0, compress_close_element = 1,
|
||||
compress_schema_item = 2, compress_literal_word = 3,
|
||||
compress_first_word = 4, compress_extended_word = 250,
|
||||
compress_end_words = 256;
|
||||
const size_t compress_max_basewords = compress_extended_word - compress_first_word;
|
||||
const size_t compress_max_words = compress_max_basewords + (compress_end_words - compress_extended_word)*compress_end_words;
|
||||
|
||||
void compress_output_literal_word(const std::string& word, std::vector<char>& output)
|
||||
{
|
||||
|
@ -806,12 +813,13 @@ namespace {
|
|||
|
||||
compression_schema::word_char_map::const_iterator add_word_to_schema(const std::string& word, compression_schema& schema)
|
||||
{
|
||||
const unsigned char c = compress_first_word + schema.word_to_char.size();
|
||||
|
||||
std::cerr << "inserting in schema: " << int(c) << " -> '" << word << "'\n";
|
||||
unsigned int c = compress_first_word + schema.word_to_char.size();
|
||||
if(c >= compress_extended_word) {
|
||||
c = ((compress_extended_word - 1 + c/compress_extended_word) << 8) + (c%compress_extended_word);
|
||||
}
|
||||
|
||||
schema.char_to_word.insert(std::pair<unsigned char,std::string>(c,word));
|
||||
return schema.word_to_char.insert(std::pair<std::string,unsigned char>(word,c)).first;
|
||||
schema.char_to_word.insert(std::pair<unsigned int,std::string>(c,word));
|
||||
return schema.word_to_char.insert(std::pair<std::string,unsigned int>(word,c)).first;
|
||||
}
|
||||
|
||||
compression_schema::word_char_map::const_iterator get_word_in_schema(const std::string& word, compression_schema& schema, std::vector<char>& output)
|
||||
|
@ -831,7 +839,6 @@ namespace {
|
|||
return add_word_to_schema(word,schema);
|
||||
} else {
|
||||
//it's not there, and there's no room to add it
|
||||
std::cerr << "no room for word '" << word << "' in schema\n";
|
||||
return schema.word_to_char.end();
|
||||
}
|
||||
}
|
||||
|
@ -842,7 +849,12 @@ namespace {
|
|||
const compression_schema::word_char_map::const_iterator w = get_word_in_schema(word,schema,res);
|
||||
if(w != schema.word_to_char.end()) {
|
||||
//the word is in the schema, all we have to do is output the compression code for it.
|
||||
res.push_back(w->second);
|
||||
if(w->second >= compress_extended_word) {
|
||||
res.push_back(w->second >> 8);
|
||||
res.push_back(w->second & 8);
|
||||
} else {
|
||||
res.push_back(w->second);
|
||||
}
|
||||
} else {
|
||||
//the word is not in the schema. Output it as a literal word
|
||||
res.push_back(char(compress_literal_word));
|
||||
|
@ -922,9 +934,18 @@ std::string::const_iterator config::read_compressed_internal(std::string::const_
|
|||
if(*i1 == compress_literal_word) {
|
||||
i1 = compress_read_literal_word(i1+1,i2,word);
|
||||
} else {
|
||||
const compression_schema::char_word_map::const_iterator itor = schema.char_to_word.find(*i1);
|
||||
const unsigned char c = *i1;
|
||||
unsigned int code = c;
|
||||
if(code >= compress_extended_word) {
|
||||
++i1;
|
||||
const unsigned char c = *i1;
|
||||
code <<= 8;
|
||||
code += c;
|
||||
}
|
||||
|
||||
const compression_schema::char_word_map::const_iterator itor = schema.char_to_word.find(code);
|
||||
if(itor == schema.char_to_word.end()) {
|
||||
std::cerr << "illegal char: " << int(*i1) << "\n";
|
||||
std::cerr << "illegal word code: " << code << "\n";
|
||||
throw error("Illegal character in compression input\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ typedef std::map<std::string,std::string> string_map;
|
|||
//this object holds the schema by which config objects can be compressed and decompressed.
|
||||
struct compression_schema
|
||||
{
|
||||
typedef std::map<unsigned char,std::string> char_word_map;
|
||||
typedef std::map<unsigned int,std::string> char_word_map;
|
||||
char_word_map char_to_word;
|
||||
|
||||
typedef std::map<std::string,unsigned char> word_char_map;
|
||||
typedef std::map<std::string,unsigned int> word_char_map;
|
||||
word_char_map word_to_char;
|
||||
};
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ display::display(unit_map& units, CVideo& video, const gamemap& map,
|
|||
deadAmount_(0.0), advancingAmount_(0.0), updatesLocked_(0),
|
||||
turbo_(false), grid_(false), sidebarScaling_(1.0),
|
||||
theme_(theme_cfg,screen_area()), builder_(built_terrains, map),
|
||||
firstTurn_(true), map_labels_(*this,map),
|
||||
first_turn_(true), in_game_(false), map_labels_(*this,map),
|
||||
tod_hex_mask1(NULL), tod_hex_mask2(NULL)
|
||||
{
|
||||
if(non_interactive())
|
||||
|
@ -102,7 +102,7 @@ void display::new_turn()
|
|||
{
|
||||
const time_of_day& tod = status_.get_time_of_day();
|
||||
|
||||
if(!turbo() && !firstTurn_) {
|
||||
if(!turbo() && !first_turn_) {
|
||||
image::set_image_mask("");
|
||||
|
||||
const time_of_day& old_tod = status_.get_previous_time_of_day();
|
||||
|
@ -141,7 +141,7 @@ void display::new_turn()
|
|||
tod_hex_mask2.assign(NULL);
|
||||
}
|
||||
|
||||
firstTurn_ = false;
|
||||
first_turn_ = false;
|
||||
|
||||
image::set_colour_adjustment(tod.red,tod.green,tod.blue);
|
||||
image::set_image_mask(tod.image_mask);
|
||||
|
@ -2071,6 +2071,12 @@ const theme::menu* display::menu_pressed(int mousex, int mousey, bool button_pre
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void display::begin_game()
|
||||
{
|
||||
in_game_ = true;
|
||||
create_buttons();
|
||||
}
|
||||
|
||||
void display::create_buttons()
|
||||
{
|
||||
std::cerr << "clearing buttons...\n";
|
||||
|
|
|
@ -319,7 +319,9 @@ public:
|
|||
|
||||
void remove_highlighted_loc(const gamemap::location &hex);
|
||||
|
||||
void create_buttons();
|
||||
void begin_game();
|
||||
|
||||
bool in_game() const { return in_game_; }
|
||||
|
||||
private:
|
||||
display(const display&);
|
||||
|
@ -422,9 +424,10 @@ private:
|
|||
theme theme_;
|
||||
terrain_builder builder_;
|
||||
|
||||
void create_buttons();
|
||||
std::vector<gui::button> buttons_;
|
||||
|
||||
bool firstTurn_;
|
||||
bool first_turn_, in_game_;
|
||||
|
||||
std::set<std::string> observers_;
|
||||
|
||||
|
|
|
@ -153,6 +153,12 @@ std::string get_saves_dir()
|
|||
return get_dir(dir_path);
|
||||
}
|
||||
|
||||
std::string get_cache_dir()
|
||||
{
|
||||
const std::string dir_path = get_user_data_dir() + "/cache";
|
||||
return get_dir(dir_path);
|
||||
}
|
||||
|
||||
std::string get_dir(const std::string& dir_path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -271,6 +277,35 @@ time_t file_create_time(const std::string& fname)
|
|||
return buf.st_mtime;
|
||||
}
|
||||
|
||||
time_t file_tree_modified_time(const std::string& path, time_t tm)
|
||||
{
|
||||
std::vector<std::string> files, dirs;
|
||||
get_files_in_dir(path,&files,&dirs,ENTIRE_FILE_PATH);
|
||||
|
||||
for(std::vector<std::string>::const_iterator i = files.begin(); i != files.end(); ++i) {
|
||||
const time_t t = file_create_time(*i);
|
||||
if(t > tm) {
|
||||
tm = t;
|
||||
}
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::const_iterator j = dirs.begin(); j != dirs.end(); ++j) {
|
||||
tm = file_tree_modified_time(*j,tm);
|
||||
}
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
time_t data_tree_modified_time()
|
||||
{
|
||||
static time_t cached_val = 0;
|
||||
if(cached_val == 0) {
|
||||
cached_val = file_tree_modified_time("data/");
|
||||
}
|
||||
|
||||
return cached_val;
|
||||
}
|
||||
|
||||
int file_size(const std::string& fname)
|
||||
{
|
||||
struct stat buf;
|
||||
|
|
|
@ -35,6 +35,7 @@ std::string get_dir(const std::string &dir);
|
|||
//the location of various important files
|
||||
std::string get_prefs_file();
|
||||
std::string get_saves_dir();
|
||||
std::string get_cache_dir();
|
||||
std::string get_user_data_dir();
|
||||
|
||||
//function which returns true iff the given file is a directory
|
||||
|
@ -43,8 +44,16 @@ bool is_directory(const std::string& fname);
|
|||
//function which returns true iff file with name already exists
|
||||
bool file_exists(const std::string& name);
|
||||
|
||||
//function to get the creation time of a file
|
||||
time_t file_create_time(const std::string& fname);
|
||||
|
||||
//function to get the time at which the most recently modified file
|
||||
//in a directory tree was modified at
|
||||
time_t file_tree_modified_time(const std::string& path, time_t tm=0);
|
||||
|
||||
//function to get the time at which the data/ tree was last modified at
|
||||
time_t data_tree_modified_time();
|
||||
|
||||
//returns the size of a file, or -1 if the file doesn't exist
|
||||
int file_size(const std::string& fname);
|
||||
|
||||
|
|
100
src/game.cpp
100
src/game.cpp
|
@ -203,8 +203,70 @@ LEVEL_RESULT play_game(display& disp, game_state& state, config& game_config,
|
|||
return VICTORY;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
//this function reads the game configuration, searching for valid cached copies first
|
||||
void read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, config& cfg, bool use_cache)
|
||||
{
|
||||
log_scope("read_game_cfg");
|
||||
|
||||
if(defines.size() < 4 && use_cache) {
|
||||
bool is_valid = true;
|
||||
std::stringstream str;
|
||||
for(preproc_map::const_iterator i = defines.begin(); i != defines.end(); ++i) {
|
||||
if(i->second.value != "" || i->second.arguments.empty() == false) {
|
||||
is_valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
str << "-" << i->first;
|
||||
}
|
||||
|
||||
if(is_valid) {
|
||||
const std::string& cache = get_cache_dir();
|
||||
if(cache != "") {
|
||||
const std::string fname = cache + "/game.cfg-cache" + str.str();
|
||||
if(file_exists(fname) && file_create_time(fname) > data_tree_modified_time()) {
|
||||
std::cerr << "found valid cache at '" << fname << "' using it\n";
|
||||
log_scope("read cache");
|
||||
compression_schema schema;
|
||||
|
||||
try {
|
||||
cfg.read_compressed(read_file(fname),schema);
|
||||
return;
|
||||
} catch(config::error&) {
|
||||
std::cerr << "cache is corrupt. Loading from files\n";
|
||||
} catch(io_exception&) {
|
||||
std::cerr << "error reading cache. Loading from files\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "no valid cache found. Writing cache to '" << fname << "'\n";
|
||||
|
||||
//read the file and then write to the cache
|
||||
cfg.read(preprocess_file("data/game.cfg",&defines,&line_src));
|
||||
try {
|
||||
compression_schema schema;
|
||||
write_file(fname,cfg.write_compressed(schema));
|
||||
} catch(io_exception& e) {
|
||||
std::cerr << "could not write to cache '" << fname << "'\n";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "caching cannot be done. Reading file\n";
|
||||
cfg.read(preprocess_file("data/game.cfg",&defines,&line_src));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int play_game(int argc, char** argv)
|
||||
{
|
||||
const int start_ticks = SDL_GetTicks();
|
||||
|
||||
//parse arguments that shouldn't require a display device
|
||||
int arg;
|
||||
for(arg = 1; arg != argc; ++arg) {
|
||||
|
@ -222,7 +284,8 @@ int play_game(int argc, char** argv)
|
|||
<< " --path Prints the name of the game data directory and exits\n"
|
||||
<< " -t, --test Runs the game in a small example scenario\n"
|
||||
<< " -w, --windowed Runs the game in windowed mode\n"
|
||||
<< " -v, --version Prints the game's version number and exits\n";
|
||||
<< " -v, --version Prints the game's version number and exits\n"
|
||||
<< " --nocache Disables caching of game data\n";
|
||||
return 0;
|
||||
} else if(val == "--version" || val == "-v") {
|
||||
std::cout << "Battle for Wesnoth " << game_config::version
|
||||
|
@ -249,16 +312,21 @@ int play_game(int argc, char** argv)
|
|||
const events::event_context main_event_context;
|
||||
|
||||
std::cerr << "initialized managers\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
bool test_mode = false, multiplayer_mode = false, no_gui = false;
|
||||
|
||||
bool use_caching = true;
|
||||
|
||||
for(arg = 1; arg != argc; ++arg) {
|
||||
const std::string val(argv[arg]);
|
||||
if(val.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(val == "--resolution" || val == "-r") {
|
||||
if(val == "--nocache") {
|
||||
use_caching = false;
|
||||
} else if(val == "--resolution" || val == "-r") {
|
||||
if(arg+1 != argc) {
|
||||
++arg;
|
||||
const std::string val(argv[arg]);
|
||||
|
@ -299,6 +367,7 @@ int play_game(int argc, char** argv)
|
|||
}
|
||||
|
||||
std::cerr << "parsed arguments\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
if(no_gui && !multiplayer_mode) {
|
||||
std::cerr << "--nogui flag is only valid with --multiplayer flag\n";
|
||||
|
@ -381,18 +450,21 @@ int play_game(int argc, char** argv)
|
|||
const cursor::manager cursor_manager;
|
||||
|
||||
std::cerr << "initialized gui\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
//load in the game's configuration files
|
||||
preproc_map defines_map;
|
||||
defines_map["NORMAL"] = preproc_define();
|
||||
defines_map["MEDIUM"] = preproc_define();
|
||||
std::vector<line_source> line_src;
|
||||
|
||||
config game_config;
|
||||
|
||||
try {
|
||||
log_scope("loading config");
|
||||
const std::string game_cfg = preprocess_file("data/game.cfg",&defines_map,&line_src);
|
||||
game_config.read(game_cfg,&line_src);
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
read_game_cfg(defines_map,line_src,game_config,use_caching);
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
} catch(config::error& e) {
|
||||
display::unit_map u_map;
|
||||
config dummy_cfg("");
|
||||
|
@ -407,6 +479,7 @@ int play_game(int argc, char** argv)
|
|||
game_config::load_config(game_config.child("game_config"));
|
||||
|
||||
std::cerr << "parsed config files\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
const config::child_list& units = game_config.get_children("units");
|
||||
if(units.empty()) {
|
||||
|
@ -429,6 +502,7 @@ int play_game(int argc, char** argv)
|
|||
}
|
||||
|
||||
std::cerr << "set language\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
if(!no_gui) {
|
||||
SDL_WM_SetCaption(string_table["game_title"].c_str(), NULL);
|
||||
|
@ -440,6 +514,7 @@ int play_game(int argc, char** argv)
|
|||
sound::play_music(game_config::title_music);
|
||||
|
||||
std::cerr << "started music\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
game_state state;
|
||||
|
||||
|
@ -449,6 +524,7 @@ int play_game(int argc, char** argv)
|
|||
std::vector<team>(),dummy_cfg,dummy_cfg);
|
||||
|
||||
std::cerr << "initialized display object\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
|
||||
if(test_mode) {
|
||||
state.campaign_type = "test";
|
||||
|
@ -599,6 +675,7 @@ int play_game(int argc, char** argv)
|
|||
recorder.clear();
|
||||
|
||||
std::cerr << "showing title screen...\n";
|
||||
std::cerr << (SDL_GetTicks() - start_ticks) << "\n";
|
||||
gui::TITLE_RESULT res = gui::CONTINUE;
|
||||
|
||||
while(res == gui::CONTINUE) {
|
||||
|
@ -608,6 +685,7 @@ int play_game(int argc, char** argv)
|
|||
std::cerr << "title screen returned result\n";
|
||||
|
||||
if(res == gui::QUIT_GAME) {
|
||||
std::cerr << "quiting game...\n";
|
||||
return 0;
|
||||
} else if(res == gui::LOAD_GAME) {
|
||||
|
||||
|
@ -857,7 +935,9 @@ int play_game(int argc, char** argv)
|
|||
}
|
||||
|
||||
//make a new game config item based on the difficulty level
|
||||
config game_config(preprocess_file("data/game.cfg", &defines_map));
|
||||
std::vector<line_source> line_src;
|
||||
config game_config;
|
||||
read_game_cfg(defines_map,line_src,game_config,use_caching);
|
||||
|
||||
const config::child_list& units = game_config.get_children("units");
|
||||
if(units.empty()) {
|
||||
|
@ -868,8 +948,7 @@ int play_game(int argc, char** argv)
|
|||
|
||||
game_data units_data(*units[0]);
|
||||
|
||||
const LEVEL_RESULT result = play_game(disp,state,game_config,
|
||||
units_data,video);
|
||||
const LEVEL_RESULT result = play_game(disp,state,game_config,units_data,video);
|
||||
if(result == VICTORY) {
|
||||
gui::show_dialog(disp,NULL,
|
||||
string_table["end_game_heading"],
|
||||
|
@ -884,7 +963,10 @@ int play_game(int argc, char** argv)
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
try {
|
||||
return play_game(argc,argv);
|
||||
std::cerr << "started game: " << SDL_GetTicks() << "\n";
|
||||
const int res = play_game(argc,argv);
|
||||
std::cerr << "exiting with code " << res << "\n";
|
||||
return res;
|
||||
} catch(CVideo::error&) {
|
||||
std::cerr << "Could not initialize video. Exiting.\n";
|
||||
} catch(font::manager::error&) {
|
||||
|
@ -895,6 +977,8 @@ int main(int argc, char** argv)
|
|||
std::cerr << "Could not create button: Image could not be found\n";
|
||||
} catch(CVideo::quit&) {
|
||||
//just means the game should quit
|
||||
} catch(end_level_exception&) {
|
||||
std::cerr << "caught end_level_exception (quitting)\n";
|
||||
} catch(...) {
|
||||
std::cerr << "Unhandled exception. Exiting\n";
|
||||
}
|
||||
|
|
|
@ -239,9 +239,9 @@ std::string get_hotkey_name(hotkey_item i)
|
|||
|
||||
void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor* executor)
|
||||
{
|
||||
if(event.keysym.sym == SDLK_ESCAPE) {
|
||||
const int res = gui::show_dialog(disp,NULL,"",
|
||||
string_table["quit_message"],gui::YES_NO);
|
||||
if(event.keysym.sym == SDLK_ESCAPE && disp.in_game()) {
|
||||
std::cerr << "escape pressed..showing quit\n";
|
||||
const int res = gui::show_dialog(disp,NULL,"",string_table["quit_message"],gui::YES_NO);
|
||||
if(res == 0) {
|
||||
throw end_level_exception(QUIT);
|
||||
} else {
|
||||
|
@ -400,10 +400,14 @@ void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* ex
|
|||
executor->search();
|
||||
break;
|
||||
case HOTKEY_QUIT_GAME: {
|
||||
const int res = gui::show_dialog(disp,NULL,"",string_table["quit_message"],gui::YES_NO);
|
||||
if(res == 0) {
|
||||
throw end_level_exception(QUIT);
|
||||
if(disp.in_game()) {
|
||||
std::cerr << "is in game -- showing quit message\n";
|
||||
const int res = gui::show_dialog(disp,NULL,"",string_table["quit_message"],gui::YES_NO);
|
||||
if(res == 0) {
|
||||
throw end_level_exception(QUIT);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,6 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
|
|||
game_state& state_of_game,
|
||||
const std::vector<config*>& story)
|
||||
{
|
||||
std::cerr << "starting level '" << string_table["defeat_message"] << "'\n";
|
||||
//if the entire scenario should be randomly generated
|
||||
if((*level)["scenario_generation"] != "") {
|
||||
std::cerr << "randomly generating scenario...\n";
|
||||
|
@ -322,7 +321,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
|
|||
turn_info::floating_textbox textbox_info;
|
||||
|
||||
try {
|
||||
gui.create_buttons();
|
||||
gui.begin_game();
|
||||
gui.adjust_colours(0,0,0);
|
||||
game_events::fire("prestart");
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace {
|
|||
int commands_disabled = 0;
|
||||
}
|
||||
|
||||
command_disabler::command_disabler(display* disp) : hotkey::basic_handler(disp)
|
||||
command_disabler::command_disabler(display* disp)
|
||||
{
|
||||
++commands_disabled;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ private:
|
|||
display& gui_;
|
||||
};
|
||||
|
||||
struct command_disabler : private hotkey::basic_handler
|
||||
struct command_disabler
|
||||
{
|
||||
command_disabler(display* disp);
|
||||
~command_disabler();
|
||||
|
|
|
@ -69,13 +69,28 @@ bool game::filter_commands(network::connection player, config& cfg)
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string describe_turns(int turn, const std::string& num_turns)
|
||||
{
|
||||
char buf[50];
|
||||
sprintf(buf,"%d/",int(turn));
|
||||
|
||||
if(num_turns == "-1") {
|
||||
return buf + std::string("-");
|
||||
} else {
|
||||
return buf + num_turns;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void game::start_game()
|
||||
{
|
||||
started_ = true;
|
||||
|
||||
describe_slots();
|
||||
if(description()) {
|
||||
description()->values["turn"] = "1";
|
||||
description()->values["turn"] = describe_turns(1,level()["turns"]);
|
||||
}
|
||||
|
||||
allow_observers_ = level_["observer"] != "no";
|
||||
|
@ -175,9 +190,7 @@ bool game::end_turn()
|
|||
return false;
|
||||
}
|
||||
|
||||
char buf[50];
|
||||
sprintf(buf,"%d",int(turn));
|
||||
desc->values["turn"] = buf;
|
||||
desc->values["turn"] = describe_turns(int(turn),level()["turns"]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -298,7 +311,7 @@ bool game::player_on_team(const std::string& team, network::connection player) c
|
|||
}
|
||||
}
|
||||
|
||||
//other hosts than the game host
|
||||
//hosts other than the game host
|
||||
const std::map<network::connection,std::string>::const_iterator side = sides_.find(player);
|
||||
if(side != sides_.end()) {
|
||||
const config* const side_cfg = level_.find_child("side","side",side->second);
|
||||
|
|
Loading…
Add table
Reference in a new issue