Skip to content

Commit

Permalink
Merge pull request #1092 from HerculesWS/GD_GUILD_STORAGE
Browse files Browse the repository at this point in the history
Guild Storage Skill
  • Loading branch information
MishimaHaruna authored Aug 5, 2021
2 parents df9651b + 8867d3b commit 822554f
Show file tree
Hide file tree
Showing 31 changed files with 774 additions and 362 deletions.
4 changes: 3 additions & 1 deletion conf/messages.conf
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,9 @@
// 334: Thirty-Four Castles
334: Total Domination

//335-342 FREE
335: Your guild doesn't have storage!
336: You're not authorized to open your guild storage!
//337-342 FREE

// Templates for @who output
343: Name: %s
Expand Down
1 change: 1 addition & 0 deletions db/guild_skill_tree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
10012,1,10011,1,0,0,0,0,0,0,0,0 //GD_RESTORE#Restoration#
10013,1,10000,1,10002,1,10004,5,10010,1,10011,1 //GD_EMERGENCYCALL#Urgent Call#
10014,1,0,0,0,0,0,0,0,0,0,0 //GD_DEVELOPMENT#Permanent Development#
10016,5,0,0,0,0,0,0,0,0,0,0 //GD_GUILD_STORAGE#Guild Storage Expansion#
20 changes: 20 additions & 0 deletions db/pre-re/skill_db.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39501,4 +39501,24 @@ skill_db: (
}
NumberOfHits: 0
},
//{
// Id: 10015
// Name: "GD_ITEMEMERGENCYCALL"
// Description: "Unknown Skill"
// MaxLevel: 1
// SkillInfo: {
// Guild: true
// }
// NumberOfHits: 0
//},
{
Id: 10016
Name: "GD_GUILD_STORAGE"
Description: "Guild Storage Expansion"
MaxLevel: 5
SkillInfo: {
Guild: true
}
NumberOfHits: 0
},
)
20 changes: 20 additions & 0 deletions db/re/skill_db.conf
Original file line number Diff line number Diff line change
Expand Up @@ -40737,4 +40737,24 @@ conflicting with SJ_LIGHTOFMOON
}
NumberOfHits: 0
},
//{
// Id: 10015
// Name: "GD_ITEMEMERGENCYCALL"
// Description: "Unknown Skill"
// MaxLevel: 1
// SkillInfo: {
// Guild: true
// }
// NumberOfHits: 0
//},
{
Id: 10016
Name: "GD_GUILD_STORAGE"
Description: "Guild Storage Expansion"
MaxLevel: 5
SkillInfo: {
Guild: true
}
NumberOfHits: 0
},
)
17 changes: 8 additions & 9 deletions doc/script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6083,15 +6083,14 @@ Example:

This function works the same as openstorage() but will open a guild
storage window instead for the guild storage of the guild the invoking
character belongs to. This is a function because it returns a value - 0 if
the guild storage was opened successfully and 1 if it wasn't. (Notice,
it's a ZERO upon success.)
Since guild storage is only accessible to one character at one time, it
may fail if another character is accessing the guild storage at the same
time.

This will also fail and return 2 if the attached character does not belong
to any guild.
character belongs to.
Expected return values:

0 Success (Opens storage)
1 Storage is already open
2 Player has no guild / guild information hasn't arrived yet
3 Player's guild doesn't have GD_GUILD_STORAGE (only if OFFICIAL_GUILD_STORAGE is enabled - automatically enabled on PACKETVER >= 20131223)
4 Player doesn't have permission to use storage (only on PACKETVER >= 20140205)

