--- deliantra/server/common/map.C 2007/01/03 02:51:09 1.67 +++ deliantra/server/common/map.C 2007/01/13 23:06:12 1.72 @@ -1,6 +1,7 @@ /* CrossFire, A Multiplayer game for X-windows + Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team Copyright (C) 2001-2003 Mark Wedel & Crossfire Development Team Copyright (C) 1992 Frank Tore Johansen @@ -401,7 +402,7 @@ * mapflags is the same as we get with load_original_map */ bool -maptile::load_objects (object_thawer &thawer) +maptile::_load_objects (object_thawer &thawer) { int unique; object *op, *prev = NULL, *last_more = NULL, *otmp; @@ -487,12 +488,12 @@ } bool -maptile::save_objects (object_freezer &freezer, int flags) +maptile::_save_objects (object_freezer &freezer, int flags) { static int cede_count = 0; if (flags & IO_HEADER) - save_header (freezer); + _save_header (freezer); if (!spaces) return false; @@ -531,7 +532,7 @@ } bool -maptile::load_objects (const char *path, bool skip_header) +maptile::_load_objects (const char *path, bool skip_header) { object_thawer thawer (path); @@ -549,15 +550,15 @@ thawer.skip_kv (kw); } - return load_objects (thawer); + return _load_objects (thawer); } bool -maptile::save_objects (const char *path, int flags) +maptile::_save_objects (const char *path, int flags) { object_freezer freezer; - if (!save_objects (freezer, flags)) + if (!_save_objects (freezer, flags)) return false; return freezer.save (path); @@ -731,12 +732,8 @@ * MSW 2001-07-01 */ bool -maptile::load_header (object_thawer &thawer) +maptile::_load_header (object_thawer &thawer) { - char buf[HUGE_BUF], msgbuf[HUGE_BUF], maplorebuf[HUGE_BUF], *key = NULL, *value, *end; - int msgpos = 0; - int maplorepos = 0; - for (;;) { keyword kw = thawer.get_kv (); @@ -750,6 +747,11 @@ case KW_end: return true; + default: + case KW_ERROR: + LOG (llevError, "%s: skipping errornous line (%s) while reading map header.\n", &path, thawer.last_keyword); + break; + case KW_msg: thawer.get_ml (KW_endmsg, msg); break; @@ -809,10 +811,6 @@ case KW_tile_path_2: thawer.get (tile_path [1]); break; case KW_tile_path_3: thawer.get (tile_path [2]); break; case KW_tile_path_4: thawer.get (tile_path [3]); break; - - default: - LOG (llevError, "%s: skipping unknown key in map header: %s\n", &path, keyword_str [kw]); - break; } } @@ -820,14 +818,14 @@ } bool -maptile::load_header (const char *path) +maptile::_load_header (const char *path) { object_thawer thawer (path); if (!thawer) return false; - return load_header (thawer); + return _load_header (thawer); } /****************************************************************************** @@ -860,7 +858,7 @@ } bool -maptile::save_header (object_freezer &freezer) +maptile::_save_header (object_freezer &freezer) { #define MAP_OUT(k) freezer.put (KW_ ## k, k) #define MAP_OUT2(k,v) freezer.put (KW_ ## k, v) @@ -919,11 +917,11 @@ } bool -maptile::save_header (const char *path) +maptile::_save_header (const char *path) { object_freezer freezer; - if (!save_header (freezer)) + if (!_save_header (freezer)) return false; return freezer.save (path); @@ -1280,30 +1278,34 @@ faces [2] = floor; faces_obj [2] = floor != blank_face ? floor_obj : 0; } -/* this updates the orig_map->tile_map[tile_num] value after loading - * the map. It also takes care of linking back the freshly loaded +/* this updates the orig_map->tile_map[tile_num] value after finding + * the map. It also takes care of linking back the freshly found * maps tile_map values if it tiles back to this one. It returns - * the value of orig_map->tile_map[tile_num]. It really only does this - * so that it is easier for calling functions to verify success. + * the value of orig_map->tile_map[tile_num]. */ -static maptile * -load_and_link_tiled_map (maptile *orig_map, int tile_num) +static inline maptile * +find_and_link (maptile *orig_map, int tile_num) { - maptile *mp = orig_map->load_map_sync (orig_map->tile_path [tile_num], orig_map); + maptile *mp = orig_map->tile_map [tile_num]; - if (!mp || mp->in_memory != MAP_IN_MEMORY) + if (!mp) { - // emergency mode, manufacture a dummy map, this creates a memleak, but thats fine - LOG (llevError, "FATAL: cannot load tiled map %s from %s, leaking memory and worse!\n", - &orig_map->tile_path[tile_num], &orig_map->path); - mp = new maptile (1, 1); - mp->alloc (); - mp->in_memory = MAP_IN_MEMORY; + mp = orig_map->find_sync (orig_map->tile_path [tile_num], orig_map); + + if (!mp) + { + // emergency mode, manufacture a dummy map, this creates a memleak, but thats fine + LOG (llevError, "FATAL: cannot load tiled map %s from %s, leaking memory and worse!\n", + &orig_map->tile_path[tile_num], &orig_map->path); + mp = new maptile (1, 1); + mp->alloc (); + mp->in_memory = MAP_IN_MEMORY; + } } int dest_tile = (tile_num + 2) % 4; - orig_map->tile_map[tile_num] = mp; + orig_map->tile_map [tile_num] = mp; // optimisation: back-link map to origin map if euclidean //TODO: non-euclidean maps MUST GO @@ -1313,6 +1315,12 @@ return mp; } +static inline void +load_and_link (maptile *orig_map, int tile_num) +{ + find_and_link (orig_map, tile_num)->load_sync (); +} + /* this returns TRUE if the coordinates (x,y) are out of * map m. This function also takes into account any * tiling considerations, loading adjacant maps as needed. @@ -1337,7 +1345,7 @@ return 1; if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 3); + find_and_link (m, 3); return out_of_map (m->tile_map[3], x + m->tile_map[3]->width, y); } @@ -1348,7 +1356,7 @@ return 1; if (!m->tile_map[1] || m->tile_map[1]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 1); + find_and_link (m, 1); return out_of_map (m->tile_map[1], x - m->width, y); } @@ -1359,7 +1367,7 @@ return 1; if (!m->tile_map[0] || m->tile_map[0]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 0); + find_and_link (m, 0); return out_of_map (m->tile_map[0], x, y + m->tile_map[0]->height); } @@ -1370,7 +1378,7 @@ return 1; if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 2); + find_and_link (m, 2); return out_of_map (m->tile_map[2], x, y - m->height); } @@ -1390,60 +1398,52 @@ * and then figuring out what the real map is */ maptile * -get_map_from_coord (maptile *m, sint16 *x, sint16 *y) +maptile::xy_find (sint16 &x, sint16 &y) { - if (*x < 0) + if (x < 0) { - if (!m->tile_path[3]) + if (!tile_path[3]) return 0; - if (!m->tile_map[3] || m->tile_map[3]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 3); - - *x += m->tile_map[3]->width; - return (get_map_from_coord (m->tile_map[3], x, y)); + find_and_link (this, 3); + x += tile_map[3]->width; + return tile_map[3]->xy_find (x, y); } - if (*x >= m->width) + if (x >= width) { - if (!m->tile_path[1]) + if (!tile_path[1]) return 0; - if (!m->tile_map[1] || m->tile_map[1]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 1); - - *x -= m->width; - return (get_map_from_coord (m->tile_map[1], x, y)); + find_and_link (this, 1); + x -= width; + return tile_map[1]->xy_find (x, y); } - if (*y < 0) + if (y < 0) { - if (!m->tile_path[0]) + if (!tile_path[0]) return 0; - if (!m->tile_map[0] || m->tile_map[0]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 0); - - *y += m->tile_map[0]->height; - return (get_map_from_coord (m->tile_map[0], x, y)); + find_and_link (this, 0); + y += tile_map[0]->height; + return tile_map[0]->xy_find (x, y); } - if (*y >= m->height) + if (y >= height) { - if (!m->tile_path[2]) + if (!tile_path[2]) return 0; - if (!m->tile_map[2] || m->tile_map[2]->in_memory != MAP_IN_MEMORY) - load_and_link_tiled_map (m, 2); - - *y -= m->height; - return (get_map_from_coord (m->tile_map[2], x, y)); + find_and_link (this, 2); + y -= height; + return tile_map[2]->xy_find (x, y); } /* Simple case - coordinates are within this local * map. */ - return m; + return this; } /** @@ -1456,6 +1456,8 @@ if (!map1 || !map2) return 0; + //TODO: this doesn't actually check corretcly when intermediate maps are not loaded + //fix: compare paths instead (this is likely faster, too!) if (map1 == map2) { *dx = 0; @@ -1527,6 +1529,23 @@ return 1; } +maptile * +maptile::xy_load (sint16 &x, sint16 &y) +{ + maptile *map = xy_find (x, y); + + if (map) + map->load_sync (); + + return map; +} + +maptile * +get_map_from_coord (maptile *m, sint16 *x, sint16 *y) +{ + return m->xy_load (*x, *y); +} + /* From map.c * This is used by get_player to determine where the other * creature is. get_rangevector takes into account map tiling,