summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/ers.c2
-rw-r--r--src/config/const.h7
-rw-r--r--src/map/battle.c5
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/clif.c77
-rw-r--r--src/map/clif.h4
-rw-r--r--src/map/itemdb.c86
-rw-r--r--src/map/itemdb.h17
-rw-r--r--src/map/map.c2
-rw-r--r--src/map/packets.h8
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c13
-rw-r--r--src/map/script.h1
-rw-r--r--src/plugins/Makefile.in6
-rw-r--r--src/plugins/db2sql.c131
15 files changed, 308 insertions, 55 deletions
diff --git a/src/common/ers.c b/src/common/ers.c
index 27d9222ff..22269a51f 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -293,7 +293,7 @@ static void ers_obj_destroy(ERS self)
void ers_cache_size(ERS self, unsigned int new_size) {
struct ers_instance_t *instance = (struct ers_instance_t *)self;
- if (instance == NULL) {
+ if (instance == NULL) {//change as per piotrhalaczkiewicz comment
ShowError("ers_cache_size: NULL object, skipping...\n");
return;
}
diff --git a/src/config/const.h b/src/config/const.h
index 06a54a76f..f4a2821f8 100644
--- a/src/config/const.h
+++ b/src/config/const.h
@@ -111,6 +111,13 @@
#undef CONSOLE_INPUT
#endif
+#ifdef RENEWAL
+ #define ITEMDB_SQL_COLUMNS 24
+#else
+ #define ITEMDB_SQL_COLUMNS 22
+#endif
+
+
/**
* End of File
**/
diff --git a/src/map/battle.c b/src/map/battle.c
index f78e4f9a8..31fe502f6 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6375,7 +6375,7 @@ static const struct _battle_data {
{ "cashshop_show_points", &battle_config.cashshop_show_points, 0, 0, 1, },
{ "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, },
{ "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, },
-// BattleGround Settings
+ // BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
/**
@@ -6400,6 +6400,7 @@ static const struct _battle_data {
{ "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
{ "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
{ "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, },
+ { "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, },
};
#ifndef STATS_OPT_OUT
/**
@@ -6624,7 +6625,7 @@ void battle_adjust_conf(void) {
#ifndef CELL_NOSTACK
if (battle_config.cell_stack_limit != 1)
- ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
+ ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support (CELL_NOSTACK).\n");
#endif
}
diff --git a/src/map/battle.h b/src/map/battle.h
index 02d21ed69..7d41a02c5 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -449,6 +449,7 @@ struct Battle_Config {
int item_restricted_consumption_type;
int max_walk_path;
int item_enabled_npc;
+ int packet_obfuscation;
int gm_ignore_warpable_area;
diff --git a/src/map/clif.c b/src/map/clif.c
index 2f8ecd6a4..2feb6f4bf 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -632,6 +632,7 @@ void clif_authfail_fd(int fd, int type)
WFIFOB(fd,2) = type;
WFIFOSET(fd,packet_len(0x81));
set_eof(fd);
+
}
@@ -9288,6 +9289,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
WFIFOB(fd,2) = 3; // Rejected by server
WFIFOSET(fd,packet_len(0x6a));
set_eof(fd);
+
return;
}
@@ -9301,6 +9303,8 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
CREATE(sd, TBL_PC, 1);
sd->fd = fd;
+ sd->cryptKey = (( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
+
session[fd]->session_data = sd;
pc->setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd);
@@ -9819,6 +9823,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd)
(!battle_config.prevent_logout || DIFF_TICK(iTimer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{
set_eof(fd);
+
clif->disconnect_ack(sd, 0);
} else {
clif->disconnect_ack(sd, 1);
@@ -17436,6 +17441,47 @@ void clif_scriptclear(struct map_session_data *sd, int npcid) {
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
+ if( sd ) {
+ sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
+ return (cmd ^ ((sd->cryptKey >> 16) & 0x7FFF));
+ }
+ return (cmd ^ (((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) >> 16) & 0x7FFF));
+}
+unsigned short clif_parse_cmd_normal ( int fd, struct map_session_data *sd ) {
+ unsigned short cmd = RFIFOW(fd,0);
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0)
+ return 0;
+
+ return cmd;
+}
+unsigned short clif_parse_cmd_optional ( int fd, struct map_session_data *sd ) {
+ unsigned short cmd = RFIFOW(fd,0);
+
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) {
+ cmd = clif->decrypt_cmd( cmd, sd );
+ if( cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
+ return 0;
+ RFIFOW(fd, 0) = cmd;
+ }
+
+ return cmd;
+}
+unsigned short clif_parse_cmd_decrypt ( int fd, struct map_session_data *sd ) {
+ unsigned short cmd = RFIFOW(fd,0);
+
+ cmd = clif->decrypt_cmd( cmd, sd );
+
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
+ return 0;
+
+ RFIFOW(fd, 0) = cmd;
+
+ return cmd;
+}
/*==========================================
* Main client packet processing function
@@ -17479,20 +17525,18 @@ int clif_parse(int fd) {
if (RFIFOREST(fd) < 2)
return 0;
- cmd = RFIFOW(fd,0);
-
- // filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) {
- ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd);
+ if( !( cmd = clif->parse_cmd(fd,sd) ) ) {
+ ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", RFIFOW(fd,0), RFIFOREST(fd), fd);
#ifdef DUMP_INVALID_PACKET
ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
#endif
set_eof(fd);
return 0;
}
+
// determine real packet length
- packet_len = packet_db[cmd].len;
- if (packet_len == -1) { // variable-length packet
+ if ( ( packet_len = packet_db[cmd].len ) == -1) { // variable-length packet
+
if (RFIFOREST(fd) < 4)
return 0;
@@ -17503,9 +17547,11 @@ int clif_parse(int fd) {
ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
#endif
set_eof(fd);
+
return 0;
}
}
+
if ((int)RFIFOREST(fd) < packet_len)
return 0; // not enough data received to form the packet
@@ -17598,14 +17644,29 @@ void packetdb_loaddb(void) {
memset(packet_db,0,sizeof(packet_db));
#define packet(id, size, ...) packetdb_addpacket(id, size, ##__VA_ARGS__, 0xFFFF)
+ #define packetKeys(a,b,c) { clif->cryptKey[0] = a; clif->cryptKey[1] = b; clif->cryptKey[2] = c; }
#include "packets.h" /* load structure data */
#undef packet
+ #undef packetKeys
}
void clif_bc_ready(void) {
if( battle_config.display_status_timers )
clif->status_change = clif_status_change;
else
clif->status_change = clif_status_change_notick;
+
+ switch( battle_config.packet_obfuscation ) {
+ case 0:
+ clif->parse_cmd = clif_parse_cmd_normal;
+ break;
+ default:
+ case 1:
+ clif->parse_cmd = clif_parse_cmd_optional;
+ break;
+ case 2:
+ clif->parse_cmd = clif_parse_cmd_decrypt;
+ break;
+ }
}
/*==========================================
*
@@ -17689,6 +17750,8 @@ void clif_defaults(void) {
clif->send = clif_send;
clif->send_sub = clif_send_sub;
clif->parse = clif_parse;
+ clif->parse_cmd = clif_parse_cmd_optional;
+ clif->decrypt_cmd = clif_decrypt_cmd;
/* auth */
clif->authok = clif_authok;
clif->authrefuse = clif_authrefuse;
diff --git a/src/map/clif.h b/src/map/clif.h
index b447687ea..6e1fa81d3 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -462,6 +462,8 @@ struct clif_interface {
struct hCSData **data[CASHSHOP_TAB_MAX];
unsigned int item_count[CASHSHOP_TAB_MAX];
} cs;
+ /* */
+ unsigned int cryptKey[3];
/* core */
int (*init) (void);
void (*final) (void);
@@ -472,6 +474,8 @@ struct clif_interface {
int (*send) (const void* buf, int len, struct block_list* bl, enum send_target type);
int (*send_sub) (struct block_list *bl, va_list ap);
int (*parse) (int fd);
+ unsigned short (*parse_cmd) ( int fd, struct map_session_data *sd );
+ unsigned short (*decrypt_cmd) ( int cmd, struct map_session_data *sd );
/* auth */
void (*authok) (struct map_session_data *sd);
void (*authrefuse) (int fd, uint8 error_code);
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index cb845111d..859b19aac 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -296,8 +296,7 @@ static struct item_data* create_item_data(int nameid)
/*==========================================
* Loads (and creates if not found) an item from the db.
*------------------------------------------*/
-struct item_data* itemdb_load(int nameid)
-{
+struct item_data* itemdb_load(int nameid) {
struct item_data *id;
if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
@@ -967,7 +966,7 @@ void itemdb_re_split_atoi(char *str, int *atk, int *matk) {
/*==========================================
* processes one itemdb entry
*------------------------------------------*/
-static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) {
+int itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) {
/*
+----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
@@ -977,12 +976,12 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
*/
int nameid;
struct item_data* id;
+ unsigned char offset = 0;
nameid = atoi(str[0]);
- if( nameid <= 0 )
- {
+ if( nameid <= 0 ) {
ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source);
- return false;
+ return 0;
}
//ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View
@@ -1030,39 +1029,47 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
id->weight = atoi(str[6]);
#ifdef RENEWAL
- itemdb_re_split_atoi(str[7],&id->atk,&id->matk);
+ if( iMap->db_use_sqldbs ) {
+ id->atk = atoi(str[7]);
+ id->matk = atoi(str[8]);
+ offset += 1;
+ } else
+ itemdb_re_split_atoi(str[7],&id->atk,&id->matk);
#else
id->atk = atoi(str[7]);
#endif
- id->def = atoi(str[8]);
- id->range = atoi(str[9]);
- id->slot = atoi(str[10]);
+ id->def = atoi(str[8+offset]);
+ id->range = atoi(str[9+offset]);
+ id->slot = atoi(str[10+offset]);
- if (id->slot > MAX_SLOTS)
- {
+ if (id->slot > MAX_SLOTS) {
ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS);
id->slot = MAX_SLOTS;
}
- itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0));
- id->class_upper = atoi(str[12]);
- id->sex = atoi(str[13]);
- id->equip = atoi(str[14]);
+ itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11+offset],NULL,0));
+ id->class_upper = atoi(str[12+offset]);
+ id->sex = atoi(str[13+offset]);
+ id->equip = atoi(str[14+offset]);
- if (!id->equip && itemdb_isequip2(id))
- {
+ if (!id->equip && itemdb_isequip2(id)) {
ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname);
id->type = IT_ETC;
}
- id->wlv = cap_value(atoi(str[15]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
+ id->wlv = cap_value(atoi(str[15+offset]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
#ifdef RENEWAL
- itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax);
+ if( iMap->db_use_sqldbs ) {
+ id->elv = atoi(str[16+offset]);
+ id->elvmax = atoi(str[17+offset]);
+ offset += 1;
+ } else
+ itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax);
#else
id->elv = atoi(str[16]);
#endif
- id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this
- id->look = atoi(str[18]);
+ id->flag.no_refine = atoi(str[17+offset]) ? 0 : 1; //FIXME: verify this
+ id->look = atoi(str[18+offset]);
id->flag.available = 1;
id->view_id = 0;
@@ -1081,14 +1088,14 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
id->unequip_script = NULL;
}
- if (*str[19])
- id->script = parse_script(str[19], source, line, scriptopt);
- if (*str[20])
- id->equip_script = parse_script(str[20], source, line, scriptopt);
- if (*str[21])
- id->unequip_script = parse_script(str[21], source, line, scriptopt);
+ if (*str[19+offset])
+ id->script = parse_script(str[19+offset], source, line, scriptopt);
+ if (*str[20+offset])
+ id->equip_script = parse_script(str[20+offset], source, line, scriptopt);
+ if (*str[21+offset])
+ id->unequip_script = parse_script(str[21+offset], source, line, scriptopt);
- return true;
+ return id->nameid;
}
/*==========================================
@@ -1205,7 +1212,7 @@ static int itemdb_readdb(void)
}
}
- if (!itemdb_parse_dbrow(str, path, lines, 0))
+ if (!itemdb->parse_dbrow(str, path, lines, 0))
continue;
count++;
@@ -1218,7 +1225,6 @@ static int itemdb_readdb(void)
return 0;
}
-
/*======================================
* item_db table reading
*======================================*/
@@ -1234,7 +1240,7 @@ static int itemdb_read_sqldb(void) {
int fi;
for( fi = 0; fi < ARRAYLENGTH(item_db_name); ++fi ) {
- uint32 lines = 0, count = 0;
+ uint32 count = 0;
// retrieve all rows from the item database
if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) {
@@ -1244,17 +1250,16 @@ static int itemdb_read_sqldb(void) {
// process rows one by one
while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) {// wrap the result into a TXT-compatible format
- char* str[22];
+ char* str[ITEMDB_SQL_COLUMNS];
char* dummy = "";
int i;
- ++lines;
- for( i = 0; i < 22; ++i ) {
+ for( i = 0; i < ITEMDB_SQL_COLUMNS; ++i ) {
SQL->GetData(mmysql_handle, i, &str[i], NULL);
if( str[i] == NULL )
str[i] = dummy; // get rid of NULL columns
}
- if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS))
+ if (!itemdb->parse_dbrow(str, item_db_name[fi], -(atoi(str[0])), SCRIPT_IGNORE_EXTERNAL_BRACKETS))
continue;
++count;
}
@@ -1471,3 +1476,12 @@ int do_init_itemdb(void) {
return 0;
}
+/* incomplete */
+void itemdb_defaults(void) {
+ itemdb = &itemdb_s;
+
+ itemdb->reload = itemdb_reload;//incomplet=e
+ /* */
+ itemdb->parse_dbrow = itemdb_parse_dbrow;
+ itemdb->exists = itemdb_exists;//incomplete
+}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index ea478d135..44b455d80 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -1,5 +1,6 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#ifndef _ITEMDB_H_
#define _ITEMDB_H_
@@ -239,4 +240,16 @@ void itemdb_reload(void);
void do_final_itemdb(void);
int do_init_itemdb(void);
+/* incomplete */
+struct itemdb_interface {
+ void (*reload) (void);
+ /* */
+ int (*parse_dbrow) (char** str, const char* source, int line, int scriptopt);
+ struct item_data* (*exists) (int nameid);
+} itemdb_s;
+
+struct itemdb_interface *itemdb;
+
+void itemdb_defaults(void);
+
#endif /* _ITEMDB_H_ */
diff --git a/src/map/map.c b/src/map/map.c
index 510f36109..84b4f6bd2 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -5237,6 +5237,7 @@ void map_hp_symbols(void) {
HPM->share(guild,"guild");
HPM->share(homun,"homun");
HPM->share(ircbot,"ircbot");
+ HPM->share(itemdb,"itemdb");
HPM->share(logs,"logs");
HPM->share(script,"script");
HPM->share(searchstore,"searchstore");
@@ -5266,6 +5267,7 @@ void load_defaults(void) {
homunculus_defaults();
instance_defaults();
ircbot_defaults();
+ itemdb_defaults();
log_defaults();
npc_defaults();
script_defaults();
diff --git a/src/map/packets.h b/src/map/packets.h
index aada5d53f..244f19ed8 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -10,6 +10,10 @@
#define packet(a,b,...)
#endif
+#ifndef packetKeys
+ #define packetKeys(a,b,c)
+#endif
+
/*
* packet syntax
* - packet(packet_id,length)
@@ -2017,6 +2021,8 @@ packet(0x020d,-1);
packet(0x08E5,41,clif->pPartyBookingRegisterReq,2,4);
packet(0x08d2,10);
packet(0x0916,26,clif->pGuildInvite2,2);
+ packetKeys(0x1540e48,0x13041224,0x31247924);
+
#endif
#ifndef PACKETVER_RE
@@ -2058,6 +2064,7 @@ packet(0x020d,-1);
//2012-07-16aRagExe (special thanks to Yommy!)
#if PACKETVER >= 20120716
packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packetKeys(0x76052205, 0x22052205, 0x22052205);
#endif
//2013-03-20Ragexe (Judas + Yommy)
@@ -2092,6 +2099,7 @@ packet(0x020d,-1);
packet(0x086F,26,clif->pFriendsListAdd,2);
packet(0x093F,5,clif->pHomMenu,2,4);
packet(0x0947,36,clif->pStoragePassword,0);
+ packetKeys(0x3F094C49, 0x55F86C1E, 0x58AA359A);
// Shuffle End
// New Packets
diff --git a/src/map/pc.h b/src/map/pc.h
index cd2a45a6b..5c585af1c 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -497,6 +497,9 @@ struct map_session_data {
int *queues;
unsigned int queues_count;
+ /* Made Possible Thanks to Yommy~! */
+ unsigned int cryptKey;
+
// temporary debugging of bug #3504
const char* delunit_prevfile;
int delunit_prevline;
diff --git a/src/map/script.c b/src/map/script.c
index 26d64726c..60f741d6c 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2045,7 +2045,11 @@ void script_error(const char* src, const char* file, int start_line, const char*
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "\a\n");
- StrBuf->Printf(&buf, "script error on %s line %d\n", file, line);
+ if( line >= 0 )
+ StrBuf->Printf(&buf, "script error on %s line %d\n", file, line);
+ else
+ StrBuf->Printf(&buf, "script error on %s item ID %d\n", file, -line);
+
StrBuf->Printf(&buf, " %s\n", error_msg);
for(j = 0; j < 5; j++ ) {
script_print_line(&buf, linestart[j], NULL, line + j - 5);
@@ -10176,10 +10180,8 @@ BUILDIN(warpwaitingpc)
/// Detaches a character from a script.
///
/// @param st Script state to detach the character from.
-static void script_detach_rid(struct script_state* st)
-{
- if(st->rid)
- {
+void script_detach_rid(struct script_state* st) {
+ if(st->rid) {
script_detach_state(st, false);
st->rid = 0;
}
@@ -17864,6 +17866,7 @@ void script_defaults(void) {
script->conv_num = conv_num;
script->conv_str = conv_str;
script->rid2sd = script_rid2sd;
+ script->detach_rid = script_detach_rid;
script->push_val = push_val;
script->get_val = get_val;
script->get_val2 = get_val2;
diff --git a/src/map/script.h b/src/map/script.h
index 96fcdc23a..92a083556 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -361,6 +361,7 @@ struct script_interface {
int (*conv_num) (struct script_state *st,struct script_data *data);
const char* (*conv_str) (struct script_state *st,struct script_data *data);
TBL_PC *(*rid2sd) (struct script_state *st);
+ void (*detach_rid) (struct script_state* st);
struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int val, struct DBMap** ref);
void (*get_val) (struct script_state* st, struct script_data* data);
void* (*get_val2) (struct script_state* st, int uid, struct DBMap** ref);
diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in
index 71b743dca..3c80fa0e1 100644
--- a/src/plugins/Makefile.in
+++ b/src/plugins/Makefile.in
@@ -1,17 +1,19 @@
COMMON_H = ../common/HPMi.h ../common/cbasetypes.h
-PLUGINS = sample
+PLUGINS = sample db2sql
@SET_MAKE@
#####################################################################
-.PHONY : all $(PLUGINS) sample clean help
+.PHONY : all $(PLUGINS) sample db2sql clean help
all: $(PLUGINS)
sample: sample@DLLEXT@
+db2sql: db2sql@DLLEXT@
+
clean:
@echo " CLEAN plugins"
@rm -rf *.o
diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c
new file mode 100644
index 000000000..e5630ee2d
--- /dev/null
+++ b/src/plugins/db2sql.c
@@ -0,0 +1,131 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../config/core.h"
+#include "../common/HPMi.h"
+#include "../common/strlib.h"
+#include "../common/SQL.h"
+#include "../common/timer.h"
+#include "../map/clif.h"
+#include "../map/pc.h"
+#include "../map/map.h"
+#include "../map/itemdb.h"
+
+
+HPExport struct hplugin_info pinfo = {
+ "DB2SQL", // Plugin name
+ SERVER_TYPE_MAP,// Which server types this plugin works with?
+ "0.1", // Plugin version
+ HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
+};
+
+SqlStmt* stmt;
+
+int (*parse_dbrow)(char** str, const char* source, int line, int scriptopt);
+
+char* trimbraces(char* str) {
+ size_t start;
+ size_t end;
+
+ if( str == NULL )
+ return str;
+
+ for( start = 0; str[start] && str[start] == '{'; ++start )
+ ;
+ for( end = strlen(str); start < end && str[end-1] && (str[end-1] == '}' || str[end-1] == '\n'); --end )
+ ;
+ if( start == end )
+ *str = '\0';
+ else {
+ str[end] = '\0';
+ memmove(str,str+start,end-start+1);
+ trim(str);
+ }
+ return str;
+}
+int db2sql(char** str, const char* source, int line, int scriptopt) {
+ struct item_data *it = NULL;
+ unsigned char offset = 0;
+#ifdef RENEWAL
+ if( iMap->db_use_sqldbs ) offset = 1;
+#endif
+ if( (it = itemdb->exists(parse_dbrow(str,source,line,scriptopt))) ) {
+ /* renewal has the 'matk' and 'equip_level' is now 'equip_level_min', and there is a new 'equip_level_max' field */
+#ifdef RENEWAL
+ if( SQL_SUCCESS != SQL->StmtPrepare(stmt, "REPLACE INTO `%s` (`id`,`name_english`,`name_japanese`,`type`,`price_buy`,`price_sell`,`weight`,`atk`,`matk`,`defence`,`range`,`slots`,`equip_jobs`,`equip_upper`,`equip_genders`,`equip_locations`,`weapon_level`,`equip_level_min`,`equip_level_max`,`refineable`,`view`,`script`,`equip_script`,`unequip_script`) VALUES ('%u',?,?,'%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u',?,?,?)",iMap->item_db_re_db,
+ it->nameid,it->type,it->value_buy,it->value_sell,it->weight,it->atk,it->matk,it->def,it->range,it->slot,(unsigned int)strtoul(str[11+offset],NULL,0),atoi(str[12+offset]),atoi(str[13+offset]),atoi(str[14+offset]),it->wlv,it->elv,it->elvmax,atoi(str[17+offset]),it->look) )
+#else
+ if( SQL_SUCCESS != SQL->StmtPrepare(stmt, "REPLACE INTO `%s` (`id`,`name_english`,`name_japanese`,`type`,`price_buy`,`price_sell`,`weight`,`atk`,`defence`,`range`,`slots`,`equip_jobs`,`equip_upper`,`equip_genders`,`equip_locations`,`weapon_level`,`equip_level`,`refineable`,`view`,`script`,`equip_script`,`unequip_script`) VALUES ('%u',?,?,'%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u','%u',?,?,?)",iMap->item_db_db,
+ it->nameid,it->type,it->value_buy,it->value_sell,it->weight,it->atk,it->def,it->range,it->slot,(unsigned int)strtoul(str[11],NULL,0),atoi(str[12]),atoi(str[13]),atoi(str[14]),it->wlv,it->elv,atoi(str[17]),it->look) )
+#endif
+ SqlStmt_ShowDebug(stmt);
+ else {
+ if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, it->name, strlen(it->name)) )
+ SqlStmt_ShowDebug(stmt);
+ else {
+ if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, it->jname, strlen(it->jname)) )
+ SqlStmt_ShowDebug(stmt);
+ else {
+ #ifdef RENEWAL
+ if( iMap->db_use_sqldbs ) offset += 1;
+ #endif
+ if( it->script ) trimbraces(str[19+offset]);
+ if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 2, SQLDT_STRING, it->script?str[19+offset]:"", it->script?strlen(str[19+offset]):0) )
+ SqlStmt_ShowDebug(stmt);
+ else {
+ if( it->equip_script ) trimbraces(str[20+offset]);
+ if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 3, SQLDT_STRING, it->equip_script?str[20+offset]:"", it->equip_script?strlen(str[20+offset]):0) )
+ SqlStmt_ShowDebug(stmt);
+ else {
+ if( it->unequip_script ) trimbraces(str[21+offset]);
+ if ( SQL_SUCCESS != SQL->StmtBindParam(stmt, 4, SQLDT_STRING, it->unequip_script?str[21+offset]:"", it->unequip_script?strlen(str[21+offset]):0) )
+ SqlStmt_ShowDebug(stmt);
+ else {
+ if( SQL_SUCCESS != SQL->StmtExecute(stmt) )
+ SqlStmt_ShowDebug(stmt);
+ }
+ }
+ }
+ }
+ }
+ }
+ return it->nameid;
+ }
+ return 0;
+}
+
+CPCMD(db2sql) {
+
+ stmt = SQL->StmtMalloc(mysql_handle);
+ if( stmt == NULL ) {
+ SqlStmt_ShowDebug(stmt);
+ return;
+ }
+
+ /* link */
+ parse_dbrow = itemdb->parse_dbrow;
+ itemdb->parse_dbrow = db2sql;
+
+ /* empty table */
+ if ( SQL_ERROR == SQL->Query(mysql_handle, "DELETE FROM `%s`", iMap->item_db_db) )
+ Sql_ShowDebug(mysql_handle);
+ else {
+ itemdb->reload();
+ }
+ /* unlink */
+ itemdb->parse_dbrow = parse_dbrow;
+
+ SQL->StmtFree(stmt);
+}
+
+HPExport void plugin_init (void) {
+ SQL = GET_SYMBOL("SQL");
+ itemdb = GET_SYMBOL("itemdb");
+ iMap = GET_SYMBOL("iMap");
+ strlib = GET_SYMBOL("strlib");
+
+ HPMi->addCPCommand("server:tools:db2sql",CPCMD_A(db2sql));
+} \ No newline at end of file