Browse Source

I'm still here!
Rewrote fame ranking lists- changed MAP_NAME_LENGTH to 12, now there's MAP_NAME_LENGTH_EXT at 16 for
uses where there is / may be the .gat extension, code adjusted accordingly
- moved map_normalize_name to mapindex_normalize_name so that everything
handling map names uses the same extension-removing function
- greatly enhanced the map cache generator, complete documentation on the
tool and the map cache format can be found in doc/
- the map cache format changed a bit as a consequence, but of course a new
valid one is included (contains latest Nameless Island maps)
- fixed a duplicate entry in map index


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10167 54d463be-8e91-2dee-dedb-b68131a5f0ec

DracoRPG 18 years ago
parent
commit
7c8f12ccd5

+ 11 - 0
Changelog-Trunk.txt

@@ -5,6 +5,17 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 
 
 2007/04/07
 2007/04/07
+	* Final touches to the whole map crap [DracoRPG]
+	- changed MAP_NAME_LENGTH to 12, now there's MAP_NAME_LENGTH_EXT at 16 for
+	  uses where there is / may be the .gat extension, code adjusted accordingly
+	- moved map_normalize_name to mapindex_normalize_name so that everything
+	  handling map names uses the same extension-removing function
+	- greatly enhanced the map cache generator, complete documentation on the
+	  tool and the map cache format can be found in doc/
+	- the map cache format changed a bit as a consequence, but of course a new
+	  valid one is included (contains latest Nameless Island maps)
+	- and I'm sorry for the number of times I've moved around and renamed files,
+	  now the final structure should have been reached
 	* Capped clif_heal's heal field (the argument received is int, but the
 	* Capped clif_heal's heal field (the argument received is int, but the
 	  packet field is short, meaning that if the heal is high enough, the client
 	  packet field is short, meaning that if the heal is high enough, the client
 	  would receive a negative heal amount). [Skotlex]
 	  would receive a negative heal amount). [Skotlex]

+ 11 - 1
conf-tmpl/maps_athena.conf

@@ -744,7 +744,6 @@ map: ice_dun04
 
 
 // --- Veins & Thor Dungeon ---
 // --- Veins & Thor Dungeon ---
 // -- 2006-12-19sdata_k.gpf --
 // -- 2006-12-19sdata_k.gpf --
-
 map: que_thor
 map: que_thor
 map: thor_camp
 map: thor_camp
 map: thor_v01
 map: thor_v01
@@ -760,6 +759,17 @@ map: ve_fild05
 map: ve_fild06
 map: ve_fild06
 map: ve_fild07
 map: ve_fild07
 
 
+// --- Unknown Island & Abbey Dungeon ---
+// -- 2007-04-02sdata_k.gpf
+map: nameless_i
+map: nameless_n
+map: nameless_in
+map: abbey01
+map: abbey02
+map: abbey03
+map: poring_w01
+map: poring_w02
+
 //------------------------- Clone Maps ---------------------------
 //------------------------- Clone Maps ---------------------------
 //------------------------- Extra Maps ---------------------------
 //------------------------- Extra Maps ---------------------------
 
 

+ 2 - 0
db/Changelog.txt

@@ -21,6 +21,8 @@
 ========================
 ========================
 
 
 04/07
 04/07
+	* Updated map index and map cache with Nameless Island maps [DracoRPG]
+	- also removed the duplicate g_room2 entry from map index, read the note
 	* Corrected Aliza card's item_db line. [Skotlex]
 	* Corrected Aliza card's item_db line. [Skotlex]
 04/05
 04/05
 	* Fixed some items that should heal percentual hp/sp [Playtester]
 	* Fixed some items that should heal percentual hp/sp [Playtester]

+ 0 - 15
db/grf_files.txt

@@ -1,15 +0,0 @@
-//-----------------------------------------
-// GRF List
-//-----------------------------------------
-
-grf: C:\Program Files\Gravity\RO\data.grf
-grf: C:\Program Files\Gravity\RO\sdata.grf
-
-// You may add more in this format
-// grf: <data file path>
-
-//------ Others ---------------------------
-
-//Path to directory that contains the data dir 
-//NOTE: Path must include trailing backslash, only one data_dir entry is supported.
-//data_dir: C:\Program Files\Gravity\RO\

BIN
db/map_cache.dat


+ 15 - 2
db/map_list.txt → db/map_index.txt

@@ -9,6 +9,11 @@
 //mapname <- map will use index of previous map +1
 //mapname <- map will use index of previous map +1
 //Note that map index 0 is special and reserved for "error" status. 
 //Note that map index 0 is special and reserved for "error" status. 
 
 
+// NOTE TO DEVELOPERS
+// Due to a removed duplicate, index 591 is free, if you have to add a single map,
+// please add it there instead of the end. Then remove the 592 on next line (rachel)
+// and remove all those comments.  ~DracoRPG
+
 alb_ship 1
 alb_ship 1
 alb2trea
 alb2trea
 alberta
 alberta
@@ -599,8 +604,8 @@ job_hunter
 job_knight
 job_knight
 job_priest
 job_priest
 job_wizard
 job_wizard
-g_room2
-rachel
+// INDEX 591 IS FREE, PLEASE USE IT
+rachel 592
 ra_in01
 ra_in01
 ra_fild01
 ra_fild01
 ra_fild02
 ra_fild02
@@ -645,6 +650,14 @@ ve_fild07
 poring_c01
 poring_c01
 poring_c02
 poring_c02
 que_ng
 que_ng
+nameless_i
+nameless_n
+nameless_in
+abbey01
+abbey02
+abbey03
+poring_w01
+poring_w02
 
 
 
 
 // Only add maps under this line if they are not standard maps!
 // Only add maps under this line if they are not standard maps!

+ 60 - 11
doc/map_cache.txt

@@ -1,18 +1,67 @@
-"How to use the mapcache builder"
-DracoRPG
+//===== Athena Doc ========================================
+//= Map Cache Builder and Format Documentation
+//===== By ================================================
+//= DracoRPG
+//===== Version ===========================================
+//= 1.0
+//=========================================================
+//= 0.1 - Short howto for the initial builder version
+//= 1.0 - Complete manual covering the improved version
+//===== Description =======================================
+//= A complete manual for eAthena's map cache generator
+//= as well as a reference on the map cache format used
+//=========================================================
 
 
+Preface:
+-------------------------------------------------------------------------------
 
 
-This is only useful if you have custom maps, as eAthena is provided with an updated mapcache containing every map
-from kRO Sakray's data.
+Since SVN revision ~10000, the map-server does not know how to read RO client files anymore. It reads maps from a
+"map cache" file that contains all and only the useful data about the maps. A map cache containing every official
+kRO Sakray map currently supported by eAthena is provided as a default.
+If you have custom maps or want to minimize the size of your map cache because your server does not load all of them
+(multi-map-server or light test server), you can use the map cache builder to generate a new one fitting your needs.
 
 
-1. First add the path to the directory / GRF containing your maps to db/grf_files.txt
-/!\ Please note you must also have the official maps as the whole mapcache will be rebuilt from scratch
+Map cache builder manual:
+-------------------------------------------------------------------------------
 
 
-2. Then add those custom maps at the end of db/map_list.txt, carefully chosing their index
+The source code for the map cache builder is located in src/tool/. It can be built using "make tools" if you use the Makefile
+or using the "mapcache" project under Visual Studio. Named "mapcache", the executable will be in your eAthena main folder.
+The map cache builder needs 3 file paths : one is a list of GRFs and/or data directory containing the maps, the second
+is the list of maps to add to the map cache, and the last one is the path of the map cache to generate. Default values for
+those paths are "tools/mapcache/grf_files.txt", "db/map_index.txt" and "db/map_cache.dat".
+The list of GRF and/or data directory must follow the format and indication of the default file: as many "grf:" entries as
+you wish and optionally one only "data_dir:" entry with trailing backslash included. // comments are supported as usual.
+In fact, any file with one map name per line can be used as a map list, that's why the map index list is used as a default:
+we are sure it contains every map supported by the server. Anything after the map name is ignored, // comments are supported
+and if the first word on the line is "map:" then the second word is used as the map name instead: that allows using
+maps_athena.conf as your map list, which is handy if you want to generate a minimal map cache for each of your multiple
+map-servers.
+The map cache file path can point to an already existing file, as the builder adds a map only if it's not already cached.
+This way, you can add custom maps to the base map cache without even needing kRO Sakray maps. If you wish to rebuild the
+entire map cache, though, you can either provide a path to a non-existing file, or force the rebuild mode.
 
 
-3. Now just run the mapcache builder and it'll build a new one at db/map_cache.dat
+Here are the command-line arguments you can provide to the map cache builder to customize its behavior:
+ -grf path/to/grf/list
+   Allows to specify the file containing the list of GRFs and/or data directory
+ -list path/to/map/list
+   Allows to specify the file containing the list of maps to add to the map cache
+ -cache path/to/map/cache
+   Allows to specify the path to the generated map cache
+ - rebuild
+   Allows to force the rebuild mode (map cache will be overwritten even if it already exists)
 
 
 
 
-NOTE:
-You can override those default paths by providing your own ones as command-line arguments to the mapcache builder:
-$> mapcache [grf_files_path [map_list_path [map_cache_path]]]
+Map cache format reference:
+-------------------------------------------------------------------------------
+
+The file is written as little-endian, even on big-endian systems, for cross-compatibility reasons. Appropriate conversions
+are done when generating it, so don't worry about it.
+The first 6 bytes are a main header:
+<unsigned long> file size
+<unsigned short> number of maps
+Then maps are stored one right after another:
+<12-characters-long string> map name
+<short> X size
+<short> Y size
+<long> compressed cell data length
+<variable> compressed cell data

+ 3 - 7
src/char/char.c