The mapflag 'nogstorage' when set to type '2' (or 3), will not open the
guild storage. Unless the character group has the permission 'bypass_nostorage'.
Expand Down
4 changes: 3 additions & 1 deletion sql-files/main.sql
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ CREATE TABLE IF NOT EXISTS `guild` (
`guild_lv` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`connect_member` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`max_member` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`max_storage` SMALLINT UNSIGNED NOT NULL DEFAULT '0',
`average_lv` SMALLINT UNSIGNED NOT NULL DEFAULT '1',
`exp` BIGINT UNSIGNED NOT NULL DEFAULT '0',
`next_exp` INT UNSIGNED NOT NULL DEFAULT '0',
Expand Down Expand Up @@ -486,7 +487,7 @@ CREATE TABLE IF NOT EXISTS `guild_position` (
`guild_id` INT UNSIGNED NOT NULL DEFAULT '0',
`position` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`name` VARCHAR(24) NOT NULL DEFAULT '',
`mode` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`mode` SMALLINT UNSIGNED NOT NULL DEFAULT '0',
`exp_mode` TINYINT UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`guild_id`,`position`)
) ENGINE=MyISAM;
Expand Down Expand Up @@ -953,6 +954,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1588301040); -- 2020-05-0
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1589145060); -- 2020-05-10--23-11.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1597467600); -- 2020-08-15--13-00.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1612286353); -- 2021-05-03--10-19.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1628121360); -- 2021-08-04--23-56.sql

--
-- Table structure for table `storage`
Expand Down
4 changes: 4 additions & 0 deletions sql-files/upgrades/2021-08-04--23-56.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#1628121360
ALTER TABLE `guild_position` CHANGE `mode` `mode` SMALLINT UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `guild` ADD `max_storage` SMALLINT UNSIGNED NOT NULL DEFAULT '0' AFTER `max_member`;
INSERT INTO `sql_updates` (`timestamp`) VALUES (1628121360);
1 change: 1 addition & 0 deletions sql-files/upgrades/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@
2020-05-10--23-11.sql
2020-08-15--13-00.sql
2021-05-03--10-19.sql
2021-08-04--23-56.sql
85 changes: 45 additions & 40 deletions src/char/char.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,15 +441,15 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)

//map inventory data
if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) ) {
if (!chr->memitemdata_to_sql(p->inventory, p->char_id, TABLE_INVENTORY))
if (!chr->memitemdata_to_sql(p->inventory, -1, p->char_id, TABLE_INVENTORY))
strcat(save_status, " inventory");
else
errors++;
}

