summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/maps.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-24 16:27:58 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-24 16:27:58 +0000
commit93f5fdd067279f953af9440fa7c712985e6ecf34 (patch)
tree177f36448c1dbeedf772d627e654714c704d6b22 /crawl-ref/source/maps.cc
parentc633d5d2b956aab18819d51236982db57ee17134 (diff)
downloadcrawl-ref-93f5fdd067279f953af9440fa7c712985e6ecf34.tar.gz
crawl-ref-93f5fdd067279f953af9440fa7c712985e6ecf34.zip
Implemented .des file caching (speeds startup a fair bit): .des files are
parsed only once (unless they're modified again). Crawl also keeps only map stubs in memory (name, place, orient, tags) and loads the map body only when it is actually selected by the dungeon builder. This probably breaks the Windows build, will be fixed soonish. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1637 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/maps.cc')
-rw-r--r--crawl-ref/source/maps.cc193
1 files changed, 189 insertions, 4 deletions
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 97a2eec5d8..3e27840dd3 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -27,9 +27,7 @@
#include "misc.h"
#include "stuff.h"
-#include "levcomp.h"
-
-static int write_vault(const map_def &mdef, map_type mt,
+static int write_vault(map_def &mdef, map_type mt,
vault_placement &,
std::vector<vault_placement> *);
static int apply_vault_definition(
@@ -80,10 +78,12 @@ int vault_main(
return write_vault( vdefs[which_vault], vgrid, place, avoid );
} // end vault_main()
-static int write_vault(const map_def &mdef, map_type map,
+static int write_vault(map_def &mdef, map_type map,
vault_placement &place,
std::vector<vault_placement> *avoid)
{
+ mdef.load();
+
// Copy the map so we can monkey with it.
place.map = mdef;
@@ -354,8 +354,176 @@ const map_def *map_by_index(int index)
/////////////////////////////////////////////////////////////////////////////
// Reading maps from .des files.
+dlua_chunk lc_file_prelude;
+std::string lc_desfile;
+map_def lc_map;
+level_range lc_range;
+depth_ranges lc_default_depths;
+
+std::set<std::string> map_files_read;
+
+extern int yylineno;
+
+void reset_map_parser()
+{
+ lc_map.init();
+ lc_range.reset();
+ lc_default_depths.clear();
+ lc_file_prelude.clear();
+
+ yylineno = 1;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static bool checked_des_index_dir = false;
+
+#define DESCACHE_VER 1000
+
+static void check_des_index_dir()
+{
+ if (checked_des_index_dir)
+ return;
+
+ std::string desdir = get_savedir_path("des");
+ if (!check_dir("Data file cache", desdir, true))
+ end(1, true, "Can't create data file cache: %s", desdir.c_str());
+
+ checked_des_index_dir = true;
+}
+
+std::string get_descache_path(const std::string &file,
+ const std::string &ext)
+{
+ const std::string basename =
+ change_file_extension(get_base_filename(file), ext);
+ return get_savedir_path("des/" + basename);
+}
+
+static bool verify_file_version(const std::string &file)
+{
+ FILE *inf = fopen(file.c_str(), "rb");
+ if (!inf)
+ return (false);
+
+ const long ver = readLong(inf);
+ fclose(inf);
+
+ return (ver == DESCACHE_VER);
+}
+
+static bool verify_map_index(const std::string &base)
+{
+ return verify_file_version(base + ".idx");
+}
+
+static bool verify_map_full(const std::string &base)
+{
+ return verify_file_version(base + ".dsc");
+}
+
+static bool load_map_index(const std::string &base)
+{
+ FILE *inf = fopen((base + ".idx").c_str(), "rb");
+ // Discard version (it's been checked by verify_map_index).
+ readLong(inf);
+ const int nmaps = readShort(inf);
+ const int nexist = vdefs.size();
+ vdefs.resize( nexist + nmaps, map_def() );
+ for (int i = 0; i < nmaps; ++i)
+ {
+ vdefs[nexist + i].read_index(inf);
+ vdefs[nexist + i].set_file(base);
+ }
+ fclose(inf);
+
+ return (true);
+}
+
+static bool load_map_cache(const std::string &filename)
+{
+ check_des_index_dir();
+ const std::string descache_base = get_descache_path(filename, "");
+
+ file_lock deslock(descache_base + ".lk", "rb", false);
+
+ if (is_newer(filename, descache_base + ".idx")
+ || is_newer(filename, descache_base + ".dsc"))
+ return (false);
+
+ if (!verify_map_index(descache_base) || !verify_map_full(descache_base))
+ return (false);
+
+ return load_map_index(descache_base);
+}
+
+static void write_map_prelude(const std::string &filebase)
+{
+ const std::string luafile = filebase + ".lua";
+ if (lc_file_prelude.empty())
+ {
+ unlink(luafile.c_str());
+ return;
+ }
+
+ FILE *outf = fopen(luafile.c_str(), "w");
+ if (!outf)
+ end(1, true, "Unable to open %s for writing", luafile.c_str());
+ fprintf(outf, "%s", lc_file_prelude.lua_string().c_str());
+ fclose(outf);
+}
+
+static void write_map_full(const std::string &filebase, size_t vs, size_t ve)
+{
+ const std::string cfile = filebase + ".dsc";
+ FILE *outf = fopen(cfile.c_str(), "wb");
+ if (!outf)
+ end(1, true, "Unable to open %s for writing", cfile.c_str());
+
+ writeLong(outf, DESCACHE_VER);
+ for (size_t i = vs; i < ve; ++i)
+ vdefs[i].write_full(outf);
+ fclose(outf);
+}
+
+static void write_map_index(const std::string &filebase, size_t vs, size_t ve)
+{
+ const std::string cfile = filebase + ".idx";
+ FILE *outf = fopen(cfile.c_str(), "wb");
+ if (!outf)
+ end(1, true, "Unable to open %s for writing", cfile.c_str());
+
+ writeLong(outf, DESCACHE_VER);
+ writeShort(outf, ve > vs? ve - vs : 0);
+ for (size_t i = vs; i < ve; ++i)
+ vdefs[i].write_index(outf);
+ fclose(outf);
+}
+
+static void write_map_cache(const std::string &filename, size_t vs, size_t ve)
+{
+ check_des_index_dir();
+
+ const std::string descache_base = get_descache_path(filename, "");
+
+ file_lock deslock(descache_base + ".lk", "wb");
+
+ write_map_prelude(descache_base);
+ write_map_full(descache_base, vs, ve);
+ write_map_index(descache_base, vs, ve);
+}
+
static void parse_maps(const std::string &s)
{
+ const std::string base = get_base_filename(s);
+ if (map_files_read.find(base) != map_files_read.end())
+ end(1, false, "Map file %s has already been read.", base.c_str());
+
+ map_files_read.insert(base);
+
+ if (load_map_cache(s))
+ return;
+
FILE *dat = fopen(s.c_str(), "r");
if (!dat)
end(1, true, "Failed to open %s for reading", s.c_str());
@@ -366,8 +534,11 @@ static void parse_maps(const std::string &s)
extern FILE *yyin;
yyin = dat;
+ size_t file_start = vdefs.size();
yyparse();
fclose(dat);
+
+ write_map_cache(s, file_start, vdefs.size());
}
void read_maps()
@@ -397,3 +568,17 @@ void add_parsed_map( const map_def &md )
map.fixup();
vdefs.push_back( map );
}
+
+void run_map_preludes()
+{
+ for (int i = 0, size = vdefs.size(); i < size; ++i)
+ {
+ if (!vdefs[i].prelude.empty())
+ {
+ std::string err = vdefs[i].run_lua(true);
+ if (!err.empty())
+ mprf(MSGCH_WARN, "Lua error (map %s): %s",
+ vdefs[i].name.c_str(), err.c_str());
+ }
+ }
+}