Browse Source

Split off mapreg code from script.c
* new mapserver files, mapreg.h, mapreg_txt.c, mapreg_sql.c
* removed MAPREGSQL from project files / makefiles
* mapreg storage engine is now fully dependent on the server type
* added config settings mapreg_txt and mapreg_db to inter config
* added get_str() function to complement add_str()
* fixed txt mapreg code allowing too long variable names

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

ultramage 16 years ago
parent
commit
dcc2cdb5da

+ 7 - 0
Changelog-Trunk.txt

@@ -4,6 +4,13 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 2008/08/15
 2008/08/15
+	* Split off mapreg code from script.c [ultramage]
+	- new mapserver files, mapreg.h, mapreg_txt.c, mapreg_sql.c
+	- removed MAPREGSQL from project files / makefiles
+	- mapreg storage engine is now fully dependent on the server type
+	- added config settings mapreg_txt and mapreg_db to inter config
+	- added get_str() function to complement add_str()
+	- fixed txt mapreg code allowing too long variable names
 	* Removed gm_cant_party_max_lv. It now uses gm_cant_party_min_lv as the threshold. (bugreport:2051) [SketchyPhoenix] 
 	* Removed gm_cant_party_max_lv. It now uses gm_cant_party_min_lv as the threshold. (bugreport:2051) [SketchyPhoenix] 
 2008/08/11
 2008/08/11
 	* Fixed right-click npc unload not unloading duplicates (bugreport:2014)
 	* Fixed right-click npc unload not unloading duplicates (bugreport:2014)

+ 2 - 0
conf/Changelog.txt

@@ -1,5 +1,7 @@
 Date	Added
 Date	Added
 
 
+2008/08/13
+	* Added config settings mapreg_txt and mapreg_db to inter config [ultramage]
 2008/08/10
 2008/08/10
 	* Removed duplicate gef_cas mapflags [Yommy]
 	* Removed duplicate gef_cas mapflags [Yommy]
 2008/08/01
 2008/08/01

+ 4 - 0
conf/inter_athena.conf

@@ -38,6 +38,9 @@ castle_txt: save/castle.txt
 // Status change flatfile database, for status changes that are saved between sessions.
 // Status change flatfile database, for status changes that are saved between sessions.
 scdata_txt: save/scdata.txt
 scdata_txt: save/scdata.txt
 
 
+// Mapserver permanent script variables ($-type)
+mapreg_txt: save/mapreg.txt
+
 
 
 // SQL version options only
 // SQL version options only
 
 
@@ -114,6 +117,7 @@ item_db_db: item_db
 item_db2_db: item_db2
 item_db2_db: item_db2
 mob_db_db: mob_db
 mob_db_db: mob_db
 mob_db2_db: mob_db2
 mob_db2_db: mob_db2
+mapreg_db: mapreg
 
 
 //Use SQL item_db and mob_db for the map server
 //Use SQL item_db and mob_db for the map server
 use_sql_db: no
 use_sql_db: no

+ 0 - 2
conf/map_athena.conf

@@ -121,8 +121,6 @@ help_txt: conf/help.txt
 help2_txt: conf/help2.txt
 help2_txt: conf/help2.txt
 charhelp_txt: conf/charhelp.txt
 charhelp_txt: conf/charhelp.txt
 
 
-mapreg_txt: save/mapreg.txt
-
 // Scripts
 // Scripts
 import: npc/scripts_main.conf
 import: npc/scripts_main.conf
 
 

+ 1 - 34
configure

@@ -1,5 +1,5 @@
 #! /bin/sh
 #! /bin/sh
-# From configure.in Revision: 13024 .
+# From configure.in Revision: 13073 .
 # Guess values for system-dependent variables and create Makefiles.
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61.
 # Generated by GNU Autoconf 2.61.
 #
 #
@@ -1256,9 +1256,6 @@ Optional Features:
                           gcollect, bcheck (defaults to builtin)
                           gcollect, bcheck (defaults to builtin)
   --enable-packetver=ARG  Sets the PACKETVER define of the map-server. (see
   --enable-packetver=ARG  Sets the PACKETVER define of the map-server. (see
                           src/map/clif.h)
                           src/map/clif.h)
-  --enable-mapregsql      Makes map-wide script variables be saved to SQL
-                          instead of TXT files in the sql map-server.
-                          (disabled by default)
   --enable-debug          Compiles extra debug code. (disabled by default)
   --enable-debug          Compiles extra debug code. (disabled by default)
                           (available options: yes, no, gdb)
                           (available options: yes, no, gdb)
 
 
@@ -1764,28 +1761,6 @@ fi
 
 
 
 
 
 
-#
-# mapregsql
-#
-# Check whether --enable-mapregsql was given.
-if test "${enable_mapregsql+set}" = set; then
-  enableval=$enable_mapregsql;
-		enable_mapregsql="$enableval"
-		case $enableval in
-			no);;
-			yes);;
-			*) { { echo "$as_me:$LINENO: error: invalid argument --enable-mapregsql=$enableval... stopping" >&5
-echo "$as_me: error: invalid argument --enable-mapregsql=$enableval... stopping" >&2;}
-   { (exit 1); exit 1; }; };;
-		esac
-
-else
-  enable_mapregsql="no"
-
-fi
-
-
-
 #
 #
 # debug
 # debug
 #
 #
@@ -4516,14 +4491,6 @@ if test -n "$enable_packetver" ; then
 fi
 fi
 
 
 
 
-#
-# Mapregsql
-#
-if test "$enable_mapregsql" = "yes" ; then
-	CFLAGS="$CFLAGS -DMAPREGSQL"
-fi
-
-
 #
 #
 # Debug
 # Debug
 #
 #

+ 0 - 29
configure.in

@@ -50,27 +50,6 @@ AC_ARG_ENABLE(
 )
 )
 
 
 
 
-#
-# mapregsql
-#
-AC_ARG_ENABLE(
-	[mapregsql],
-	AC_HELP_STRING(
-		[--enable-mapregsql],
-		[Makes map-wide script variables be saved to SQL instead of TXT files in the sql map-server. (disabled by default)]
-	),
-	[
-		enable_mapregsql="$enableval"
-		case $enableval in
-			no);;
-			yes);;
-			*) AC_MSG_ERROR([[invalid argument --enable-mapregsql=$enableval... stopping]]);;
-		esac
-	],
-	[enable_mapregsql="no"]
-)
-
-
 #
 #
 # debug
 # debug
 #
 #