//map cart data
if( memcmp(p->cart, cp->cart, sizeof(p->cart)) ) {
if (!chr->memitemdata_to_sql(p->cart, p->char_id, TABLE_CART))
if (!chr->memitemdata_to_sql(p->cart, -1, p->char_id, TABLE_CART))
strcat(save_status, " cart");
else
errors++;
Expand Down Expand Up @@ -746,12 +746,13 @@ static int char_getitemdata_from_sql(struct item *items, int max, int guid, enum
StringBuf buf;
struct item item = { 0 }; // temp storage variable

nullpo_retr(-1, items);
if (max > 0)
nullpo_retr(-1, items);
Assert_retr(-1, guid > 0);
Assert_retr(-1, max > 0);

// Initialize the array.
memset(items, 0x0, sizeof(struct item) * max);
if (max > 0)
memset(items, 0x0, sizeof(struct item) * max);

switch (table) {
case TABLE_INVENTORY:
Expand Down Expand Up @@ -839,84 +840,87 @@ static int char_getitemdata_from_sql(struct item *items, int max, int guid, enum

/**
* Saves an array of 'item' entries into the specified table. [Smokexyz/Hercules]
* @param[in] items The items array.
* @param[in] guid The character/account/guild ID (depending on table).
* @param[in] tableswitch The type of table (@see enum inventory_table_type).
* @param[in] items The items array.
* @param[in] current_size The current size of the items array (-1 to automatically use the maximum size, for fixed size inventories).
* @param[in] guid The character/account/guild ID (depending on table).
* @param[in] table The type of table (@see enum inventory_table_type).
* @retval -1 in case of failure, or number of changes made within the table.
*/
static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum inventory_table_type table)
static int char_memitemdata_to_sql(const struct item *p_items, int current_size, int guid, enum inventory_table_type table)
{
StringBuf buf;
int i = 0, j = 0;
const char *tablename = NULL;
const char *selectoption = NULL;
bool has_favorite = false;
struct item *cp_items = NULL; // temp item storage variable
bool *matched_p = NULL;
int total_updates = 0, total_deletes = 0, total_inserts = 0, total_changes = 0;
int item_count = 0, db_max = 0;

nullpo_ret(p_items);
int max_size = 0;
int db_size = 0;

switch (table) {
case TABLE_INVENTORY:
tablename = inventory_db;
selectoption = "char_id";
has_favorite = true;
item_count = MAX_INVENTORY;
max_size = MAX_INVENTORY;
break;
case TABLE_CART:
tablename = cart_db;
selectoption = "char_id";
item_count = MAX_CART;
max_size = MAX_CART;
break;
case TABLE_GUILD_STORAGE:
tablename = guild_storage_db;
selectoption = "guild_id";
item_count = MAX_GUILD_STORAGE;
max_size = MAX_GUILD_STORAGE;
break;
case TABLE_STORAGE:
default:
ShowError("Invalid table type %d!\n", (int) table);
Assert_retr(-1, table);
return -1;
}
if (current_size == -1)
current_size = max_size;

bool *matched_p = NULL;
if (current_size > 0) {
nullpo_ret(p_items);

cp_items = aCalloc(item_count, sizeof(struct item));
matched_p = aCalloc(item_count, sizeof(bool));
matched_p = aCalloc(current_size, sizeof(bool));
}

StringBuf buf;
StrBuf->Init(&buf);

/**
* If the storage table is not empty, check for items and replace or delete where needed.
*/
if ((db_max = chr->getitemdata_from_sql(cp_items, item_count, guid, table)) > 0) {
int *deletes = aCalloc(db_max, sizeof(struct item));
struct item *cp_items = aCalloc(max_size, sizeof(struct item));
if ((db_size = chr->getitemdata_from_sql(cp_items, max_size, guid, table)) > 0) {
int *deletes = aCalloc(db_size, sizeof(struct item));

for (i = 0; i < db_max; i++) {
struct item *cp_it = &cp_items[i];
for (int i = 0; i < db_size; i++) {
const struct item *cp_it = &cp_items[i];

ARR_FIND(0, item_count, j,
int j = 0;
ARR_FIND(0, current_size, j,
matched_p[j] != true
&& p_items[j].nameid != 0
&& cp_it->nameid == p_items[j].nameid
&& cp_it->unique_id == p_items[j].unique_id
&& memcmp(p_items[j].card, cp_it->card, sizeof(int) * MAX_SLOTS) == 0
&& memcmp(p_items[j].option, cp_it->option, 5 * MAX_ITEM_OPTIONS) == 0);

if (j < item_count) { // Item found.
if (j < current_size) { // Item found.
matched_p[j] = true; // Mark the item as matched.

// If the amount has changed, set for replacement with current item properties.
if (memcmp(cp_it, &p_items[j], sizeof(struct item)) != 0) {
int k = 0;

if (total_updates == 0) {
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "REPLACE INTO `%s` (`id`, `%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", tablename, selectoption);
for (k = 0; k < MAX_SLOTS; k++)
for (int k = 0; k < MAX_SLOTS; k++)
StrBuf->Printf(&buf, ", `card%d`", k);
for (k = 0; k < MAX_ITEM_OPTIONS; k++)
for (int k = 0; k < MAX_ITEM_OPTIONS; k++)
StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", k, k);
StrBuf->AppendStr(&buf, ", `expire_time`, `bound`, `unique_id`");
if (has_favorite)
Expand All @@ -928,9 +932,9 @@ static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum in

StrBuf->Printf(&buf, "%s('%d', '%d', '%d', '%d', '%u', '%d', '%d', '%d'",
total_updates > 0 ? ", " : "", cp_it->id, guid, p_items[j].nameid, p_items[j].amount, p_items[j].equip, p_items[j].identify, p_items[j].refine, p_items[j].attribute);
for (k = 0; k < MAX_SLOTS; k++)
for (int k = 0; k < MAX_SLOTS; k++)
StrBuf->Printf(&buf, ", '%d'", p_items[j].card[k]);
for (k = 0; k < MAX_ITEM_OPTIONS; ++k)
for (int k = 0; k < MAX_ITEM_OPTIONS; ++k)
StrBuf->Printf(&buf, ", '%d', '%d'", p_items[j].option[k].index, p_items[j].option[k].value);
StrBuf->Printf(&buf, ", '%u', '%d', '%"PRIu64"'", p_items[j].expire_time, p_items[j].bound, p_items[j].unique_id);
if (has_favorite)
Expand All @@ -954,7 +958,7 @@ static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum in
if (total_deletes > 0) {
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "DELETE FROM `%s` WHERE `id` IN (", tablename);
for (i = 0; i < total_deletes; i++)
for (int i = 0; i < total_deletes; i++)
StrBuf->Printf(&buf, "%s'%d'", i == 0 ? "" : ", ", deletes[i]);

StrBuf->AppendStr(&buf, ");");
Expand All @@ -969,7 +973,7 @@ static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum in
/**
* Check for new items and add if required.
*/
for (i = 0; i < item_count; i++) {
for (int i = 0; i < current_size; i++) {
const struct item *p_it = &p_items[i];

if (matched_p[i] || p_it->nameid == 0)
Expand All @@ -978,9 +982,9 @@ static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum in
if (total_inserts == 0) {
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s` (`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", tablename, selectoption);
for (j = 0; j < MAX_SLOTS; ++j)
for (int j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", `card%d`", j);
for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
for (int j = 0; j < MAX_ITEM_OPTIONS; ++j)
StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", j, j);
if (has_favorite)
StrBuf->AppendStr(&buf, ", `favorite`");
Expand All @@ -991,9 +995,9 @@ static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum in
total_inserts > 0 ? ", " : "", guid, p_it->nameid, p_it->amount, p_it->equip, p_it->identify, p_it->refine,
p_it->attribute, p_it->expire_time, p_it->bound, p_it->unique_id);

for (j = 0; j < MAX_SLOTS; ++j)
for (int j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", '%d'", p_it->card[j]);
for (j = 0; j < MAX_ITEM_OPTIONS; ++j)
for (int j = 0; j < MAX_ITEM_OPTIONS; ++j)
StrBuf->Printf(&buf, ", '%d', '%d'", p_it->option[j].index, p_it->option[j].value);

if (has_favorite)
Expand All @@ -1010,7 +1014,8 @@ static int char_memitemdata_to_sql(const struct item *p_items, int guid, enum in
StrBuf->Destroy(&buf);

aFree(cp_items);
aFree(matched_p);
if (matched_p != NULL)
aFree(matched_p);

ShowInfo("%s save complete - guid: %d (replace: %d, insert: %d, delete: %d)\n", tablename, guid, total_updates, total_inserts, total_deletes);

Expand Down
2 changes: 1 addition & 1 deletion src/char/char.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ struct char_interface {
struct DBData (*create_charstatus) (union DBKey key, va_list args);
int (*mmo_char_tosql) (int char_id, struct mmo_charstatus* p);
int (*getitemdata_from_sql) (struct item *items, int max, int guid, enum inventory_table_type table);
int (*memitemdata_to_sql) (const struct item items[], int id, enum inventory_table_type table);
int (*memitemdata_to_sql) (const struct item items[], int current_size, int guid, enum inventory_table_type table);
int (*mmo_gender) (const struct char_session_data *sd, const struct mmo_charstatus *p, char sex);
int (*mmo_chars_fromsql) (struct char_session_data* sd, uint8* buf, int *count);
int (*mmo_char_fromsql) (int char_id, struct mmo_charstatus* p, bool load_everything);
Expand Down
Loading

0 comments on commit 822554f

Please sign in to comment.