@@ -1605,10 +1605,6 @@ void create_online_files(void) {
 				if (online_display_option & 24) { // 8 or 16
 				if (online_display_option & 24) { // 8 or 16
 					// prepare map name
 					// prepare map name
 					memcpy(temp, mapindex_id2name(char_dat[j].status.last_point.map), MAP_NAME_LENGTH);
 					memcpy(temp, mapindex_id2name(char_dat[j].status.last_point.map), MAP_NAME_LENGTH);
-					temp[MAP_NAME_LENGTH] = '\0';
-					if (strstr(temp, ".gat") != NULL) {
-						temp[strstr(temp, ".gat") - temp] = 0; // suppress the '.gat'
-					}
 					// write map name
 					// write map name
 					if (online_display_option & 16) { // map-name AND coordinates
 					if (online_display_option & 16) { // map-name AND coordinates
 						fprintf(fp2, "        <td>%s (%d, %d)</td>\n", temp, char_dat[j].status.last_point.x, char_dat[j].status.last_point.y);
 						fprintf(fp2, "        <td>%s (%d, %d)</td>\n", temp, char_dat[j].status.last_point.x, char_dat[j].status.last_point.y);
@@ -3532,13 +3528,13 @@ int parse_char(int fd)
 			{
 			{
 				//Send player to map
 				//Send player to map
 				uint32 subnet_map_ip;
 				uint32 subnet_map_ip;
-				char map_name[MAP_NAME_LENGTH];
-				snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(cd->last_point.map));
+				char map_name[MAP_NAME_LENGTH_EXT];
+				snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(cd->last_point.map));
 
 
 				WFIFOHEAD(fd,28);
 				WFIFOHEAD(fd,28);
 				WFIFOW(fd,0) = 0x71;
 				WFIFOW(fd,0) = 0x71;
 				WFIFOL(fd,2) = cd->char_id;
 				WFIFOL(fd,2) = cd->char_id;
-				memcpy(WFIFOP(fd,6), map_name, MAP_NAME_LENGTH);
+				memcpy(WFIFOP(fd,6), map_name, MAP_NAME_LENGTH_EXT);
 			
 			
 				// Advanced subnet check [LuzZza]
 				// Advanced subnet check [LuzZza]
 				subnet_map_ip = lan_subnetcheck(ipl);
 				subnet_map_ip = lan_subnetcheck(ipl);

+ 9 - 12
src/char_sql/char.c

@@ -3340,13 +3340,12 @@ int parse_char(int fd)
 			{
 			{
 				//Send player to map.
 				//Send player to map.
 				uint32 subnet_map_ip;
 				uint32 subnet_map_ip;
-				char map_name[MAP_NAME_LENGTH];
-				snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(char_dat.last_point.map));
-
+				char map_name[MAP_NAME_LENGTH_EXT];
+				snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(char_dat.last_point.map));	
 				WFIFOHEAD(fd,28);
 				WFIFOHEAD(fd,28);
 				WFIFOW(fd,0) = 0x71;
 				WFIFOW(fd,0) = 0x71;
 				WFIFOL(fd,2) = char_dat.char_id;
 				WFIFOL(fd,2) = char_dat.char_id;
-				memcpy(WFIFOP(fd,6), map_name, MAP_NAME_LENGTH);
+				memcpy(WFIFOP(fd,6), map_name, MAP_NAME_LENGTH_EXT);
 
 
 				// Advanced subnet check [LuzZza]
 				// Advanced subnet check [LuzZza]
 				subnet_map_ip = lan_subnetcheck(ipl);
 				subnet_map_ip = lan_subnetcheck(ipl);
@@ -4024,17 +4023,15 @@ int char_config_read(const char *cfgName) {
 		} else if (strcmpi(w1, "save_log") == 0) {
 		} else if (strcmpi(w1, "save_log") == 0) {
 			save_log = config_switch(w2);
 			save_log = config_switch(w2);
 		} else if (strcmpi(w1, "start_point") == 0) {
 		} else if (strcmpi(w1, "start_point") == 0) {
-			char map[MAP_NAME_LENGTH];
+			char map[MAP_NAME_LENGTH_EXT];
 			int x, y;
 			int x, y;
 			if (sscanf(w2, "%16[^,],%d,%d", map, &x, &y) < 3)
 			if (sscanf(w2, "%16[^,],%d,%d", map, &x, &y) < 3)
 				continue;
 				continue;
-			if (strstr(map, ".gat") != NULL) { // Verify at least if '.gat' is in the map name
-				start_point.map = mapindex_name2id(map);
-				if (!start_point.map)
-					ShowError("Specified start_point %s not found in map-index cache.\n", map);
-				start_point.x = x;
-				start_point.y = y;
-			}
+			start_point.map = mapindex_name2id(map);
+			if (!start_point.map)
+				ShowError("Specified start_point %s not found in map-index cache.\n", map);
+			start_point.x = x;
+			start_point.y = y;
 		} else if (strcmpi(w1, "start_zeny") == 0) {
 		} else if (strcmpi(w1, "start_zeny") == 0) {
 			start_zeny = atoi(w2);
 			start_zeny = atoi(w2);
 			if (start_zeny < 0)
 			if (start_zeny < 0)

+ 32 - 20
src/common/mapindex.c

@@ -15,42 +15,53 @@
 //Leave an extra char of space to hold the terminator, in case for the strncpy(mapindex_id2name()) calls.
 //Leave an extra char of space to hold the terminator, in case for the strncpy(mapindex_id2name()) calls.
 struct indexes {
 struct indexes {
 	char name[MAP_NAME_LENGTH+1]; //Stores map name
 	char name[MAP_NAME_LENGTH+1]; //Stores map name
-	int length; //Stores string length WITHOUT the extension for quick lookup.
+	char exists; //Set to 1 if index exists
 } indexes[MAX_MAPINDEX];
 } indexes[MAX_MAPINDEX];
 
 
 static unsigned short max_index = 0;
 static unsigned short max_index = 0;
 
 
-char mapindex_cfgfile[80] = "db/map_list.txt";
+char mapindex_cfgfile[80] = "db/map_index.txt";
+
+// Removes the extension from a map name
+char *mapindex_normalize_name(char *mapname)
+{
+	char *ptr, *ptr2;
+	ptr = strchr(mapname, '.');
+	if (ptr) { //Check and remove extension.
+		while (ptr[1] && (ptr2 = strchr(ptr+1, '.')))
+			ptr = ptr2; //Skip to the last dot.
+		if(stricmp(ptr,".gat") == 0 ||
+			stricmp(ptr,".afm") == 0 ||
+			stricmp(ptr,".af2") == 0)
+			*ptr = '\0'; //Remove extension.
+	}
+	return mapname;
+}
 
 
 /// Adds a map to the specified index
 /// Adds a map to the specified index
 /// Returns 1 if successful, 0 oherwise
 /// Returns 1 if successful, 0 oherwise
 int mapindex_addmap(int index, const char *name)
 int mapindex_addmap(int index, const char *name)
 {
 {
 	char map_name[1024];
 	char map_name[1024];
-	char *ext;
-	int length;
 
 
 	if (index < 0 || index >= MAX_MAPINDEX) {
 	if (index < 0 || index >= MAX_MAPINDEX) {
 		ShowError("(mapindex_add) Map index (%d) for \"%s\" out of range (max is %d)\n", index, name, MAX_MAPINDEX);
 		ShowError("(mapindex_add) Map index (%d) for \"%s\" out of range (max is %d)\n", index, name, MAX_MAPINDEX);
 		return 0;
 		return 0;
 	}
 	}
+
 	snprintf(map_name, 1024, "%s", name);
 	snprintf(map_name, 1024, "%s", name);
-	map_name[1023] = 0;
-	length = strlen(map_name);
-	if (length > MAP_NAME_LENGTH) {
+	mapindex_normalize_name(map_name);
+
+	if (strlen(map_name) > MAP_NAME_LENGTH-1) {
 		ShowError("(mapindex_add) Map name %s is too long. Maps are limited to %d characters.\n", map_name, MAP_NAME_LENGTH);
 		ShowError("(mapindex_add) Map name %s is too long. Maps are limited to %d characters.\n", map_name, MAP_NAME_LENGTH);
 		return 0;
 		return 0;
 	}
 	}
-	if ((ext = strstr(map_name, ".")) != NULL) { // Remove extension
-		length = ext-map_name;
-		*ext = '\0';
-	}
 
 
-	if (indexes[index].length)
+	if (indexes[index].exists)
 		ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name);
 		ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name);
 
 
 	strncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
 	strncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
-	indexes[index].length = length;
+	indexes[index].exists = 1;
 	if (max_index <= index)
 	if (max_index <= index)
 		max_index = index+1;
 		max_index = index+1;
 	return 1;
 	return 1;
@@ -59,17 +70,18 @@ int mapindex_addmap(int index, const char *name)
 unsigned short mapindex_name2id(const char* name) {
 unsigned short mapindex_name2id(const char* name) {
 	//TODO: Perhaps use a db to speed this up? [Skotlex]
 	//TODO: Perhaps use a db to speed this up? [Skotlex]
 	int i;
 	int i;
-	int length = strlen(name);
-	char *ext = strstr(name, ".");
-	if (ext)
-		length = ext-name; //Base map-name length without the extension.
+	char map_name[1024];
+
+	snprintf(map_name, 1024, "%s", name);
+	mapindex_normalize_name(map_name);
+
 	for (i = 1; i < max_index; i++)
 	for (i = 1; i < max_index; i++)
 	{
 	{
-		if (strncmp(indexes[i].name,name,length)==0)
+		if (strcmp(indexes[i].name,map_name)==0)
 			return i;
 			return i;
 	}
 	}
 #ifdef MAPINDEX_AUTOADD
 #ifdef MAPINDEX_AUTOADD
-	if( mapindex_addmap(i,name) )
+	if( mapindex_addmap(i,map_name) )
 	{
 	{
 		ShowDebug("mapindex_name2id: Auto-added map \"%s\" to position %d\n", indexes[i], i);
 		ShowDebug("mapindex_name2id: Auto-added map \"%s\" to position %d\n", indexes[i], i);
 		return i;
 		return i;
@@ -83,7 +95,7 @@ unsigned short mapindex_name2id(const char* name) {
 }
 }
 
 
 const char* mapindex_id2name(unsigned short id) {
 const char* mapindex_id2name(unsigned short id) {
-	if (id > MAX_MAPINDEX || !indexes[id].length) {
+	if (id > MAX_MAPINDEX || !indexes[id].exists) {
 		ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", id);
 		ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", id);
 		return indexes[0].name; //Theorically this should never happen, hence we return this string to prevent null pointer crashes.
 		return indexes[0].name; //Theorically this should never happen, hence we return this string to prevent null pointer crashes.
 	}
 	}

+ 1 - 0
src/common/mapindex.h

@@ -37,6 +37,7 @@ extern char mapindex_cfgfile[80];
 #define MAP_VEINS "veins"
 #define MAP_VEINS "veins"
 #define MAP_JAIL "sec_pri"
 #define MAP_JAIL "sec_pri"
 #define MAP_NOVICE "new_zone01"
 #define MAP_NOVICE "new_zone01"
+char *mapindex_normalize_name(char *mapname);
 int mapindex_addmap(int index, const char *name);
 int mapindex_addmap(int index, const char *name);
 unsigned short mapindex_name2id(const char*);
 unsigned short mapindex_name2id(const char*);
 const char* mapindex_id2name(unsigned short);
 const char* mapindex_id2name(unsigned short);

+ 3 - 2
src/common/mmo.h

@@ -77,8 +77,9 @@
 #define NAME_LENGTH 24
 #define NAME_LENGTH 24
 //For item names, which tend to have much longer names.
 //For item names, which tend to have much longer names.
 #define ITEM_NAME_LENGTH 50
 #define ITEM_NAME_LENGTH 50
-//For Map Names, which the client considers to be 16 in length
-#define MAP_NAME_LENGTH 16
+//For Map Names, which the client considers to be 16 in length including the .gat extension
+#define MAP_NAME_LENGTH 12
+#define MAP_NAME_LENGTH_EXT 16
 
 
 #define MAX_FRIENDS 40
 #define MAX_FRIENDS 40
 #define MAX_MEMOPOINTS 10
 #define MAX_MEMOPOINTS 10

+ 10 - 10
src/map/atcommand.c

@@ -1310,7 +1310,7 @@ int atcommand_send(const int fd, struct map_session_data* sd, const char* comman
  */
  */
 int atcommand_rura( const int fd, struct map_session_data* sd, const char* command, const char* message)
 int atcommand_rura( const int fd, struct map_session_data* sd, const char* command, const char* message)
 {
 {
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 	unsigned short mapindex;
 	unsigned short mapindex;
 	int x = 0, y = 0;
 	int x = 0, y = 0;
 	int m = -1;
 	int m = -1;
@@ -1698,7 +1698,7 @@ int atcommand_whomap3(const int fd, struct map_session_data* sd, const char* com
 	int i, count, users;
 	int i, count, users;
 	int pl_GM_level, GM_level;
 	int pl_GM_level, GM_level;
 	int map_id;
 	int map_id;
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 
 
 	memset(atcmd_output, '\0', sizeof(atcmd_output));
 	memset(atcmd_output, '\0', sizeof(atcmd_output));
 	memset(map_name, '\0', sizeof(map_name));
 	memset(map_name, '\0', sizeof(map_name));
@@ -1752,7 +1752,7 @@ int atcommand_whomap2(const int fd, struct map_session_data* sd, const char* com
 	int i, count, users;
 	int i, count, users;
 	int pl_GM_level, GM_level;
 	int pl_GM_level, GM_level;
 	int map_id = 0;
 	int map_id = 0;
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 
 
 	nullpo_retr(-1, sd);
 	nullpo_retr(-1, sd);
 
 
@@ -1810,7 +1810,7 @@ int atcommand_whomap(const int fd, struct map_session_data* sd, const char* comm
 	int i, count, users;
 	int i, count, users;
 	int pl_GM_level, GM_level;
 	int pl_GM_level, GM_level;
 	int map_id = 0;
 	int map_id = 0;
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 	struct guild *g;
 	struct guild *g;
 	struct party_data *p;
 	struct party_data *p;
 
 
@@ -3190,10 +3190,10 @@ int atcommand_go(const int fd, struct map_session_data* sd, const char* command,
 {
 {
 	int i;
 	int i;
 	int town;
 	int town;
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 	int m;
 	int m;
  
  
-	const struct { char map[MAP_NAME_LENGTH]; int x,   y; } data[] = {
+	const struct { char map[MAP_NAME_LENGTH_EXT]; int x,   y; } data[] = {
 		{ MAP_PRONTERA,	156, 191  },		//	 0=Prontera
 		{ MAP_PRONTERA,	156, 191  },		//	 0=Prontera
 		{ MAP_MORROC,		156, 93  },			//	 1=Morroc
 		{ MAP_MORROC,		156, 93  },			//	 1=Morroc
 		{ MAP_GEFFEN,		119, 59  },			//	 2=Geffen
 		{ MAP_GEFFEN,		119, 59  },			//	 2=Geffen
@@ -3250,7 +3250,7 @@ int atcommand_go(const int fd, struct map_session_data* sd, const char* command,
 		return -1;
 		return -1;
 	} else {
 	} else {
 		// get possible name of the city
 		// get possible name of the city
-		map_name[MAP_NAME_LENGTH-1] = '\0';
+		map_name[MAP_NAME_LENGTH_EXT-1] = '\0';
 		for (i = 0; map_name[i]; i++)
 		for (i = 0; map_name[i]; i++)
 			map_name[i] = TOLOWER(map_name[i]);
 			map_name[i] = TOLOWER(map_name[i]);
 		// try to see if it's a name, and not a number (try a lot of possibilities, write errors and abbreviations too)
 		// try to see if it's a name, and not a number (try a lot of possibilities, write errors and abbreviations too)
@@ -3636,7 +3636,7 @@ static int atkillmonster_sub(struct block_list *bl, va_list ap)
 void atcommand_killmonster_sub(const int fd, struct map_session_data* sd, const char* message, const int drop)
 void atcommand_killmonster_sub(const int fd, struct map_session_data* sd, const char* message, const int drop)
 {
 {
 	int map_id;
 	int map_id;
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 
 
 	if (!sd) return;
 	if (!sd) return;
 
 
@@ -5432,8 +5432,8 @@ int atcommand_mapinfo(const int fd, struct map_session_data* sd, const char* com
 	}
 	}
 
 
 	if (atcmd_player_name[0] == '\0') {
 	if (atcmd_player_name[0] == '\0') {
-		memcpy(atcmd_player_name, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH);
-		atcmd_player_name[MAP_NAME_LENGTH] = '\0';
+		memcpy(atcmd_player_name, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH_EXT);
+		atcmd_player_name[MAP_NAME_LENGTH_EXT] = '\0';
 		m_id =  map_mapindex2mapid(sd->mapindex);
 		m_id =  map_mapindex2mapid(sd->mapindex);
 	} else {
 	} else {
 		m_id = map_mapname2mapid(atcmd_player_name);
 		m_id = map_mapname2mapid(atcmd_player_name);

+ 2 - 2
src/map/charcommand.c

@@ -617,7 +617,7 @@ int charcommand_save(
 	const int fd, struct map_session_data* sd,
 	const int fd, struct map_session_data* sd,
 	const char* command, const char* message)
 	const char* command, const char* message)
 {
 {
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 	char character[NAME_LENGTH];
 	char character[NAME_LENGTH];
 	struct map_session_data* pl_sd;
 	struct map_session_data* pl_sd;
 	int x = 0, y = 0;
 	int x = 0, y = 0;
@@ -1130,7 +1130,7 @@ int charcommand_warp(
 	const int fd, struct map_session_data* sd,
 	const int fd, struct map_session_data* sd,
 	const char* command, const char* message)
 	const char* command, const char* message)
 {
 {
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 	char character[NAME_LENGTH];
 	char character[NAME_LENGTH];
 	int x = 0, y = 0;
 	int x = 0, y = 0;
 	struct map_session_data *pl_sd;
 	struct map_session_data *pl_sd;

+ 1 - 1
src/map/chrif.c

@@ -328,7 +328,7 @@ int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y,
 int chrif_changemapserverack(int fd)
 int chrif_changemapserverack(int fd)
 {
 {
 	struct map_session_data *sd;
 	struct map_session_data *sd;
-	char mapname[MAP_NAME_LENGTH+1];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	RFIFOHEAD(fd);
 	RFIFOHEAD(fd);
 	sd = map_id2sd(RFIFOL(fd,2));
 	sd = map_id2sd(RFIFOL(fd,2));
 
 

+ 34 - 27
src/map/clif.c

@@ -1208,12 +1208,16 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd)
  *------------------------------------------
  *------------------------------------------
  */
  */
 static int clif_set0192(int fd, int m, int x, int y, int type) {
 static int clif_set0192(int fd, int m, int x, int y, int type) {
+	char map_name[MAP_NAME_LENGTH_EXT];
+
+	sprintf(map_name, "%s.gat", map[m].name);
+
 	WFIFOHEAD(fd, packet_len(0x192));
 	WFIFOHEAD(fd, packet_len(0x192));
 	WFIFOW(fd,0) = 0x192;
 	WFIFOW(fd,0) = 0x192;
 	WFIFOW(fd,2) = x;
 	WFIFOW(fd,2) = x;
 	WFIFOW(fd,4) = y;
 	WFIFOW(fd,4) = y;
 	WFIFOW(fd,6) = type;
 	WFIFOW(fd,6) = type;
-	memcpy(WFIFOP(fd,8),map[m].name,MAP_NAME_LENGTH);
+	memcpy(WFIFOP(fd,8),map_name,MAP_NAME_LENGTH_EXT);
 	WFIFOSET(fd,packet_len(0x192));
 	WFIFOSET(fd,packet_len(0x192));
 
 
 	return 0;
 	return 0;
@@ -1600,17 +1604,17 @@ void clif_setwaitclose(int fd) {
  */
  */
 int clif_changemap(struct map_session_data *sd, short map, int x, int y) {
 int clif_changemap(struct map_session_data *sd, short map, int x, int y) {
 	int fd;
 	int fd;
-	char map_name[MAP_NAME_LENGTH];
-	
+	char map_name[MAP_NAME_LENGTH_EXT];
+
 	nullpo_retr(0, sd);
 	nullpo_retr(0, sd);
 
 
 	fd = sd->fd;
 	fd = sd->fd;
 
 
-	snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(map));
+	sprintf(map_name, "%s.gat", mapindex_id2name(map));
 
 
 	WFIFOHEAD(fd, packet_len(0x91));
 	WFIFOHEAD(fd, packet_len(0x91));
 	WFIFOW(fd,0) = 0x91;
 	WFIFOW(fd,0) = 0x91;
-	memcpy(WFIFOP(fd,2), map_name, MAP_NAME_LENGTH);
+	memcpy(WFIFOP(fd,2), map_name, MAP_NAME_LENGTH_EXT);
 	WFIFOW(fd,18) = x;
 	WFIFOW(fd,18) = x;
 	WFIFOW(fd,20) = y;
 	WFIFOW(fd,20) = y;
 	WFIFOSET(fd, packet_len(0x91));
 	WFIFOSET(fd, packet_len(0x91));
@@ -1631,7 +1635,7 @@ int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x
 	WFIFOHEAD(fd, packet_len(0x92));
 	WFIFOHEAD(fd, packet_len(0x92));
 	WFIFOW(fd,0) = 0x92;
 	WFIFOW(fd,0) = 0x92;
 	//Better not trust the null-terminator is there. [Skotlex]
 	//Better not trust the null-terminator is there. [Skotlex]
-	memcpy(WFIFOP(fd,2), mapname, MAP_NAME_LENGTH);
+	memcpy(WFIFOP(fd,2), mapname, MAP_NAME_LENGTH_EXT);
 	WFIFOB(fd,17) = 0;	//Null terminator for mapname
 	WFIFOB(fd,17) = 0;	//Null terminator for mapname
 	WFIFOW(fd,18) = x;
 	WFIFOW(fd,18) = x;
 	WFIFOW(fd,20) = y;
 	WFIFOW(fd,20) = y;
@@ -4661,10 +4665,10 @@ int clif_skill_warppoint(struct map_session_data *sd,int skill_num,int skill_lv,
 	WFIFOHEAD(fd,packet_len(0x11c));
 	WFIFOHEAD(fd,packet_len(0x11c));
 	WFIFOW(fd,0)=0x11c;
 	WFIFOW(fd,0)=0x11c;
 	WFIFOW(fd,2)=skill_num;
 	WFIFOW(fd,2)=skill_num;
-	strncpy((char*)WFIFOP(fd, 4),map1,MAP_NAME_LENGTH);
-	strncpy((char*)WFIFOP(fd,20),map2,MAP_NAME_LENGTH);
-	strncpy((char*)WFIFOP(fd,36),map3,MAP_NAME_LENGTH);
-	strncpy((char*)WFIFOP(fd,52),map4,MAP_NAME_LENGTH);
+	strncpy((char*)WFIFOP(fd, 4),map1,MAP_NAME_LENGTH_EXT);
+	strncpy((char*)WFIFOP(fd,20),map2,MAP_NAME_LENGTH_EXT);
+	strncpy((char*)WFIFOP(fd,36),map3,MAP_NAME_LENGTH_EXT);
+	strncpy((char*)WFIFOP(fd,52),map4,MAP_NAME_LENGTH_EXT);
 	WFIFOSET(fd,packet_len(0x11c));
 	WFIFOSET(fd,packet_len(0x11c));
 	sd->menuskill_id = skill_num;
 	sd->menuskill_id = skill_num;
 	if (skill_num == AL_WARP)
 	if (skill_num == AL_WARP)
@@ -5660,7 +5664,7 @@ int clif_party_created(struct map_session_data *sd,int flag)
 int clif_party_member_info(struct party_data *p, struct map_session_data *sd)
 int clif_party_member_info(struct party_data *p, struct map_session_data *sd)
 {
 {
 	unsigned char buf[96];
 	unsigned char buf[96];
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 
 
 	if (!sd) { //Pick any party member (this call is used when changing item share rules)
 	if (!sd) { //Pick any party member (this call is used when changing item share rules)
 		int i;
 		int i;
@@ -5669,7 +5673,7 @@ int clif_party_member_info(struct party_data *p, struct map_session_data *sd)
 		sd = p->data[i].sd;
 		sd = p->data[i].sd;
 	}
 	}
 
 
-	snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->mapindex));
+	snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->mapindex));
 
 
 	WBUFW(buf,0)=0x1e9;
 	WBUFW(buf,0)=0x1e9;
 	WBUFL(buf,2)= sd->status.account_id;
 	WBUFL(buf,2)= sd->status.account_id;
@@ -5679,7 +5683,7 @@ int clif_party_member_info(struct party_data *p, struct map_session_data *sd)
 	WBUFB(buf,14)=0; //Unconfirmed byte, could be online/offline.
 	WBUFB(buf,14)=0; //Unconfirmed byte, could be online/offline.
 	memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH);
 	memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH);
 	memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH);
 	memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH);
-	memcpy(WBUFP(buf,63), map_name, MAP_NAME_LENGTH);
+	memcpy(WBUFP(buf,63), map_name, MAP_NAME_LENGTH_EXT);
 	WBUFB(buf,79) = (p->party.item&1)?1:0;
 	WBUFB(buf,79) = (p->party.item&1)?1:0;
 	WBUFB(buf,80) = (p->party.item&2)?1:0;
 	WBUFB(buf,80) = (p->party.item&2)?1:0;
 	clif_send(buf,packet_len(0x1e9),&sd->bl,PARTY);
 	clif_send(buf,packet_len(0x1e9),&sd->bl,PARTY);
@@ -5693,7 +5697,7 @@ int clif_party_member_info(struct party_data *p, struct map_session_data *sd)
  *------------------------------------------*/
  *------------------------------------------*/
 int clif_party_info(struct party_data* p, struct map_session_data *sd)
 int clif_party_info(struct party_data* p, struct map_session_data *sd)
 {
 {
-	unsigned char buf[2+2+NAME_LENGTH+(4+NAME_LENGTH+MAP_NAME_LENGTH+1+1)*MAX_PARTY];
+	unsigned char buf[2+2+NAME_LENGTH+(4+NAME_LENGTH+MAP_NAME_LENGTH_EXT+1+1)*MAX_PARTY];
 	struct map_session_data* party_sd = NULL;
 	struct map_session_data* party_sd = NULL;
 	int i, c;
 	int i, c;
 
 
@@ -5704,17 +5708,17 @@ int clif_party_info(struct party_data* p, struct map_session_data *sd)
 	for(i = 0, c = 0; i < MAX_PARTY; i++)
 	for(i = 0, c = 0; i < MAX_PARTY; i++)
 	{
 	{
 		struct party_member* m = &p->party.member[i];
 		struct party_member* m = &p->party.member[i];
-		char map_name[MAP_NAME_LENGTH];
+		char map_name[MAP_NAME_LENGTH_EXT];
 
 
 		if(!m->account_id) continue;
 		if(!m->account_id) continue;
 
 
 		if(party_sd == NULL) party_sd = p->data[i].sd;
 		if(party_sd == NULL) party_sd = p->data[i].sd;
 
 
-		snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(m->map));
+		snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(m->map));
 
 
 		WBUFL(buf,28+c*46) = m->account_id;
 		WBUFL(buf,28+c*46) = m->account_id;
 		memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH);
 		memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH);
-		memcpy(WBUFP(buf,28+c*46+28), map_name, MAP_NAME_LENGTH);
+		memcpy(WBUFP(buf,28+c*46+28), map_name, MAP_NAME_LENGTH_EXT);
 		WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1;
 		WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1;
 		WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1;
 		WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1;
 		c++;
 		c++;
@@ -5993,12 +5997,12 @@ int clif_hpmeter(struct map_session_data *sd)
 int clif_party_move(struct party *p,struct map_session_data *sd,int online)
 int clif_party_move(struct party *p,struct map_session_data *sd,int online)
 {
 {
 	unsigned char buf[128];
 	unsigned char buf[128];
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 
 
 	nullpo_retr(0, sd);
 	nullpo_retr(0, sd);
 	nullpo_retr(0, p);
 	nullpo_retr(0, p);
 
 
-	snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", map[sd->bl.m].name);
+	snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", map[sd->bl.m].name);
 
 
 	WBUFW(buf, 0)=0x104;
 	WBUFW(buf, 0)=0x104;
 	WBUFL(buf, 2)=sd->status.account_id;
 	WBUFL(buf, 2)=sd->status.account_id;
@@ -6008,7 +6012,7 @@ int clif_party_move(struct party *p,struct map_session_data *sd,int online)
 	WBUFB(buf,14)=!online;
 	WBUFB(buf,14)=!online;
 	memcpy(WBUFP(buf,15),p->name, NAME_LENGTH);
 	memcpy(WBUFP(buf,15),p->name, NAME_LENGTH);
 	memcpy(WBUFP(buf,39),sd->status.name, NAME_LENGTH);
 	memcpy(WBUFP(buf,39),sd->status.name, NAME_LENGTH);
-	memcpy(WBUFP(buf,63),map_name, MAP_NAME_LENGTH);
+	memcpy(WBUFP(buf,63),map_name, MAP_NAME_LENGTH_EXT);
 	clif_send(buf,packet_len(0x104),&sd->bl,PARTY);
 	clif_send(buf,packet_len(0x104),&sd->bl,PARTY);
 	return 0;
 	return 0;
 }
 }
@@ -6415,6 +6419,9 @@ int clif_changemapcell(int m,int x,int y,int cell_type,int type)
 {
 {
 	struct block_list bl;
 	struct block_list bl;
 	unsigned char buf[32];
 	unsigned char buf[32];
+	char map_name[MAP_NAME_LENGTH_EXT];
+
+	snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", map[m].name);
 
 
 	bl.type = BL_NUL;
 	bl.type = BL_NUL;
 	bl.m = m;
 	bl.m = m;
@@ -6424,7 +6431,7 @@ int clif_changemapcell(int m,int x,int y,int cell_type,int type)
 	WBUFW(buf,2) = x;
 	WBUFW(buf,2) = x;
 	WBUFW(buf,4) = y;
 	WBUFW(buf,4) = y;
 	WBUFW(buf,6) = cell_type;
 	WBUFW(buf,6) = cell_type;
-	memcpy(WBUFP(buf,8),map[m].name,MAP_NAME_LENGTH);
+	memcpy(WBUFP(buf,8),map_name,MAP_NAME_LENGTH_EXT);
 	if(!type)
 	if(!type)
 		clif_send(buf,packet_len(0x192),&bl,AREA);
 		clif_send(buf,packet_len(0x192),&bl,AREA);
 	else
 	else
@@ -7850,13 +7857,13 @@ void clif_gospel_info(struct map_session_data *sd, int type)
 void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type)
 void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type)
 {
 {
 	int fd=sd->fd;
 	int fd=sd->fd;
-	char map_name[MAP_NAME_LENGTH];
+	char map_name[MAP_NAME_LENGTH_EXT];
 
 
-	snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->feel_map[feel_level].index));
+	snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->feel_map[feel_level].index));
 
 
 	WFIFOHEAD(fd,packet_len(0x20e));
 	WFIFOHEAD(fd,packet_len(0x20e));
 	WFIFOW(fd,0)=0x20e;
 	WFIFOW(fd,0)=0x20e;
-	memcpy(WFIFOP(fd,2),map_name, MAP_NAME_LENGTH);
+	memcpy(WFIFOP(fd,2),map_name, MAP_NAME_LENGTH_EXT);
 	WFIFOL(fd,26)=sd->bl.id;
 	WFIFOL(fd,26)=sd->bl.id;
 	WFIFOB(fd,30)=feel_level;
 	WFIFOB(fd,30)=feel_level;
 	WFIFOB(fd,31)=type?1:0;
 	WFIFOB(fd,31)=type?1:0;
@@ -8636,8 +8643,8 @@ int clif_message(struct block_list *bl, const char* msg)
  */
  */
 void clif_parse_MapMove(int fd, struct map_session_data *sd) {
 void clif_parse_MapMove(int fd, struct map_session_data *sd) {
 // /m /mapmove (as @rura GM command)
 // /m /mapmove (as @rura GM command)
-	char output[MAP_NAME_LENGTH+15]; // Max length of a short: ' -6XXXX' -> 7 digits
-	char message[MAP_NAME_LENGTH+15+5]; // "/mm "+output
+	char output[MAP_NAME_LENGTH_EXT+15]; // Max length of a short: ' -6XXXX' -> 7 digits
+	char message[MAP_NAME_LENGTH_EXT+15+5]; // "/mm "+output
 	char *map_name;
 	char *map_name;
 	RFIFOHEAD(fd);
 	RFIFOHEAD(fd);
 
 
@@ -8647,7 +8654,7 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) {
 		return;
 		return;
 
 
 	map_name = RFIFOP(fd,2);
 	map_name = RFIFOP(fd,2);
-	map_name[MAP_NAME_LENGTH-1]='\0';
+	map_name[MAP_NAME_LENGTH_EXT-1]='\0';
 	sprintf(output, "%s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20));
 	sprintf(output, "%s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20));
 	atcommand_rura(fd, sd, "@rura", output);
 	atcommand_rura(fd, sd, "@rura", output);
 	if(log_config.gm && get_atcommand_level(AtCommand_MapMove) >= log_config.gm)
 	if(log_config.gm && get_atcommand_level(AtCommand_MapMove) >= log_config.gm)

+ 3 - 2
src/map/guild.c

@@ -9,6 +9,7 @@
 #include "../common/timer.h"
 #include "../common/timer.h"
 #include "../common/nullpo.h"
 #include "../common/nullpo.h"
 #include "../common/malloc.h"
 #include "../common/malloc.h"
+#include "../common/mapindex.h"
 #include "../common/showmsg.h"
 #include "../common/showmsg.h"
 #include "../common/ers.h"
 #include "../common/ers.h"
 
 
@@ -183,7 +184,7 @@ static int guild_read_castledb(void)
 
 
 		gc=(struct guild_castle *)aCalloc(1,sizeof(struct guild_castle));
 		gc=(struct guild_castle *)aCalloc(1,sizeof(struct guild_castle));
 		gc->castle_id=atoi(str[0]);
 		gc->castle_id=atoi(str[0]);
-		memcpy(gc->map_name,map_normalize_name(str[1]),MAP_NAME_LENGTH-1);
+		memcpy(gc->map_name,mapindex_normalize_name(str[1]),MAP_NAME_LENGTH-1);
 		memcpy(gc->castle_name,str[2],NAME_LENGTH-1);
 		memcpy(gc->castle_name,str[2],NAME_LENGTH-1);
 		memcpy(gc->castle_event,str[3],NAME_LENGTH-1);
 		memcpy(gc->castle_event,str[3],NAME_LENGTH-1);
 
 
@@ -254,7 +255,7 @@ struct guild_castle *guild_mapname2gc(char *mapname)
 	int i;
 	int i;
 	struct guild_castle *gc=NULL;
 	struct guild_castle *gc=NULL;
 
 
-	map_normalize_name(mapname);
+	mapindex_normalize_name(mapname);
 
 
 	for(i=0;i<MAX_GUILDCASTLE;i++){
 	for(i=0;i<MAX_GUILDCASTLE;i++){
 		gc=guild_castle_search(i);
 		gc=guild_castle_search(i);

+ 30 - 40
src/map/map.c

@@ -145,6 +145,20 @@ struct charid2nick {
 	int req_id;
 	int req_id;
 };
 };
 
 
+// This is the main header found at the very beginning of the map cache
+struct map_cache_main_header {
+	unsigned long file_size;
+	unsigned short map_count;
+};
+
+// This is the header appended before every compressed map cells info in the map cache
+struct map_cache_map_info {
+	char name[MAP_NAME_LENGTH];
+	short xs;
+	short ys;
+	long len;
+};
+
 char map_cache_file[256]="db/map_cache.dat";
 char map_cache_file[256]="db/map_cache.dat";
 char db_path[256] = "db";
 char db_path[256] = "db";
 char motd_txt[256] = "conf/motd.txt";
 char motd_txt[256] = "conf/motd.txt";
@@ -2410,61 +2424,34 @@ int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port)
 * Map cache reading
 * Map cache reading
 *===========================================*/
 *===========================================*/
 
 
-// This is the header appended before every compressed map cells info
-struct map_cache_info {
-	char name[MAP_NAME_LENGTH];
-	unsigned short index;
-	short xs;
-	short ys;
-	long len;
-};
-
-FILE *map_cache_fp;
-
-// Removes the extension from a map name
-char *map_normalize_name(char *mapname)
-{
-	char *ptr, *ptr2;
-	ptr = strchr(mapname, '.');
-	if (ptr) { //Check and remove extension.
-		while (ptr[1] && (ptr2 = strchr(ptr+1, '.')))
-			ptr = ptr2; //Skip to the last dot.
-		if(stricmp(ptr,".gat") == 0 ||
-			stricmp(ptr,".afm") == 0 ||
-			stricmp(ptr,".af2") == 0)
-			*ptr = '\0'; //Remove extension.
-	}
-	return mapname;
-}
-
-int map_readmap(struct map_data *m)
+int map_readfromcache(struct map_data *m, FILE *fp)
 {
 {
 	int i;
 	int i;
-	unsigned short map_count;
-	struct map_cache_info info;
+	struct map_cache_main_header header;
+	struct map_cache_map_info info;
 	unsigned long size;
 	unsigned long size;
 	unsigned char *buf;
 	unsigned char *buf;
 
 
-	if(!map_cache_fp)
+	if(!fp)
 		return 0;
 		return 0;
 
 
-	fseek(map_cache_fp, 0, SEEK_SET);
-	fread(&map_count, sizeof(map_count), 1, map_cache_fp);
+	fseek(fp, 0, SEEK_SET);
+	fread(&header, sizeof(struct map_cache_main_header), 1, fp);
 
 
-	for(i = 0; i < map_count; i++) {
-		fread(&info, sizeof(info), 1, map_cache_fp);
+	for(i = 0; i < header.map_count; i++) {
+		fread(&info, sizeof(struct map_cache_map_info), 1, fp);
 		if(strcmp(m->name, info.name) == 0) { // Map found
 		if(strcmp(m->name, info.name) == 0) { // Map found
 			m->xs = info.xs;
 			m->xs = info.xs;
 			m->ys = info.ys;
 			m->ys = info.ys;
 			m->gat = (unsigned char *)aMalloc(m->xs*m->ys); // Allocate room for map cells data
 			m->gat = (unsigned char *)aMalloc(m->xs*m->ys); // Allocate room for map cells data
 			buf = aMalloc(info.len); // Allocate a temp buffer to read the zipped map
 			buf = aMalloc(info.len); // Allocate a temp buffer to read the zipped map
-			fread(buf, info.len, 1, map_cache_fp);
+			fread(buf, info.len, 1, fp);
 			size = m->xs*m->ys;
 			size = m->xs*m->ys;
 			decode_zip(m->gat, &size, buf, info.len); // Unzip the map from the buffer
 			decode_zip(m->gat, &size, buf, info.len); // Unzip the map from the buffer
 			aFree(buf);
 			aFree(buf);
 			return 1;
 			return 1;
 		} else // Map not found, jump to the beginning of the next map info header
 		} else // Map not found, jump to the beginning of the next map info header
-			fseek(map_cache_fp, info.len, SEEK_CUR);
+			fseek(fp, info.len, SEEK_CUR);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -2482,7 +2469,7 @@ int map_addmap(char *mapname) {
 		return 1;
 		return 1;
 	}
 	}
 
 
-	memcpy(map[map_num].name, map_normalize_name(mapname), MAP_NAME_LENGTH-1);
+	memcpy(map[map_num].name, mapindex_normalize_name(mapname), MAP_NAME_LENGTH-1);
 	map_num++;
 	map_num++;
 	return 0;
 	return 0;
 }
 }
@@ -2520,8 +2507,9 @@ int map_readallmaps (void)
 {
 {
 	int i;
 	int i;
 	int maps_removed = 0;
 	int maps_removed = 0;
+	FILE *fp;
 
 
-	if(!(map_cache_fp = fopen(map_cache_file, "rb")))
+	if(!(fp = fopen(map_cache_file, "rb")))
 	{
 	{
 		ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", map_cache_file);
 		ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", map_cache_file);
 		exit(1); //No use launching server if maps can't be read.
 		exit(1); //No use launching server if maps can't be read.
@@ -2559,7 +2547,7 @@ int map_readallmaps (void)
 			fflush(stdout);
 			fflush(stdout);
 		}
 		}
 
 
-		if(!map_readmap(&map[i])) {
+		if(!map_readfromcache(&map[i], fp)) {
 			map_delmapid(i);
 			map_delmapid(i);
 			maps_removed++;
 			maps_removed++;
 			i--;
 			i--;
@@ -2609,6 +2597,8 @@ int map_readallmaps (void)
 		map[i].block_mob_count = (int*)aCallocA(size, 1);
 		map[i].block_mob_count = (int*)aCallocA(size, 1);
 	}
 	}
 
 
+	fclose(fp);
+
 	// finished map loading
 	// finished map loading
 	printf("\r");
 	printf("\r");
 	ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps.%30s\n",map_num,"");
 	ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps.%30s\n",map_num,"");

+ 1 - 2
src/map/map.h

@@ -1030,7 +1030,7 @@ enum { ATK_LUCKY=1,ATK_FLEE,ATK_DEF};	// 
 struct map_data {
 struct map_data {
 	char name[MAP_NAME_LENGTH];
 	char name[MAP_NAME_LENGTH];
 	unsigned short index; //Index is the map index used by the mapindex* functions.
 	unsigned short index; //Index is the map index used by the mapindex* functions.
-	unsigned char *gat;	// NULL‚Ȃ牺‚Ìmap_data_other_server‚Æ‚µ‚Ĉµ‚¤
+	unsigned char *gat;	// If this is NULL‚ the map is not on this map-server
 	unsigned char *cell; //Contains temporary cell data that is set/unset on tiles.
 	unsigned char *cell; //Contains temporary cell data that is set/unset on tiles.
 #ifdef CELL_NOSTACK
 #ifdef CELL_NOSTACK
 	unsigned char *cell_bl; //Holds amount of bls in any given cell.
 	unsigned char *cell_bl; //Holds amount of bls in any given cell.
@@ -1350,7 +1350,6 @@ void map_foreachpc(int (*func)(DBKey,void*,va_list),...);
 int map_foreachiddb(int (*)(DBKey,void*,va_list),...);
 int map_foreachiddb(int (*)(DBKey,void*,va_list),...);
 void map_addnickdb(struct map_session_data *);
 void map_addnickdb(struct map_session_data *);
 struct map_session_data * map_nick2sd(const char*);
 struct map_session_data * map_nick2sd(const char*);
-char *map_normalize_name(char *mapname);
 
 
 // ‚»‚Ì‘¼
 // ‚»‚Ì‘¼
 int map_check_dir(int s_dir,int t_dir);
 int map_check_dir(int s_dir,int t_dir);

+ 7 - 7
src/map/npc.c

@@ -1659,7 +1659,7 @@ int npc_parse_warp (char *w1,char *w2,char *w3,char *w4)
 {
 {
 	int x, y, xs, ys, to_x, to_y, m;
 	int x, y, xs, ys, to_x, to_y, m;
 	int i;
 	int i;
-	char mapname[MAP_NAME_LENGTH], to_mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT], to_mapname[MAP_NAME_LENGTH_EXT];
 	struct npc_data *nd;
 	struct npc_data *nd;
 
 
 	// 引数の個数チェック
 	// 引数の個数チェック
@@ -1723,7 +1723,7 @@ static int npc_parse_shop (char *w1, char *w2, char *w3, char *w4)
 	#define MAX_SHOPITEM 100
 	#define MAX_SHOPITEM 100
 	char *p;
 	char *p;
 	int x, y, dir, m, pos = 0;
 	int x, y, dir, m, pos = 0;
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	struct npc_data *nd;
 	struct npc_data *nd;
 
 
 	if (strcmp(w1, "-") == 0) {
 	if (strcmp(w1, "-") == 0) {
@@ -1953,7 +1953,7 @@ static int npc_skip_script (char *w1,char *w2,char *w3,char *w4,char *first_line
 static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line,FILE *fp,int *lines,const char* file)
 static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line,FILE *fp,int *lines,const char* file)
 {
 {
 	int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0;	// [Valaris] thanks to fov
 	int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0;	// [Valaris] thanks to fov
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	unsigned char *srcbuf = NULL;
 	unsigned char *srcbuf = NULL;
 	struct script_code *script;
 	struct script_code *script;
 	int srcsize = 65536;
 	int srcsize = 65536;
@@ -2380,7 +2380,7 @@ int npc_parse_mob2 (struct spawn_data *mob, int index)
 int npc_parse_mob (char *w1, char *w2, char *w3, char *w4)
 int npc_parse_mob (char *w1, char *w2, char *w3, char *w4)
 {
 {
 	int level, num, class_, mode, x,y,xs,ys;
 	int level, num, class_, mode, x,y,xs,ys;
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	char mobname[NAME_LENGTH];
 	char mobname[NAME_LENGTH];
 	struct spawn_data mob, *data;
 	struct spawn_data mob, *data;
 
 
@@ -2515,7 +2515,7 @@ int npc_parse_mob (char *w1, char *w2, char *w3, char *w4)
 static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
 static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
 {
 {
 	int m;
 	int m;
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	int state = 1;
 	int state = 1;
 
 
 	// 引数の個数チェック
 	// 引数の個数チェック
@@ -2530,7 +2530,7 @@ static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
 	
 	
 //マップフラグ
 //マップフラグ
 	if (strcmpi(w3, "nosave") == 0) {
 	if (strcmpi(w3, "nosave") == 0) {
-		char savemap[MAP_NAME_LENGTH];
+		char savemap[MAP_NAME_LENGTH_EXT];
 		int savex, savey;
 		int savex, savey;
 		if (state == 0)
 		if (state == 0)
 			; //Map flag disabled.
 			; //Map flag disabled.
@@ -2764,7 +2764,7 @@ static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
 static int npc_parse_mapcell (char *w1, char *w2, char *w3, char *w4)
 static int npc_parse_mapcell (char *w1, char *w2, char *w3, char *w4)
 {
 {
 	int m, cell, x, y, x0, y0, x1, y1;
 	int m, cell, x, y, x0, y0, x1, y1;
-	char type[24], mapname[MAP_NAME_LENGTH];
+	char type[24], mapname[MAP_NAME_LENGTH_EXT];
 
 
 	if (sscanf(w1, "%15[^,]", mapname) != 1)
 	if (sscanf(w1, "%15[^,]", mapname) != 1)
 		return 1;
 		return 1;

+ 9 - 9
src/map/script.c

@@ -9119,10 +9119,10 @@ BUILDIN_FUNC(flagemblem)
 
 
 BUILDIN_FUNC(getcastlename)
 BUILDIN_FUNC(getcastlename)
 {
 {
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	struct guild_castle *gc;
 	struct guild_castle *gc;
 
 
-	strncpy(mapname, script_getstr(st,2), MAP_NAME_LENGTH);
+	strncpy(mapname, script_getstr(st,2), MAP_NAME_LENGTH_EXT);
 	gc = guild_mapname2gc(mapname);
 	gc = guild_mapname2gc(mapname);
 
 
 	if(gc)
 	if(gc)
@@ -9134,13 +9134,13 @@ BUILDIN_FUNC(getcastlename)
 
 
 BUILDIN_FUNC(getcastledata)
 BUILDIN_FUNC(getcastledata)
 {
 {
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	int index=script_getnum(st,3);
 	int index=script_getnum(st,3);
 	const char *event=NULL;
 	const char *event=NULL;
 	struct guild_castle *gc;
 	struct guild_castle *gc;
 	int i;
 	int i;
 
 
-	strncpy(mapname, script_getstr(st,2), MAP_NAME_LENGTH);
+	strncpy(mapname, script_getstr(st,2), MAP_NAME_LENGTH_EXT);
 	gc = guild_mapname2gc(mapname);
 	gc = guild_mapname2gc(mapname);
 
 
 	if(script_hasdata(st,4) && index==0 && gc) {
 	if(script_hasdata(st,4) && index==0 && gc) {
@@ -9202,12 +9202,12 @@ BUILDIN_FUNC(getcastledata)
 
 
 BUILDIN_FUNC(setcastledata)
 BUILDIN_FUNC(setcastledata)
 {
 {
-	char mapname[MAP_NAME_LENGTH];
+	char mapname[MAP_NAME_LENGTH_EXT];
 	int index=script_getnum(st,3);
 	int index=script_getnum(st,3);
 	int value=script_getnum(st,4);
 	int value=script_getnum(st,4);
 	struct guild_castle *gc;
 	struct guild_castle *gc;
 
 
-	strncpy(mapname, script_getstr(st,2), MAP_NAME_LENGTH);
+	strncpy(mapname, script_getstr(st,2), MAP_NAME_LENGTH_EXT);
 	gc = guild_mapname2gc(mapname);
 	gc = guild_mapname2gc(mapname);
 
 
 	if(gc) {
 	if(gc) {
@@ -11084,9 +11084,9 @@ BUILDIN_FUNC(getsavepoint)
 	y=sd->status.save_point.y;
 	y=sd->status.save_point.y;
 	switch(type){
 	switch(type){
 		case 0:
 		case 0:
-			mapname=(char *) aMallocA((MAP_NAME_LENGTH+1)*sizeof(char));
+			mapname=(char *) aMallocA((MAP_NAME_LENGTH)*sizeof(char));
 			memcpy(mapname, mapindex_id2name(sd->status.save_point.map), MAP_NAME_LENGTH);
 			memcpy(mapname, mapindex_id2name(sd->status.save_point.map), MAP_NAME_LENGTH);
-			mapname[MAP_NAME_LENGTH]='\0';
+			mapname[MAP_NAME_LENGTH-1]='\0';
 			script_pushstr(st,mapname);
 			script_pushstr(st,mapname);
 		break;
 		break;
 		case 1:
 		case 1:
@@ -11133,7 +11133,7 @@ BUILDIN_FUNC(getmapxy)
 	char prefix;
 	char prefix;
 
 
 	int x,y,type;
 	int x,y,type;
-	char mapname[MAP_NAME_LENGTH+1];
+	char mapname[MAP_NAME_LENGTH];
 	memset(mapname, 0, sizeof(mapname));
 	memset(mapname, 0, sizeof(mapname));
 
 
 	if( !data_isreference(script_getdata(st,2)) ){
 	if( !data_isreference(script_getdata(st,2)) ){

+ 7 - 7
src/map/skill.c

@@ -4445,8 +4445,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			} else {
 			} else {
 				if (sd->skillitem != AL_TELEPORT)
 				if (sd->skillitem != AL_TELEPORT)
 				{
 				{
-					char save_map[MAP_NAME_LENGTH];
-					snprintf(save_map, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->status.save_point.map));
+					char save_map[MAP_NAME_LENGTH_EXT];
+					snprintf(save_map, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->status.save_point.map));
 					clif_skill_warppoint(sd,skillid,skilllv,"Random",save_map,"","");
 					clif_skill_warppoint(sd,skillid,skilllv,"Random",save_map,"","");
 				}
 				}
 				else //Autocasted Teleport level 2??
 				else //Autocasted Teleport level 2??
@@ -6086,14 +6086,14 @@ int skill_castend_pos2 (struct block_list *src, int x, int y, int skillid, int s
 
 
 	case AL_WARP:
 	case AL_WARP:
 		if(sd) {
 		if(sd) {
-			char memo[4][MAP_NAME_LENGTH] = {"", "", "", ""};
-			snprintf(memo[0], MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->status.save_point.map));
+			char memo[4][MAP_NAME_LENGTH_EXT] = {"", "", "", ""};
+			snprintf(memo[0], MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->status.save_point.map));
 			if (skilllv>1 && sd->status.memo_point[0].map)
 			if (skilllv>1 && sd->status.memo_point[0].map)
-				snprintf(memo[1], MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->status.memo_point[0].map));
+				snprintf(memo[1], MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->status.memo_point[0].map));
 			if (skilllv>2 && sd->status.memo_point[1].map)
 			if (skilllv>2 && sd->status.memo_point[1].map)
-				snprintf(memo[2], MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->status.memo_point[1].map));
+				snprintf(memo[2], MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->status.memo_point[1].map));
 			if (skilllv>3 && sd->status.memo_point[2].map)
 			if (skilllv>3 && sd->status.memo_point[2].map)
-				snprintf(memo[3], MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(sd->status.memo_point[2].map));
+				snprintf(memo[3], MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(sd->status.memo_point[2].map));
 
 
 			clif_skill_warppoint(sd,skillid,skilllv,
 			clif_skill_warppoint(sd,skillid,skilllv,
 				memo[0],memo[1],memo[2],memo[3]);
 				memo[0],memo[1],memo[2],memo[3]);

+ 0 - 1
src/tool/grfio.c

@@ -578,7 +578,6 @@ void* grfio_reads(char *fname, int *size)
 			if (entry != NULL && entry->gentry < 0) {
 			if (entry != NULL && entry->gentry < 0) {
 				entry->gentry = -entry->gentry;	// local file checked
 				entry->gentry = -entry->gentry;	// local file checked
 			} else {
 			} else {
-				printf("%s not found (grfio_reads - local file %s)\n", fname, lfname);
 				return NULL;
 				return NULL;
 			}
 			}
 		}
 		}

+ 154 - 60
src/tool/mapcache.c

@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
+#include <malloc.h>
 
 
 #ifndef _WIN32
 #ifndef _WIN32
 #include <unistd.h>
 #include <unistd.h>
@@ -11,12 +12,18 @@
 
 
 #include "grfio.h"
 #include "grfio.h"
 
 
-char grf_list_file[256] = "db/grf_files.txt";
-char map_list_file[256] = "db/map_list.txt";
+#define MAP_NAME_LENGTH 12
+#define MAP_NAME_LENGTH_EXT 16
+#define NO_WATER 1000000
+
+char grf_list_file[256] = "tools/mapcache/grf_files.txt";
+char map_list_file[256] = "db/map_index.txt";
 char map_cache_file[256] = "db/map_cache.dat";
 char map_cache_file[256] = "db/map_cache.dat";
+int rebuild = 0;
 
 
-#define MAP_NAME_LENGTH 16
-#define NO_WATER 1000000
+FILE *map_cache_fp;
+
+unsigned long file_size;
 
 
 // Used internally, this structure contains the physical map cells
 // Used internally, this structure contains the physical map cells
 struct map_data {
 struct map_data {
@@ -26,31 +33,25 @@ struct map_data {
 };
 };
 
 
 // This is the main header found at the very beginning of the file
 // This is the main header found at the very beginning of the file
-unsigned short map_count;
+struct main_header {
+	unsigned long file_size;
+	unsigned short map_count;
+} header;
 
 
 // This is the header appended before every compressed map cells info
 // This is the header appended before every compressed map cells info
-struct map_cache_info {
+struct map_info {
 	char name[MAP_NAME_LENGTH];
 	char name[MAP_NAME_LENGTH];
-	unsigned short index;
 	short xs;
 	short xs;
 	short ys;
 	short ys;
 	long len;
 	long len;
 };
 };
 
 
-FILE *map_cache_fp;
-
-int filesize;
 
 
-/// Converts an unsigned short (16 bits) from current machine order to little-endian
-unsigned short MakeUShortLE(unsigned short val)
-{
-	unsigned char buf[2];
-	buf[0] = (unsigned char)( (val & 0x00FF)         );
-	buf[1] = (unsigned char)( (val & 0xFF00) >> 0x08 );
-	return *((unsigned short*)buf);
-}
+/*************************************
+* Big-endian compatibility functions *
+*************************************/
 
 
-/// Converts a short (16 bits) from current machine order to little-endian
+// Converts a short (16 bits) from current machine order to little-endian
 short MakeShortLE(short val)
 short MakeShortLE(short val)
 {
 {
 	unsigned char buf[2];
 	unsigned char buf[2];
@@ -59,7 +60,7 @@ short MakeShortLE(short val)
 	return *((short*)buf);
 	return *((short*)buf);
 }
 }
 
 
-/// Converts a long (32 bits) from current machine order to little-endian
+// Converts a long (32 bits) from current machine order to little-endian
 long MakeLongLE(long val)
 long MakeLongLE(long val)
 {
 {
 	unsigned char buf[4];
 	unsigned char buf[4];
@@ -70,7 +71,23 @@ long MakeLongLE(long val)
 	return *((long*)buf);
 	return *((long*)buf);
 }
 }
 
 
-/// Reads an unsigned long (32 bits) in little-endian from the buffer
+// Reads an unsigned short (16 bits) in little-endian from the buffer
+unsigned short GetUShort(const unsigned char *buf)
+{
+	return	 ( ((unsigned short)(buf[0]))         )
+			|( ((unsigned short)(buf[1])) << 0x08 );
+}
+
+// Reads a long (32 bits) in little-endian from the buffer
+long GetLong(const unsigned char *buf)
+{
+	return	 ( ((long)(buf[0]))         )
+			|( ((long)(buf[1])) << 0x08 )
+			|( ((long)(buf[2])) << 0x10 )
+			|( ((long)(buf[3])) << 0x18 );
+}
+
+// Reads an unsigned long (32 bits) in little-endian from the buffer
 unsigned long GetULong(const unsigned char *buf)
 unsigned long GetULong(const unsigned char *buf)
 {
 {
 	return	 ( ((unsigned long)(buf[0]))         )
 	return	 ( ((unsigned long)(buf[0]))         )
@@ -87,7 +104,7 @@ float GetFloat(const unsigned char *buf)
 }
 }
 
 
 
 
-// Read map from GRF's GAT and RSW files
+// Reads a map from GRF's GAT and RSW files
 int read_map(char *name, struct map_data *m)
 int read_map(char *name, struct map_data *m)
 {
 {
 	char filename[256];
 	char filename[256];
@@ -143,31 +160,31 @@ int read_map(char *name, struct map_data *m)
 	return 1;
 	return 1;
 }
 }
 
 
-void cache_map(char *name, unsigned short index, struct map_data *m)
+// Adds a map to the cache
+void cache_map(char *name, struct map_data *m)
 {
 {
-	struct map_cache_info info;
-	unsigned long len;
-	char *write_buf;
+	struct map_info info;
+	long len;
+	unsigned char *write_buf;
 
 
 	// Create an output buffer twice as big as the uncompressed map... this way we're sure it fits
 	// Create an output buffer twice as big as the uncompressed map... this way we're sure it fits
 	len = m->xs*m->ys*2;
 	len = m->xs*m->ys*2;
-	write_buf = (char *)malloc(len);
+	write_buf = (unsigned char *)malloc(len);
 	// Compress the cells and get the compressed length
 	// Compress the cells and get the compressed length
-	encode_zip((unsigned char *)write_buf, &len, m->cells, m->xs*m->ys);
+	encode_zip(write_buf, &len, m->cells, m->xs*m->ys);
 
 
 	// Fill the map header
 	// Fill the map header
 	strncpy(info.name, name, MAP_NAME_LENGTH);
 	strncpy(info.name, name, MAP_NAME_LENGTH);
-	info.index = MakeUShortLE(index);
 	info.xs = MakeShortLE(m->xs);
 	info.xs = MakeShortLE(m->xs);
 	info.ys = MakeShortLE(m->ys);
 	info.ys = MakeShortLE(m->ys);
-	info.len = MakeLongLE((long)len);
+	info.len = MakeLongLE(len);
 
 
 	// Append map header then compressed cells at the end of the file
 	// Append map header then compressed cells at the end of the file
-	fseek(map_cache_fp, filesize, SEEK_SET);
-	fwrite(&info, sizeof(struct map_cache_info), 1, map_cache_fp);
+	fseek(map_cache_fp, header.file_size, SEEK_SET);
+	fwrite(&info, sizeof(struct map_info), 1, map_cache_fp);
 	fwrite(write_buf, 1, len, map_cache_fp);
 	fwrite(write_buf, 1, len, map_cache_fp);
-	map_count++;
-	filesize += sizeof(struct map_cache_info) + len;
+	header.file_size += sizeof(struct map_info) + len;
+	header.map_count++;
 
 
 	free(write_buf);
 	free(write_buf);
 	free(m->cells);
 	free(m->cells);
@@ -175,41 +192,111 @@ void cache_map(char *name, unsigned short index, struct map_data *m)
 	return;
 	return;
 }
 }
 
 
+// Checks whether a map is already is the cache
+int find_map(char *name)
+{
+	int i;
+	struct map_info info;
+
+	fseek(map_cache_fp, sizeof(struct main_header), SEEK_SET);
+
+	for(i = 0; i < header.map_count; i++) {
+		fread(&info, sizeof(info), 1, map_cache_fp);
+		if(strcmp(name, info.name) == 0) // Map found
+			return 1;
+		else // Map not found, jump to the beginning of the next map info header
+			fseek(map_cache_fp, GetLong((unsigned char *)&(info.len)), SEEK_CUR);
+	}
+
+	return 0;
+}
+
+// Cuts the extension from a map name
+char *remove_extension(char *mapname)
+{
+	char *ptr, *ptr2;
+	ptr = strchr(mapname, '.');
+	if (ptr) { //Check and remove extension.
+		while (ptr[1] && (ptr2 = strchr(ptr+1, '.')))
+			ptr = ptr2; //Skip to the last dot.
+		if(stricmp(ptr,".gat") == 0 ||
+			stricmp(ptr,".afm") == 0 ||
+			stricmp(ptr,".af2") == 0)
+			*ptr = '\0'; //Remove extension.
+	}
+	return mapname;
+}
+
+// Processes command-line arguments
+void process_args(int argc, char *argv[])
+{
+	int i;
+
+	for(i = 0; i < argc; i++) {
+		if(strcmp(argv[i], "-grf") == 0) {
+			if(++i < argc)
+				strcpy(grf_list_file, argv[i]);
+		} else if(strcmp(argv[i], "-list") == 0) {
+			if(++i < argc)
+				strcpy(map_list_file, argv[i]);
+		} else if(strcmp(argv[i], "-cache") == 0) {
+			if(++i < argc)
+				strcpy(map_cache_file, argv[i]);
+		} else if(strcmp(argv[i], "-rebuild") == 0)
+			rebuild = 1;
+	}
+
+}
+
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 {
 	FILE *list;
 	FILE *list;
 	char line[1024];
 	char line[1024];
 	struct map_data map;
 	struct map_data map;
-	char name[MAP_NAME_LENGTH];
-	unsigned short index = 1;
+	char name[MAP_NAME_LENGTH_EXT];
 
 
-	if(argc > 1)
-		strcpy(grf_list_file, argv[1]);
-	if(argc > 2)
-		strcpy(map_list_file, argv[2]);
-	if(argc > 3)
-		strcpy(map_cache_file, argv[3]);
+	// Process the command-line arguments
+	process_args(argc, argv);
 
 
 	printf("Initializing grfio with %s\n", grf_list_file);
 	printf("Initializing grfio with %s\n", grf_list_file);
 	grfio_init(grf_list_file);
 	grfio_init(grf_list_file);
 
 
+	// Attempt to open the map cache file and force rebuild if not found
 	printf("Opening map cache: %s\n", map_cache_file);
 	printf("Opening map cache: %s\n", map_cache_file);
-	map_cache_fp = fopen(map_cache_file, "wb");
-	if( map_cache_fp == NULL ) {
+	if(!rebuild) {
+		map_cache_fp = fopen(map_cache_file, "rb");
+		if(map_cache_fp == NULL) {
+			printf("Existing map cache not found, forcing rebuild mode\n");
+			rebuild = 1;
+		} else
+			fclose(map_cache_fp);
+	}
+	if(rebuild)
+		map_cache_fp = fopen(map_cache_file, "w+b");
+	else
+		map_cache_fp = fopen(map_cache_file, "r+b");
+	if(map_cache_fp == NULL) {
 		printf("Failure when opening map cache file %s\n", map_cache_file);
 		printf("Failure when opening map cache file %s\n", map_cache_file);
 		exit(1);
 		exit(1);
 	}
 	}
 
 
+	// Open the map list
 	printf("Opening map list: %s\n", map_list_file);
 	printf("Opening map list: %s\n", map_list_file);
 	list = fopen(map_list_file, "r");
 	list = fopen(map_list_file, "r");
-	if( list == NULL ) {
+	if(list == NULL) {
 		printf("Failure when opening maps list file %s\n", map_list_file);
 		printf("Failure when opening maps list file %s\n", map_list_file);
-		exit(1);
+		exit(2);
 	}
 	}
 
 
 	// Initialize the main header
 	// Initialize the main header
-	map_count = 0;
-	filesize = sizeof(map_count);
+	if(rebuild) {
+		header.file_size = sizeof(struct main_header);
+		header.map_count = 0;
+	} else {
+		fread(&header, sizeof(struct main_header), 1, map_cache_fp);
+		header.file_size = GetULong((unsigned char *)&(header.file_size));
+		header.map_count = GetUShort((unsigned char *)&(header.map_count));
+	}
 
 
 	// Read and process the map list
 	// Read and process the map list
 	while(fgets(line, 1020, list)){
 	while(fgets(line, 1020, list)){
@@ -217,30 +304,37 @@ int main(int argc, char *argv[])
 		if(line[0] == '/' && line[1] == '/')
 		if(line[0] == '/' && line[1] == '/')
 			continue;
 			continue;
 
 
-		if(sscanf(line, "%16s %hu", name, &index) > 0) { // No defines in strings, 16 is hardcoded here
-				printf("Index %d : %s\n", index, name);
-				if(read_map(name, &map))
-					cache_map(name, index, &map);
-				else
-					printf("Map file not found in GRF\n");
-				// If the 2nd argument is omitted at next line, we'll keep last used index + 1
-				index++;
-		}
+		if(sscanf(line, "%15s", name) < 1)
+			continue;
+
+		if(strcmp("map:", name) == 0 && sscanf(line, "%*s %15s", name) < 1)
+			continue;
+
+		remove_extension(name);
+		printf("%s", name);
+		if(find_map(name))
+			printf(" already in cache!\n");
+		else if(read_map(name, &map)) {
+			cache_map(name, &map);
+			printf(" successfully cached\n");
+		} else
+			printf(" not found in GRF!\n");
+
 	}
 	}
 
 
 	printf("Closing map list: %s\n", map_list_file);
 	printf("Closing map list: %s\n", map_list_file);
 	fclose(list);
 	fclose(list);
 
 
-	printf("Closing map cache: %s\n", map_cache_file);
 	// Write the main header and close the map cache
 	// Write the main header and close the map cache
+	printf("Closing map cache: %s\n", map_cache_file);
 	fseek(map_cache_fp, 0, SEEK_SET);
 	fseek(map_cache_fp, 0, SEEK_SET);
-	fwrite(&map_count, sizeof(map_count), 1, map_cache_fp);
+	fwrite(&header, sizeof(struct main_header), 1, map_cache_fp);
 	fclose(map_cache_fp);
 	fclose(map_cache_fp);
 
 
 	printf("Finalizing grfio\n");
 	printf("Finalizing grfio\n");
 	grfio_final();
 	grfio_final();
 
 
-	printf("%d maps cached\n", map_count);
+	printf("%d maps now in cache\n", header.map_count);
 
 
 	return 0;
 	return 0;
 }
 }

+ 15 - 0
tools/mapcache/grf_files.txt

@@ -0,0 +1,15 @@
+//-----------------------------------------
+// GRF List
+//  Add as many entries as you wish
+//-----------------------------------------
+
+//grf: C:\Program Files\Gravity\RO\data.grf
+grf: C:\Program Files\Gravity\RO\sdata.grf
+
+//-----------------------------------------
+// Data Directory
+//  Path must include trailing backslash
+//  Only one entry supported!
+//-----------------------------------------
+
+//data_dir: C:\Program Files\Gravity\RO\