diff options
Diffstat (limited to 'src/char')
-rw-r--r-- | src/char/Makefile.in | 25 | ||||
-rw-r--r-- | src/char/int_pet.c | 231 |
2 files changed, 172 insertions, 84 deletions
diff --git a/src/char/Makefile.in b/src/char/Makefile.in index 79ee3e18f..88a99c96c 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -36,6 +36,19 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \ LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \ scanctx.h scanner.h strbuf.h wincompat.h) +ifeq (@USE_LIBBACKTRACE@,yes) + LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace + LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \ + dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \ + simple.o sort.o state.o) + LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \ + backtrace-supported.h config.h filenames.h internal.h) +else + LIBBACKTRACE_D = + LIBBACKTRACE_OBJ = + LIBBACKTRACE_H = +endif + MT19937AR_D = $(THIRDPARTY_D)/mt19937ar MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o MT19937AR_H = $(MT19937AR_D)/mt19937ar.h @@ -51,7 +64,7 @@ CHAR_PH = HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) - CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC) + CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) $(SYSINFO_INC) else CHAR_SERVER_SQL_DEPENDS=needs_mysql endif @@ -90,7 +103,7 @@ help: Makefile: Makefile.in @$(MAKE) -C ../.. src/char/Makefile -$(SYSINFO_INC): $(CHAR_C) $(CHAR_PH) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) +$(SYSINFO_INC): $(CHAR_C) $(CHAR_PH) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) @echo " MAKE $@" @$(MAKE) -C ../.. sysinfo @@ -111,7 +124,7 @@ char-server: ../../char-server@EXEEXT@ ../../char-server@EXEEXT@: $(CHAR_SERVER_SQL_DEPENDS) Makefile @echo " LD $(notdir $@)" @$(CC) @STATIC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a \ - $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ + $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) @LIBS@ @MYSQL_LIBS@ # missing object files $(COMMON_D)/obj_all/common.a: @@ -130,10 +143,14 @@ $(LIBCONFIG_OBJ): @echo " MAKE $@" @$(MAKE) -C $(LIBCONFIG_D) +$(LIBBACKTRACE_OBJ): + @echo " MAKE $@" + @$(MAKE) -C $(LIBBACKTRACE_D) + .SECONDEXPANSION: # char object files -obj_sql/%.o: %.c $$(filter %.p.h, $(CHAR_PH)) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql +obj_sql/%.o: %.c $$(filter %.p.h, $(CHAR_PH)) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | obj_sql @echo " CC $<" @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< diff --git a/src/char/int_pet.c b/src/char/int_pet.c index 880de668d..176025f13 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -43,97 +43,161 @@ struct inter_pet_interface *inter_pet; /** * Saves a pet to the SQL database. * - * @remark - * In case of newly created pet, the pet ID is not updated to reflect the - * newly assigned ID. The caller must do so. + * Table structure: + * `pet` (`pet_id`, `class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, `intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`) + * + * @remark In case of newly created pet, the pet ID is not updated to reflect the newly assigned ID. The caller must do so. * * @param p The pet data to save. - * @return The ID of the saved pet. - * @retval 0 in case of errors. - */ + * @return The ID of the saved pet, or 0 in case of errors. + * + **/ static int inter_pet_tosql(const struct s_pet *p) { - //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`) - char esc_name[NAME_LENGTH*2+1];// escaped pet name - int pet_id = 0, hungry = 0, intimate = 0; - nullpo_ret(p); - SQL->EscapeStringLen(inter->sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); - hungry = cap_value(p->hungry, 0, 100); - intimate = cap_value(p->intimate, 0, 1000); - - if (p->pet_id == 0) { - // New pet. - if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` " - "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) " - "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, - p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed)) { - Sql_ShowDebug(inter->sql_handle); + struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle); + + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return 0; + } + + int pet_id = 0; + + if (p->pet_id == 0) { // New pet. + const char *query = "INSERT INTO `%s` " + "(`class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, " + "`intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) || + SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, &p->name, strnlen(p->name, sizeof(p->name))) || + SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed)) || + SQL_ERROR == SQL->StmtExecute(stmt)) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); return 0; } + pet_id = (int)SQL->LastInsertId(inter->sql_handle); - } else { - // Update pet. - if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d', `autofeed`='%d' WHERE `pet_id`='%d'", - pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, - p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed, p->pet_id)) { - Sql_ShowDebug(inter->sql_handle); + } else { // Update pet. + const char *query = "UPDATE `%s` SET " + "`class`=?, `name`=?, `account_id`=?, `char_id`=?, `level`=?, `egg_id`=?, `equip`=?, " + "`intimate`=?, `hungry`=?, `rename_flag`=?, `incubate`=?, `autofeed`=? " + "WHERE `pet_id`=?"; + + if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) || + SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, &p->name, strnlen(p->name, sizeof(p->name))) || + SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed)) || + SQL_ERROR == SQL->StmtBindParam(stmt, 12, SQLDT_INT32, &p->pet_id, sizeof(p->pet_id)) || + SQL_ERROR == SQL->StmtExecute(stmt)) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); return 0; } + pet_id = p->pet_id; } + SQL->StmtFree(stmt); + if (chr->show_save_log) ShowInfo("Pet saved %d - %s.\n", pet_id, p->name); return pet_id; } +/** + * Loads a pet's data from the SQL database. + * + * Table structure: + * `pet` (`pet_id`, `class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, `intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`) + * + * @param pet_id The pet's ID. + * @param p The pet data to save the SQL data in. + * @return Always 0. + * + **/ static int inter_pet_fromsql(int pet_id, struct s_pet *p) { - char* data; - size_t len; + nullpo_ret(p); + + struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle); + + if (stmt == NULL) { + SqlStmt_ShowDebug(stmt); + return 0; + } #ifdef NOISY ShowInfo("Loading pet (%d)...\n",pet_id); #endif - nullpo_ret(p); + memset(p, 0, sizeof(struct s_pet)); - //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) + const char *query = "SELECT " + "`class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, " + "`intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed` " + "FROM `%s` WHERE `pet_id`=?"; + + if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) || + SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &pet_id, sizeof(pet_id)) || + SQL_ERROR == SQL->StmtExecute(stmt) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_STRING, &p->name, sizeof(p->name), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate), NULL, NULL) || + SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed), NULL, NULL)) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return 0; + } - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`,`autofeed` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) - { - Sql_ShowDebug(inter->sql_handle); + if (SQL->StmtNumRows(stmt) < 1) { + ShowError("inter_pet_fromsql: Requested non-existant pet ID: %d\n", pet_id); + SQL->StmtFree(stmt); return 0; } - if( SQL_SUCCESS == SQL->NextRow(inter->sql_handle) ) - { - p->pet_id = pet_id; - SQL->GetData(inter->sql_handle, 1, &data, NULL); p->class_ = atoi(data); - SQL->GetData(inter->sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); - SQL->GetData(inter->sql_handle, 3, &data, NULL); p->account_id = atoi(data); - SQL->GetData(inter->sql_handle, 4, &data, NULL); p->char_id = atoi(data); - SQL->GetData(inter->sql_handle, 5, &data, NULL); p->level = atoi(data); - SQL->GetData(inter->sql_handle, 6, &data, NULL); p->egg_id = atoi(data); - SQL->GetData(inter->sql_handle, 7, &data, NULL); p->equip = atoi(data); - SQL->GetData(inter->sql_handle, 8, &data, NULL); p->intimate = atoi(data); - SQL->GetData(inter->sql_handle, 9, &data, NULL); p->hungry = atoi(data); - SQL->GetData(inter->sql_handle, 10, &data, NULL); p->rename_flag = atoi(data); - SQL->GetData(inter->sql_handle, 11, &data, NULL); p->incubate = atoi(data); - SQL->GetData(inter->sql_handle, 12, &data, NULL); p->autofeed = atoi(data); - - SQL->FreeResult(inter->sql_handle); - - p->hungry = cap_value(p->hungry, 0, 100); - p->intimate = cap_value(p->intimate, 0, 1000); - - if (chr->show_save_log) - ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name); + if (SQL_ERROR == SQL->StmtNextRow(stmt)) { + SqlStmt_ShowDebug(stmt); + SQL->StmtFree(stmt); + return 0; } + + SQL->StmtFree(stmt); + + if (chr->show_save_log) + ShowInfo("Pet loaded %d - %s.\n", pet_id, p->name); + return 0; } //---------------------------------------------- @@ -160,41 +224,48 @@ static int inter_pet_delete(int pet_id) return 0; } //------------------------------------------------------ + +/** + * Creates a new pet and inserts its data into the `pet` SQL table. + * + * @param account_id The pet's master's account ID. + * @param char_id The pet's master's char ID. + * @param pet_class The pet's class/monster ID. + * @param pet_lv The pet's level. + * @param pet_egg_id The pet's egg's item ID. + * @param pet_equip The pet's equipment's item ID. + * @param intimate The pet's intimacy value. + * @param hungry The pet's hunger value. + * @param rename_flag The pet's rename flag. + * @param incubate The pet's incubate state. + * @param pet_name The pet's name. + * @return The created pet's data struct, or NULL in case of errors. + * + **/ static struct s_pet *inter_pet_create(int account_id, int char_id, int pet_class, int pet_lv, int pet_egg_id, - int pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name) + int pet_equip, short intimate, short hungry, char rename_flag, + char incubate, const char *pet_name) { - nullpo_ret(pet_name); + nullpo_retr(NULL, pet_name); + memset(inter_pet->pt, 0, sizeof(struct s_pet)); safestrncpy(inter_pet->pt->name, pet_name, NAME_LENGTH); - if(incubate == 1) - inter_pet->pt->account_id = inter_pet->pt->char_id = 0; - else { - inter_pet->pt->account_id = account_id; - inter_pet->pt->char_id = char_id; - } + inter_pet->pt->account_id = (incubate == 1) ? 0 : account_id; + inter_pet->pt->char_id = (incubate == 1) ? 0 : char_id; inter_pet->pt->class_ = pet_class; inter_pet->pt->level = pet_lv; inter_pet->pt->egg_id = pet_egg_id; inter_pet->pt->equip = pet_equip; - inter_pet->pt->intimate = intimate; - inter_pet->pt->hungry = hungry; + inter_pet->pt->intimate = cap_value(intimate, PET_INTIMACY_NONE, PET_INTIMACY_MAX); + inter_pet->pt->hungry = cap_value(hungry, PET_HUNGER_STARVING, PET_HUNGER_STUFFED); inter_pet->pt->rename_flag = rename_flag; inter_pet->pt->incubate = incubate; + inter_pet->pt->pet_id = 0; // Signal NEW pet. - if(inter_pet->pt->hungry < 0) - inter_pet->pt->hungry = 0; - else if(inter_pet->pt->hungry > 100) - inter_pet->pt->hungry = 100; - if(inter_pet->pt->intimate < 0) - inter_pet->pt->intimate = 0; - else if(inter_pet->pt->intimate > 1000) - inter_pet->pt->intimate = 1000; - - inter_pet->pt->pet_id = 0; //Signal NEW pet. if ((inter_pet->pt->pet_id = inter_pet->tosql(inter_pet->pt)) != 0) return inter_pet->pt; - else //Failed... - return NULL; + + return NULL; } static struct s_pet *inter_pet_load(int account_id, int char_id, int pet_id) |