@@ -338,14 +317,6 @@ if test -n "$enable_packetver" ; then
 fi
 fi
 
 
 
 
-#
-# Mapregsql
-#
-if test "$enable_mapregsql" = "yes" ; then
-	CFLAGS="$CFLAGS -DMAPREGSQL"
-fi
-
-
 #
 #
 # Debug
 # Debug
 #
 #

+ 1 - 1
doc/script_commands.txt

@@ -533,7 +533,7 @@ nothing  - A permanent variable attached to the character, the default
            names starting with 'l' if you want full backward compatibility.
            names starting with 'l' if you want full backward compatibility.
 "$"      - A global permanent variable.
 "$"      - A global permanent variable.
            They are stored in "save\mapreg.txt" or database table `mapreg`,
            They are stored in "save\mapreg.txt" or database table `mapreg`,
-           depending on server type and the MAPREGSQL compilation flag.
+           depending on server type.
 "$@"     - A global temporary variable.
 "$@"     - A global temporary variable.
            This is important for scripts which are called with no RID
            This is important for scripts which are called with no RID
            attached, that is, not triggered by a specific character object.
            attached, that is, not triggered by a specific character object.

+ 5 - 3
src/map/Makefile.in

@@ -18,13 +18,15 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
 	storage.o skill.o atcommand.o charcommand.o battle.o \
 	storage.o skill.o atcommand.o charcommand.o battle.o \
 	intif.o trade.o party.o vending.o guild.o pet.o \
 	intif.o trade.o party.o vending.o guild.o pet.o \
 	log.o mail.o date.o unit.o mercenary.o quest.o
 	log.o mail.o date.o unit.o mercenary.o quest.o
-MAP_TXT_OBJ = $(MAP_OBJ:%=obj_txt/%)
-MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%)
+MAP_TXT_OBJ = $(MAP_OBJ:%=obj_txt/%) \
+	obj_txt/mapreg_txt.o
+MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
+	obj_sql/mapreg_sql.o
 MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
 MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
 	chat.h itemdb.h mob.h script.h path.h \
 	chat.h itemdb.h mob.h script.h path.h \
 	storage.h skill.h atcommand.h charcommand.h battle.h \
 	storage.h skill.h atcommand.h charcommand.h battle.h \
 	intif.h trade.h party.h vending.h guild.h pet.h \
 	intif.h trade.h party.h vending.h guild.h pet.h \
-	log.h mail.h date.h unit.h mercenary.h quest.h
+	log.h mail.h date.h unit.h mercenary.h quest.h mapreg.h
 
 
 HAVE_MYSQL=@HAVE_MYSQL@
 HAVE_MYSQL=@HAVE_MYSQL@
 ifeq ($(HAVE_MYSQL),yes)
 ifeq ($(HAVE_MYSQL),yes)

+ 4 - 3
src/map/map.c

@@ -32,6 +32,7 @@
 #include "unit.h"
 #include "unit.h"
 #include "battle.h"
 #include "battle.h"
 #include "script.h"
 #include "script.h"
+#include "mapreg.h"
 #include "guild.h"
 #include "guild.h"
 #include "pet.h"
 #include "pet.h"
 #include "mercenary.h"
 #include "mercenary.h"
@@ -2932,9 +2933,6 @@ int map_config_read(char *cfgName)
 		if (strcmpi(w1, "charhelp_txt") == 0)
 		if (strcmpi(w1, "charhelp_txt") == 0)
 			strcpy(charhelp_txt, w2);
 			strcpy(charhelp_txt, w2);
 		else
 		else
-		if (strcmpi(w1, "mapreg_txt") == 0)
-			strcpy(mapreg_txt, w2);
-		else
 		if(strcmpi(w1,"map_cache_file") == 0)
 		if(strcmpi(w1,"map_cache_file") == 0)
 			strncpy(map_cache_file,w2,255);
 			strncpy(map_cache_file,w2,255);
 		else
 		else
@@ -3034,6 +3032,9 @@ int inter_config_read(char *cfgName)
 		if(strcmpi(w1,"log_db_db")==0)
 		if(strcmpi(w1,"log_db_db")==0)
 			strcpy(log_db_db, w2);
 			strcpy(log_db_db, w2);
 	#endif
 	#endif
+		else
+		if( mapreg_config_read(w1,w2) )
+			continue;
 		//support the import command, just like any other config
 		//support the import command, just like any other config
 		else
 		else
 		if(strcmpi(w1,"import")==0)
 		if(strcmpi(w1,"import")==0)

+ 17 - 0
src/map/mapreg.h

@@ -0,0 +1,17 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _MAPREG_H_
+#define _MAPREG_H_
+
+void mapreg_reload(void);
+void mapreg_final(void);
+void mapreg_init(void);
+bool mapreg_config_read(const char* w1, const char* w2);
+
+int mapreg_readreg(int uid);
+char* mapreg_readregstr(int uid);
+bool mapreg_setreg(int uid, int val);
+bool mapreg_setregstr(int uid, const char* str);
+
+#endif /* _MAPREG_H_ */

+ 242 - 0
src/map/mapreg_sql.c

