summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/maps.cc
diff options
context:
space:
mode:
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());
+ }
+ }
+}