summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
Diffstat (limited to 'src/char')
-rw-r--r--src/char/Makefile.in25
-rw-r--r--src/char/int_pet.c231
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)