@@ -0,0 +1,242 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
+#include "../common/sql.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "map.h" // mmysql_handle
+#include "script.h"
+#include <stdlib.h>
+#include <string.h>
+
+static DBMap* mapreg_db = NULL; // int var_id -> int value
+static DBMap* mapregstr_db = NULL; // int var_id -> char* value
+
+static char mapreg_table[32] = "mapreg";
+static bool mapreg_dirty = false;
+#define MAPREG_AUTOSAVE_INTERVAL (300*1000)
+
+
+/// Looks up the value of an integer variable using its uid.
+int mapreg_readreg(int uid)
+{
+	return (int)idb_get(mapreg_db, uid);
+}
+
+/// Looks up the value of a string variable using its uid.
+char* mapreg_readregstr(int uid)
+{
+	return (char*)idb_get(mapregstr_db, uid);
+}
+
+/// Modifies the value of an integer variable.
+bool mapreg_setreg(int uid, int val)
+{
+	int num = uid & 0x00ffffff;
+	int i   = uid & 0xff000000 >> 24;
+	const char* name = get_str(num);
+
+	if( val != 0 )
+	{
+		if( idb_put(mapreg_db,uid,(void*)val) )
+			; // already exists, delay write
+		else
+		if( name[1] == '@' )
+			; // nothing more to do
+		else
+		{// write new wariable to database
+			char tmp_str[32*2+1];
+			Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32));
+			if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val) )
+				Sql_ShowDebug(mmysql_handle);
+		}
+	}
+	else // val == 0
+	{
+		idb_remove(mapreg_db,uid);
+
+		if( name[1] == '@' )
+			; // nothing more to do
+		else
+		{// Remove from database because it is unused.
+			if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) )
+				Sql_ShowDebug(mmysql_handle);
+		}
+	}
+
+	mapreg_dirty = true;
+	return true;
+}
+
+/// Modifies the value of a string variable.
+bool mapreg_setregstr(int uid, const char* str)
+{
+	int num = uid & 0x00ffffff;
+	int i   = uid & 0xff000000 >> 24;
+	const char* name = get_str(num);
+	
+	if( str == NULL || *str == 0 )
+	{
+		if(name[1] != '@') {
+			if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) )
+				Sql_ShowDebug(mmysql_handle);
+		}
+		idb_remove(mapregstr_db,uid);
+	}
+	else
+	{
+		if (idb_put(mapregstr_db,uid, aStrdup(str)))
+			;
+		else if(name[1] != '@') { //put returned null, so we must insert.
+			// Someone is causing a database size infinite increase here without name[1] != '@' [Lance]
+			char tmp_str[32*2+1];
+			char tmp_str2[255*2+1];
+			Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32));
+			Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255));
+			if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2) )
+				Sql_ShowDebug(mmysql_handle);
+		}
+	}
+
+	mapreg_dirty = true;
+	return true;
+}
+
+/// Loads permanent variables from database
+static void script_load_mapreg(void)
+{
+	/*
+	        0        1       2
+	   +-------------------------+
+	   | varname | index | value |
+	   +-------------------------+
+	                                */
+	SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle);
+	char varname[32+1];
+	int index;
+	char value[255+1];
+	uint32 length;
+
+	if ( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg_table)
+	  || SQL_ERROR == SqlStmt_Execute(stmt)
+	  ) {
+		SqlStmt_ShowDebug(stmt);
+		SqlStmt_Free(stmt);
+		return;
+	}
+
+	SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &varname[0], 32, &length, NULL);
+	SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL);
+	SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], 255, NULL, NULL);
+	
+	while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) )
+	{
+		int s = add_str(varname);
+		int i = index;
+
+		if( varname[length-1] == '$' )
+			idb_put(mapregstr_db, (i<<24)|s, aStrdup(value));
+		else
+			idb_put(mapreg_db, (i<<24)|s, (void *)atoi(value));
+	}
+	
+	SqlStmt_Free(stmt);
+
+	mapreg_dirty = false;
+}
+
+/// Saves permanent variables to database
+static void script_save_mapreg(void)
+{
+	DBIterator* iter;
+	void* data;
+	DBKey key;
+
+	iter = mapreg_db->iterator(mapreg_db);
+	for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) )
+	{
+		int num = key.i & 0x00ffffff;
+		int i   = key.i & 0xff000000 >> 24;
+		const char* name = get_str(num);
+
+		if( name[1] == '@' )
+			continue;
+
+		if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, (int)data, name, i) )
+			Sql_ShowDebug(mmysql_handle);
+	}
+	iter->destroy(iter);
+
+	iter = mapregstr_db->iterator(mapregstr_db);
+	for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) )
+	{
+		int num = key.i & 0x00ffffff;
+		int i   = key.i & 0xff000000 >> 24;
+		const char* name = get_str(num);
+		char tmp_str2[2*255+1];
+
+		if( name[1] == '@' )
+			continue;
+
+		Sql_EscapeStringLen(mmysql_handle, tmp_str2, (char*)data, safestrnlen((char*)data, 255));
+		if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, tmp_str2, name, i) )
+			Sql_ShowDebug(mmysql_handle);
+	}
+	iter->destroy(iter);
+
+	mapreg_dirty = false;
+}
+
+static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data)
+{
+	if( mapreg_dirty )
+		script_save_mapreg();
+
+	return 0;
+}
+
+
+void mapreg_reload(void)
+{
+	if( mapreg_dirty )
+		script_save_mapreg();
+
+	mapreg_db->clear(mapreg_db, NULL);
+	mapregstr_db->clear(mapregstr_db, NULL);
+
+	script_load_mapreg();
+}
+
+void mapreg_final(void)
+{
+	if( mapreg_dirty )
+		script_save_mapreg();
+
+	mapreg_db->destroy(mapreg_db,NULL);
+	mapregstr_db->destroy(mapregstr_db,NULL);
+}
+
+void mapreg_init(void)
+{
+	mapreg_db = idb_alloc(DB_OPT_BASE);
+	mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+	script_load_mapreg();
+
+	add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg");
+	add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL);
+}
+
+bool mapreg_config_read(const char* w1, const char* w2)
+{
+	if(!strcmpi(w1, "mapreg_db"))
+		safestrncpy(mapreg_table, w2, sizeof(mapreg_table));
+	else
+		return false;
+
+	return true;
+}

+ 202 - 0
src/map/mapreg_txt.c

@@ -0,0 +1,202 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/lock.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "script.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static DBMap* mapreg_db = NULL; // int var_id -> int value
+static DBMap* mapregstr_db = NULL; // int var_id -> char* value
+
+static char mapreg_txt[256] = "save/mapreg.txt";
+static bool mapreg_dirty = false;
+#define MAPREG_AUTOSAVE_INTERVAL (300*1000)
+
+
+/// Looks up the value of an integer variable using its uid.
+int mapreg_readreg(int uid)
+{
+	return (int)idb_get(mapreg_db, uid);
+}
+
+/// Looks up the value of a string variable using its uid.
+char* mapreg_readregstr(int uid)
+{
+	return (char*)idb_get(mapregstr_db, uid);
+}
+
+/// Modifies the value of an integer variable.
+bool mapreg_setreg(int uid, int val)
+{
+	if( val != 0 )
+		idb_put(mapreg_db,uid,(void*)val);
+	else
+		idb_remove(mapreg_db,uid);
+
+	mapreg_dirty = true;
+	return true;
+}
+
+/// Modifies the value of a string variable.
+bool mapreg_setregstr(int uid, const char* str)
+{
+	if( str == NULL || *str == 0 )
+		idb_remove(mapregstr_db,uid);
+	else
+		idb_put(mapregstr_db,uid,aStrdup(str));
+
+	mapreg_dirty = true;
+	return true;
+}
+
+/// Loads permanent variables from savefile
+static void script_load_mapreg(void)
+{
+	FILE* fp;
+	char line[1024];
+
+	fp = fopen(mapreg_txt,"rt");
+	if( fp == NULL )
+		return;
+
+	while( fgets(line,sizeof(line),fp) )
+	{
+		char varname[32+1];
+		char value[255+1];
+		int n,s,i;
+
+		// read name and index
+		if( sscanf(line, "%255[^,],%d\t%n", varname,&i,&n) != 2 &&
+			(i = 0, sscanf(line,"%[^\t]\t%n", varname,&n) != 1) )
+			continue;
+
+		// read value
+		if( sscanf(line + n, "%[^\n\r]", value) != 1 )
+		{
+			ShowError("%s: %s broken data !\n", mapreg_txt, varname);
+			continue;
+		}
+
+		s = add_str(varname);
+		if( varname[strlen(varname)-1] == '$' )
+			idb_put(mapregstr_db, (i<<24)|s, aStrdup(value));
+		else
+			idb_put(mapreg_db, (i<<24)|s, (void*)atoi(value));
+	}
+	fclose(fp);
+
+	mapreg_dirty = false;
+}
+
+/// Saves permanent variables to savefile
+static void script_save_mapreg(void)
+{
+	FILE *fp;
+	int lock;
+	DBIterator* iter;
+	void* data;
+	DBKey key;
+
+	fp = lock_fopen(mapreg_txt,&lock);
+	if( fp == NULL )
+	{
+		ShowError("script_save_mapreg: Unable to lock-open file [%s]!\n", mapreg_txt);
+		return;
+	}
+
+	iter = mapreg_db->iterator(mapreg_db);
+	for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) )
+	{
+		int num = key.i & 0x00ffffff;
+		int i   = key.i & 0xff000000 >> 24;
+		const char* name = get_str(num);
+
+		if( name[1] == '@' )
+			continue;
+
+		if( i == 0 )
+			fprintf(fp, "%s\t%d\n", name, (int)data);
+		else
+			fprintf(fp, "%s,%d\t%d\n", name, i, (int)data);
+	}
+	iter->destroy(iter);
+
+	iter = mapregstr_db->iterator(mapregstr_db);
+	for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) )
+	{
+		int num = key.i & 0x00ffffff;
+		int i   = key.i & 0xff000000 >> 24;
+		const char* name = get_str(num);
+
+		if( name[1] == '@' )
+			continue;
+
+		if( i == 0 )
+			fprintf(fp, "%s\t%s\n", name, (char *)data);
+		else
+			fprintf(fp, "%s,%d\t%s\n", name, i, (char *)data);
+	}
+	iter->destroy(iter);
+
+	lock_fclose(fp,mapreg_txt,&lock);
+
+	mapreg_dirty = false;
+}
+
+static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data)
+{
+	if( mapreg_dirty )
+		script_save_mapreg();
+
+	return 0;
+}
+
+
+void mapreg_reload(void)
+{
+	if( mapreg_dirty )
+		script_save_mapreg();
+
+	mapreg_db->clear(mapreg_db, NULL);
+	mapregstr_db->clear(mapregstr_db, NULL);
+
+	script_load_mapreg();
+}
+
+void mapreg_final(void)
+{
+	if( mapreg_dirty )
+		script_save_mapreg();
+
+	mapreg_db->destroy(mapreg_db,NULL);
+	mapregstr_db->destroy(mapregstr_db,NULL);
+}
+
+void mapreg_init(void)
+{
+	mapreg_db = idb_alloc(DB_OPT_BASE);
+	mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+	script_load_mapreg();
+
+	add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg");
+	add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL);
+}
+
+bool mapreg_config_read(const char* w1, const char* w2)
+{
+	if(!strcmpi(w1, "mapreg_txt"))
+		safestrncpy(mapreg_txt, w2, sizeof(mapreg_txt));
+	else
+		return false;
+
+	return true;
+}

+ 68 - 319
src/map/script.c

@@ -26,6 +26,7 @@
 #include "mob.h"
 #include "mob.h"
 #include "npc.h"
 #include "npc.h"
 #include "pet.h"
 #include "pet.h"
+#include "mapreg.h"
 #include "mercenary.h"	//[orn]
 #include "mercenary.h"	//[orn]
 #include "intif.h"
 #include "intif.h"
 #include "skill.h"
 #include "skill.h"
@@ -157,9 +158,10 @@ static int script_pos,script_size;
 #define GETVALUE(buf,i)		((int)MakeDWord(MakeWord((buf)[i],(buf)[i+1]),MakeWord((buf)[i+2],0)))
 #define GETVALUE(buf,i)		((int)MakeDWord(MakeWord((buf)[i],(buf)[i+1]),MakeWord((buf)[i+2],0)))
 #define SETVALUE(buf,i,n)	((buf)[i]=GetByte(n,0),(buf)[i+1]=GetByte(n,1),(buf)[i+2]=GetByte(n,2))
 #define SETVALUE(buf,i,n)	((buf)[i]=GetByte(n,0),(buf)[i+1]=GetByte(n,1),(buf)[i+2]=GetByte(n,2))
 
 
-#define GETSTRING(off) (str_buf+(off))
 static char *str_buf;
 static char *str_buf;
 static int str_pos,str_size;
 static int str_pos,str_size;
+static int str_data_size = 0;
+int str_num=LABEL_START;
 static struct str_data_struct {
 static struct str_data_struct {
 	enum c_op type;
 	enum c_op type;
 	int str;
 	int str;
@@ -169,7 +171,6 @@ static struct str_data_struct {
 	int val;
 	int val;
 	int next;
 	int next;
 } *str_data = NULL;
 } *str_data = NULL;
-int str_num=LABEL_START,str_data_size;
 
 
 // Using a prime number for SCRIPT_HASH_SIZE should give better distributions
 // Using a prime number for SCRIPT_HASH_SIZE should give better distributions
 #define SCRIPT_HASH_SIZE 1021
 #define SCRIPT_HASH_SIZE 1021
@@ -179,11 +180,6 @@ int str_hash[SCRIPT_HASH_SIZE];
 //#define SCRIPT_HASH_SDBM
 //#define SCRIPT_HASH_SDBM
 #define SCRIPT_HASH_ELF
 #define SCRIPT_HASH_ELF
 
 
-static DBMap* mapreg_db=NULL; // int var_id -> int value
-static DBMap* mapregstr_db=NULL; // int var_id -> char* value
-static int mapreg_dirty=-1;
-char mapreg_txt[256]="save/mapreg.txt";
-#define MAPREG_AUTOSAVE_INTERVAL	(300*1000)
 
 
 static DBMap* scriptlabel_db=NULL; // const char* label_name -> int script_pos
 static DBMap* scriptlabel_db=NULL; // const char* label_name -> int script_pos
 static DBMap* userfunc_db=NULL; // const char* func_name -> struct script_code*
 static DBMap* userfunc_db=NULL; // const char* func_name -> struct script_code*
@@ -248,12 +244,6 @@ int potion_flag=0; //For use on Alchemist improved potions/Potion Pitcher. [Skot
 int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
 int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
 int potion_target=0;
 int potion_target=0;
 
 
-#if !defined(TXT_ONLY) && defined(MAPREGSQL)
-char mapregsql_db[32] = "mapreg";
-char mapregsql_db_varname[32] = "varname";
-char mapregsql_db_index[32] = "index";
-char mapregsql_db_value[32] = "value";
-#endif
 
 
 c_op get_com(unsigned char *script,int *pos);
 c_op get_com(unsigned char *script,int *pos);
 int get_num(unsigned char *script,int *pos);
 int get_num(unsigned char *script,int *pos);
@@ -278,9 +268,6 @@ const char* parse_subexpr(const char* p,int limit);
 void push_val(struct script_stack *stack,int type,int val);
 void push_val(struct script_stack *stack,int type,int val);
 int run_func(struct script_state *st);
 int run_func(struct script_state *st);
 
 
-int mapreg_setreg(int num,int val);
-int mapreg_setregstr(int num,const char *str);
-
 enum {
 enum {
 	MF_NOMEMO,	//0
 	MF_NOMEMO,	//0
 	MF_NOTELEPORT,
 	MF_NOTELEPORT,
@@ -515,66 +502,84 @@ static unsigned int calc_hash(const char* p)
 	return h % SCRIPT_HASH_SIZE;
 	return h % SCRIPT_HASH_SIZE;
 }
 }
 
 
+
 /*==========================================
 /*==========================================
- * str_dataの中に名前があるか検索する
+ * str_data manipulation functions
  *------------------------------------------*/
  *------------------------------------------*/
-// 既存のであれば番号、無ければ-1
-static int search_str(const char *p)
+
+/// Looks up string using the provided id.
+const char* get_str(int id)
+{
+	Assert( id >= LABEL_START && id < str_size );
+	return str_buf+str_data[id].str;
+}
+
+/// Returns the uid of the string, or -1.
+static int search_str(const char* p)
 {
 {
 	int i;
 	int i;
-	i=str_hash[calc_hash(p)];
-	while(i){
-		if(strcasecmp(str_buf+str_data[i].str,p)==0){
+
+	for( i = str_hash[calc_hash(p)]; i != 0; i = str_data[i].next )
+		if( strcasecmp(get_str(i),p) == 0 )
 			return i;
 			return i;
-		}
-		i=str_data[i].next;
-	}
+
 	return -1;
 	return -1;
 }
 }
 
 
-/*==========================================
- * str_dataに名前を登録
- *------------------------------------------*/
-// 既存のであれば番号、無ければ登録して新規番号
+/// Stores a copy of the string and returns its id.
+/// If an identical string is already present, returns its id instead.
 int add_str(const char* p)
 int add_str(const char* p)
 {
 {
-	int i;
+	int i, h;
 	int len;
 	int len;
 
 
-	i=calc_hash(p);
-	if(str_hash[i]==0){
-		str_hash[i]=str_num;
-	} else {
-		i=str_hash[i];
-		for(;;){
-			if(strcasecmp(str_buf+str_data[i].str,p)==0){
-				return i;
-			}
-			if(str_data[i].next==0)
-				break;
-			i=str_data[i].next;
+	h = calc_hash(p);
+
+	if( str_hash[h] == 0 )
+	{// empty bucket, add new node here
+		str_hash[h] = str_num;
+	}
+	else
+	{// scan for end of list, or occurence of identical string
+		for( i = str_hash[h]; ; i = str_data[i].next )
+		{
+			if( strcasecmp(get_str(i),p) == 0 )
+				return i; // string already in list
+			if( str_data[i].next == 0 )
+				break; // reached the end
 		}
 		}
-		str_data[i].next=str_num;
+
+		// append node to end of list
+		str_data[i].next = str_num;
 	}
 	}
-	if(str_num>=str_data_size){
-		str_data_size+=128;
+
+	// grow list if neccessary
+	if( str_num >= str_data_size )
+	{
+		str_data_size += 128;
 		RECREATE(str_data,struct str_data_struct,str_data_size);
 		RECREATE(str_data,struct str_data_struct,str_data_size);
 		memset(str_data + (str_data_size - 128), '\0', 128);
 		memset(str_data + (str_data_size - 128), '\0', 128);
 	}
 	}
+
 	len=(int)strlen(p);
 	len=(int)strlen(p);
-	while(str_pos+len+1>=str_size){
-		str_size+=256;
+
+	// grow string buffer if neccessary
+	while( str_pos+len+1 >= str_size )
+	{
+		str_size += 256;
 		RECREATE(str_buf,char,str_size);
 		RECREATE(str_buf,char,str_size);
 		memset(str_buf + (str_size - 256), '\0', 256);
 		memset(str_buf + (str_size - 256), '\0', 256);
 	}
 	}
-	memcpy(str_buf+str_pos,p,len+1);
-	str_data[str_num].type=C_NOP;
-	str_data[str_num].str=str_pos;
-	str_data[str_num].next=0;
-	str_data[str_num].func=NULL;
-	str_data[str_num].backpatch=-1;
-	str_data[str_num].label=-1;
-	str_pos+=len+1;
+
+	safestrncpy(str_buf+str_pos, p, len+1);
+	str_data[str_num].type = C_NOP;
+	str_data[str_num].str = str_pos;
+	str_data[str_num].next = 0;
+	str_data[str_num].func = NULL;
+	str_data[str_num].backpatch = -1;
+	str_data[str_num].label = -1;
+	str_pos += len+1;
+
 	return str_num++;
 	return str_num++;
 }
 }
 
 
@@ -1462,7 +1467,7 @@ const char* parse_syntax(const char* p)
 					str_data[l].type = C_USERFUNC;
 					str_data[l].type = C_USERFUNC;
 				set_label(l, script_pos, p);
 				set_label(l, script_pos, p);
 				if( parse_options&SCRIPT_USE_LABEL_DB )
 				if( parse_options&SCRIPT_USE_LABEL_DB )
-					strdb_put(scriptlabel_db, GETSTRING(str_data[l].str), (void*)script_pos);
+					strdb_put(scriptlabel_db, get_str(l), (void*)script_pos);
 				return skip_space(p);
 				return skip_space(p);
 			}
 			}
 			else
 			else
@@ -1959,7 +1964,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
 			i=add_word(p);
 			i=add_word(p);
 			set_label(i,script_pos,p);
 			set_label(i,script_pos,p);
 			if( parse_options&SCRIPT_USE_LABEL_DB )
 			if( parse_options&SCRIPT_USE_LABEL_DB )
-				strdb_put(scriptlabel_db, GETSTRING(str_data[i].str), (void*)script_pos);
+				strdb_put(scriptlabel_db, get_str(i), (void*)script_pos);
 			p=tmpp+1;
 			p=tmpp+1;
 			p=skip_space(p);
 			p=skip_space(p);
 			continue;
 			continue;
@@ -2129,7 +2134,7 @@ void get_val(struct script_state* st, struct script_data* data)
 			data->u.str = pc_readregstr(sd, data->u.num);
 			data->u.str = pc_readregstr(sd, data->u.num);
 			break;
 			break;
 		case '$':
 		case '$':
-			data->u.str = (char *)idb_get(mapregstr_db, data->u.num);
+			data->u.str = mapreg_readregstr(data->u.num);
 			break;
 			break;
 		case '#':
 		case '#':
 			if( name[1] == '#' )
 			if( name[1] == '#' )
@@ -2183,7 +2188,7 @@ void get_val(struct script_state* st, struct script_data* data)
 			data->u.num = pc_readreg(sd, data->u.num);
 			data->u.num = pc_readreg(sd, data->u.num);
 			break;
 			break;
 		case '$':
 		case '$':
-			data->u.num = (int)idb_get(mapreg_db, data->u.num);
+			data->u.num = mapreg_readreg(data->u.num);
 			break;
 			break;
 		case '#':
 		case '#':
 			if( name[1] == '#' )
 			if( name[1] == '#' )
@@ -3190,249 +3195,6 @@ void run_script_main(struct script_state *st)
 
 
 }
 }
 
 
-/*==========================================
- * マップ変数の変更
- *------------------------------------------*/
-int mapreg_setreg(int num, int val)
-{
-#if !defined(TXT_ONLY) && defined(MAPREGSQL)
-	int i = num >> 24;
-	char* name = str_buf + str_data[num&0x00ffffff].str;
-
-	if( val != 0 ) {
-		if(idb_put(mapreg_db,num,(void*)val))
-			;
-		else if(name[1] != '@') {
-			char tmp_str[32*2+1];
-			Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32));
-			if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%d')", mapregsql_db, mapregsql_db_varname, mapregsql_db_index, mapregsql_db_value, tmp_str, i, val) )
-				Sql_ShowDebug(mmysql_handle);
-		}
-	} else { // val == 0
-		if(name[1] != '@') { // Remove from database because it is unused.
-			if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_varname, name, mapregsql_db_index, i) )
-				Sql_ShowDebug(mmysql_handle);
-		}
-		idb_remove(mapreg_db,num);
-	}
-#else
-	if(val != 0)
-		idb_put(mapreg_db,num,(void*)val);
-	else
-		idb_remove(mapreg_db,num);
-#endif
-
-	mapreg_dirty = 1;
-	return 1;
-}
-/*==========================================
- * 文字列型マップ変数の変更
- *------------------------------------------*/
-int mapreg_setregstr(int num, const char* str)
-{
-#if !defined(TXT_ONLY) && defined(MAPREGSQL)
-	int i = num >> 24;
-	char* name = str_buf + str_data[num&0x00ffffff].str;
-	
-	if( str==NULL || *str==0 ) {
-		if(name[1] != '@') {
-			if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_varname, name, mapregsql_db_index, i) )
-				Sql_ShowDebug(mmysql_handle);
-		}
-		idb_remove(mapregstr_db,num);
-		mapreg_dirty = 1;
-		return 1;
-	}
-	
-	if (idb_put(mapregstr_db,num, aStrdup(str)))
-		;
-	else if(name[1] != '@') { //put returned null, so we must insert.
-		// Someone is causing a database size infinite increase here without name[1] != '@' [Lance]
-		char tmp_str[32*2+1];
-		char tmp_str2[255*2+1];
-		Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32));
-		Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255));
-		if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%s')", mapregsql_db, mapregsql_db_varname, mapregsql_db_index, mapregsql_db_value, tmp_str, i, tmp_str2) )
-			Sql_ShowDebug(mmysql_handle);
-	}
-#else
-	if( str==NULL || *str==0 )
-		idb_remove(mapregstr_db,num);
-	else
-		idb_put(mapregstr_db,num,aStrdup(str));
-#endif
-
-	mapreg_dirty = 1;
-	return 1;
-}
-
-/*==========================================
- * 永続的マップ変数の読み込み
- *------------------------------------------*/
-static int script_load_mapreg(void)
-{
-#if defined(TXT_ONLY) || !defined(MAPREGSQL)
-	FILE* fp;
-	char line[1024];
-
-	if( (fp=fopen(mapreg_txt,"rt")) == NULL )
-		return -1;
-
-	while(fgets(line,sizeof(line),fp))
-	{
-		char buf1[256],buf2[1024];
-		char* p;
-		int n,v,s,i;
-		if( sscanf(line,"%255[^,],%d\t%n",buf1,&i,&n)!=2 &&
-			(i=0,sscanf(line,"%[^\t]\t%n",buf1,&n)!=1) )
-			continue;
-		if( buf1[strlen(buf1)-1] == '$' ) {
-			if( sscanf(line + n, "%[^\n\r]", buf2) != 1 ) {
-				ShowError("%s: %s broken data !\n", mapreg_txt, buf1);
-				continue;
-			}
-			p = aStrdup(buf2);
-			s = add_str(buf1);
-			idb_put(mapregstr_db, (i<<24)|s, p);
-		} else {
-			if( sscanf(line + n, "%d", &v) != 1 ) {
-				ShowError("%s: %s broken data !\n", mapreg_txt, buf1);
-				continue;
-			}
-			s = add_str(buf1);
-			idb_put(mapreg_db, (i<<24)|s, (void*)v);
-		}
-	}
-	fclose(fp);
-
-	mapreg_dirty = 0;
-	return 0;
-#else
-	/*
-		     0       1       2
-		+-------------------------+
-		| varname | index | value |
-		+-------------------------+
-	 */
-
-	SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle);
-	char varname[32+1];
-	int index;
-	char value[255+1];
-	uint32 length;
-
-	if ( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `%s`, `%s`, `%s` FROM `%s`", mapregsql_db_varname, mapregsql_db_index, mapregsql_db_value, mapregsql_db)
-	  || SQL_ERROR == SqlStmt_Execute(stmt)
-	  ) {
-		SqlStmt_ShowDebug(stmt);
-		SqlStmt_Free(stmt);
-		return -1;
-	}
-
-	SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &varname[0], 32, &length, NULL);
-	SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL);
-	SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], 255, NULL, NULL);
-	
-	while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) )
-	{
-		if( varname[length-1] == '$' ) {
-			int s = add_str(varname);
-			int i = index;
-			char* p = aStrdup(value);
-			idb_put(mapregstr_db, (i<<24)|s, p);
-		} else {
-			int s = add_str(varname);
-			int i = index;
-			int v = atoi(value);
-			idb_put(mapreg_db, (i<<24)|s, (void *)v);
-		}
-	}
-	
-	SqlStmt_Free(stmt);
-
-	mapreg_dirty = 0;
-	return 0;
-
-#endif /* TXT_ONLY */
-}
-/*==========================================
- * 永続的マップ変数の書き込み
- *------------------------------------------*/
-static int script_save_mapreg_intsub(DBKey key,void *data,va_list ap)
-{
-	int num=key.i&0x00ffffff, i=key.i>>24;
-	char *name=str_buf+str_data[num].str;
-
-#if defined(TXT_ONLY) || !defined(MAPREGSQL)
-	FILE *fp=va_arg(ap,FILE*);
-	if( name[1]!='@' ) {
-		if(i==0)
-			fprintf(fp,"%s\t%d\n", name, (int)data);
-		else
-			fprintf(fp,"%s,%d\t%d\n", name, i, (int)data);
-	}
-#else
-	if ( name[1] != '@') {
-		if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `%s`='%d' WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_value, (int)data, mapregsql_db_varname, name, mapregsql_db_index, i) )
-			Sql_ShowDebug(mmysql_handle);
-	}
-#endif
-
-	return 0;
-}
-
-static int script_save_mapreg_strsub(DBKey key,void *data,va_list ap)
-{
-	int num=key.i&0x00ffffff, i=key.i>>24;
-	char *name=str_buf+str_data[num].str;
-
-#if defined(TXT_ONLY) || !defined(MAPREGSQL)
-	FILE *fp=va_arg(ap,FILE*);
-	if( name[1]!='@' ) {
-		if(i==0)
-			fprintf(fp,"%s\t%s\n", name, (char *)data);
-		else
-			fprintf(fp,"%s,%d\t%s\n", name, i, (char *)data);
-	}
-#else
-	if ( name[1] != '@') {
-		char tmp_str2[2*255+1];
-		Sql_EscapeStringLen(mmysql_handle, tmp_str2, (char*)data, safestrnlen((char*)data, 255));
-		if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `%s`='%s' WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_value, tmp_str2, mapregsql_db_varname, name, mapregsql_db_index, i) )
-			Sql_ShowDebug(mmysql_handle);
-	}
-#endif
-
-	return 0;
-}
-static int script_save_mapreg(void)
-{
-#if defined(TXT_ONLY) || !defined(MAPREGSQL)
-	FILE *fp;
-	int lock;
-
-	if( (fp=lock_fopen(mapreg_txt,&lock))==NULL ) {
-		ShowError("script_save_mapreg: Unable to lock-open file [%s]\n",mapreg_txt);
-		return -1;
-	}
-	mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub,fp);
-	mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub,fp);
-	lock_fclose(fp,mapreg_txt,&lock);
-#else
-	mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub);
-	mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub);
-#endif
-	mapreg_dirty=0;
-	return 0;
-}
-static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data)
-{
-	if(mapreg_dirty)
-		if (script_save_mapreg() == -1)
-			ShowError("Failed to save the mapreg data!\n");
-	return 0;
-}
-
 int script_config_read(char *cfgName)
 int script_config_read(char *cfgName)
 {
 {
 	int i;
 	int i;
@@ -3548,11 +3310,8 @@ int do_final_script()
 	}
 	}
 #endif
 #endif
 
 
-	if(mapreg_dirty>=0)
-		script_save_mapreg();
+	mapreg_final();
 
 
-	mapreg_db->destroy(mapreg_db,NULL);
-	mapregstr_db->destroy(mapregstr_db,NULL);
 	scriptlabel_db->destroy(scriptlabel_db,NULL);
 	scriptlabel_db->destroy(scriptlabel_db,NULL);
 	userfunc_db->destroy(userfunc_db,do_final_userfunc_sub);
 	userfunc_db->destroy(userfunc_db,do_final_userfunc_sub);
 	if(sleep_db) {
 	if(sleep_db) {
@@ -3578,26 +3337,16 @@ int do_final_script()
  *------------------------------------------*/
  *------------------------------------------*/
 int do_init_script()
 int do_init_script()
 {
 {
-	mapreg_db= idb_alloc(DB_OPT_BASE);
-	mapregstr_db=idb_alloc(DB_OPT_RELEASE_DATA);
 	userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0);
 	userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0);
 	scriptlabel_db=strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA),50);
 	scriptlabel_db=strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA),50);
-	
-	script_load_mapreg();
-
-	add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg");
-	add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL);
 
 
+	mapreg_init();
+	
 	return 0;
 	return 0;
 }
 }
 
 
 int script_reload()
 int script_reload()
 {
 {
-	if(mapreg_dirty>=0)
-		script_save_mapreg();
-	
-	mapreg_db->clear(mapreg_db, NULL);
-	mapregstr_db->clear(mapregstr_db, NULL);
 	userfunc_db->clear(userfunc_db,do_final_userfunc_sub);
 	userfunc_db->clear(userfunc_db,do_final_userfunc_sub);
 	scriptlabel_db->clear(scriptlabel_db, NULL);
 	scriptlabel_db->clear(scriptlabel_db, NULL);
 
 
@@ -3614,7 +3363,7 @@ int script_reload()
 		linkdb_final(&sleep_db);
 		linkdb_final(&sleep_db);
 	}
 	}
 
 
-	script_load_mapreg();
+	mapreg_reload();
 	return 0;
 	return 0;
 }
 }
 
 

+ 4 - 1
src/map/script.h

@@ -4,6 +4,8 @@
 #ifndef _SCRIPT_H_
 #ifndef _SCRIPT_H_
 #define _SCRIPT_H_
 #define _SCRIPT_H_
 
 
+struct map_session_data;
+
 extern int potion_flag; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
 extern int potion_flag; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
 extern int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
 extern int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
 extern int potion_target;
 extern int potion_target;
@@ -150,7 +152,8 @@ struct DBMap* script_get_userfunc_db(void);
 int script_config_read(char *cfgName);
 int script_config_read(char *cfgName);
 int do_init_script(void);
 int do_init_script(void);
 int do_final_script(void);
 int do_final_script(void);
-int add_str(const char *p);
+int add_str(const char* p);
+const char* get_str(int id);
 int script_reload(void);
 int script_reload(void);
 
 
 extern char mapreg_txt[];
 extern char mapreg_txt[];

+ 0 - 2
src/txt-converter/char-converter.c

@@ -283,8 +283,6 @@ int convert_init(void)
 		fclose(fp);
 		fclose(fp);
 	}
 	}
 
 
-	//FIXME: CONVERT MAPREG HERE! (after enforcing MAPREGSQL for sql)
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 8 - 0
vcproj-6/map-server_sql.dsp

@@ -303,6 +303,14 @@ SOURCE=..\src\map\map.h
 # End Source File
 # End Source File
 # Begin Source File
 # Begin Source File
 
 
+SOURCE=..\src\map\mapreg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mapreg_sql.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\map\mercenary.c
 SOURCE=..\src\map\mercenary.c
 # End Source File
 # End Source File
 # Begin Source File
 # Begin Source File

+ 8 - 0
vcproj-6/map-server_txt.dsp

@@ -359,6 +359,14 @@ SOURCE=..\src\map\map.h
 # End Source File
 # End Source File
 # Begin Source File
 # Begin Source File
 
 
+SOURCE=..\src\map\mapreg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mapreg_txt.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\map\mercenary.h
 SOURCE=..\src\map\mercenary.h
 # End Source File
 # End Source File
 # Begin Source File
 # Begin Source File

+ 8 - 2
vcproj-7.1/map-server_sql.vcproj

@@ -22,7 +22,7 @@
 /wd4100"
 /wd4100"
 				Optimization="0"
 				Optimization="0"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;MAPREGSQL;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
 				MinimalRebuild="TRUE"
 				ExceptionHandling="FALSE"
 				ExceptionHandling="FALSE"
@@ -94,7 +94,7 @@
 				OptimizeForProcessor="2"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
 				OptimizeForWindowsApplication="TRUE"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;MAPREGSQL;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="TRUE"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
 				RuntimeLibrary="3"
 				DefaultCharIsUnsigned="FALSE"
 				DefaultCharIsUnsigned="FALSE"
@@ -226,6 +226,12 @@
 			<File
 			<File
 				RelativePath="..\src\map\map.h">
 				RelativePath="..\src\map\map.h">
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\map\mapreg.h">
+			</File>
+			<File
+				RelativePath="..\src\map\mapreg_sql.c">
+			</File>
 			<File
 			<File
 				RelativePath="..\src\map\mercenary.c">
 				RelativePath="..\src\map\mercenary.c">
 			</File>
 			</File>

+ 6 - 0
vcproj-7.1/map-server_txt.vcproj

@@ -226,6 +226,12 @@
 			<File
 			<File
 				RelativePath="..\src\map\map.h">
 				RelativePath="..\src\map\map.h">
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\map\mapreg.h">
+			</File>
+			<File
+				RelativePath="..\src\map\mapreg_txt.c">
+			</File>
 			<File
 			<File
 				RelativePath="..\src\map\mercenary.c">
 				RelativePath="..\src\map\mercenary.c">
 			</File>
 			</File>

+ 10 - 2
vcproj-8/map-server_sql.vcproj

@@ -41,7 +41,7 @@
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				Optimization="0"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;MAPREGSQL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
 				MinimalRebuild="true"
 				ExceptionHandling="0"
 				ExceptionHandling="0"
@@ -133,7 +133,7 @@
 				EnableFiberSafeOptimizations="true"
 				EnableFiberSafeOptimizations="true"
 				WholeProgramOptimization="true"
 				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;MAPREGSQL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="true"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				RuntimeLibrary="0"
 				DefaultCharIsUnsigned="false"
 				DefaultCharIsUnsigned="false"
@@ -441,6 +441,14 @@
 				RelativePath="..\src\map\map.h"
 				RelativePath="..\src\map\map.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\map\mapreg.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\map\mapreg_sql.c"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\src\map\mercenary.c"
 				RelativePath="..\src\map\mercenary.c"
 				>
 				>

+ 8 - 0
vcproj-8/map-server_txt.vcproj

@@ -300,6 +300,14 @@
 				RelativePath="..\src\map\map.h"
 				RelativePath="..\src\map\map.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\map\mapreg.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\map\mapreg_txt.c"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\src\map\mercenary.c"
 				RelativePath="..\src\map\mercenary.c"
 				>
 				>

+ 10 - 2
vcproj-9/map-server_sql.vcproj

@@ -42,7 +42,7 @@
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				Optimization="0"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;MAPREGSQL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
 				MinimalRebuild="true"
 				ExceptionHandling="0"
 				ExceptionHandling="0"
@@ -136,7 +136,7 @@
 				EnableFiberSafeOptimizations="true"
 				EnableFiberSafeOptimizations="true"
 				WholeProgramOptimization="true"
 				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;MAPREGSQL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="true"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				RuntimeLibrary="0"
 				DefaultCharIsUnsigned="false"
 				DefaultCharIsUnsigned="false"
@@ -446,6 +446,14 @@
 				RelativePath="..\src\map\map.h"
 				RelativePath="..\src\map\map.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\map\mapreg.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\map\mapreg_sql.c"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\src\map\mercenary.c"
 				RelativePath="..\src\map\mercenary.c"
 				>
 				>

+ 8 - 0
vcproj-9/map-server_txt.vcproj

@@ -305,6 +305,14 @@
 				RelativePath="..\src\map\map.h"
 				RelativePath="..\src\map\map.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\map\mapreg.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\map\mapreg_txt.c"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\src\map\mercenary.c"
 				RelativePath="..\src\map\mercenary.c"
 				>
 				>