diff options
-rw-r--r-- | src/map/atcommand.c | 54 | ||||
-rw-r--r-- | src/map/map.c | 2 | ||||
-rw-r--r-- | src/map/pc.c | 16 | ||||
-rw-r--r-- | src/map/pc.h | 2 | ||||
-rw-r--r-- | src/map/pc_groups.c | 201 | ||||
-rw-r--r-- | src/map/pc_groups.h | 66 | ||||
-rwxr-xr-x | tools/HPMHookGen/HPMHookGen.pl | 3 |
7 files changed, 215 insertions, 129 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 758ebb0db..eda7de19a 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -574,7 +574,7 @@ ACMD(who) { case 2: { StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StrBuf->Printf(&buf, msg_txt(344), pc_group_get_name(pl_sd->group)); // "(%s) " + StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) " StrBuf->Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level, pc->job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s" break; @@ -584,7 +584,7 @@ ACMD(who) { StrBuf->Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) " StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StrBuf->Printf(&buf, msg_txt(344), pc_group_get_name(pl_sd->group)); // "(%s) " + StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) " StrBuf->Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d" break; } @@ -594,7 +594,7 @@ ACMD(who) { StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StrBuf->Printf(&buf, msg_txt(344), pc_group_get_name(pl_sd->group)); // "(%s) " + StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) " if (p != NULL) StrBuf->Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'" if (g != NULL) @@ -3512,7 +3512,7 @@ ACMD(reloadatcommand) { config_destroy(&run_test); atcommand->doload(); - pc_groups_reload(); + pcg->reload(); clif->message(fd, msg_txt(254)); return true; } @@ -8164,11 +8164,11 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand switch( type ) { case COMMAND_CHARCOMMAND: - if( cmd->char_groups[pc_group_get_idx(sd->group)] == 0 ) + if( cmd->char_groups[pcg->get_idx(sd->group)] == 0 ) continue; break; case COMMAND_ATCOMMAND: - if( cmd->at_groups[pc_group_get_idx(sd->group)] == 0 ) + if( cmd->at_groups[pcg->get_idx(sd->group)] == 0 ) continue; break; default: @@ -8377,7 +8377,7 @@ ACMD(reloadquestdb) { return true; } ACMD(addperm) { - int perm_size = ARRAYLENGTH(pc_g_permission_name); + int perm_size = pcg->permission_count; bool add = (strcmpi(command+1, "addperm") == 0) ? true : false; int i; @@ -8386,37 +8386,37 @@ ACMD(addperm) { clif->message(fd, atcmd_output); clif->message(fd, msg_txt(1379)); // -- Permission List for( i = 0; i < perm_size; i++ ) { - sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); + sprintf(atcmd_output,"- %s",pcg->permissions[i].name); clif->message(fd, atcmd_output); } return false; } - ARR_FIND(0, perm_size, i, strcmpi(pc_g_permission_name[i].name, message) == 0); + ARR_FIND(0, perm_size, i, strcmpi(pcg->permissions[i].name, message) == 0); if( i == perm_size ) { sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission. clif->message(fd, atcmd_output); clif->message(fd, msg_txt(1379)); // -- Permission List for( i = 0; i < perm_size; i++ ) { - sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); + sprintf(atcmd_output,"- %s",pcg->permissions[i].name); clif->message(fd, atcmd_output); } return false; } - if( add && (sd->extra_temp_permissions&pc_g_permission_name[i].permission) ) { - sprintf(atcmd_output, msg_txt(1381),sd->status.name,pc_g_permission_name[i].name); // User '%s' already possesses the '%s' permission. + if( add && (sd->extra_temp_permissions&pcg->permissions[i].permission) ) { + sprintf(atcmd_output, msg_txt(1381),sd->status.name,pcg->permissions[i].name); // User '%s' already possesses the '%s' permission. clif->message(fd, atcmd_output); return false; - } else if ( !add && !(sd->extra_temp_permissions&pc_g_permission_name[i].permission) ) { - sprintf(atcmd_output, msg_txt(1382),sd->status.name,pc_g_permission_name[i].name); // User '%s' doesn't possess the '%s' permission. + } else if ( !add && !(sd->extra_temp_permissions&pcg->permissions[i].permission) ) { + sprintf(atcmd_output, msg_txt(1382),sd->status.name,pcg->permissions[i].name); // User '%s' doesn't possess the '%s' permission. clif->message(fd, atcmd_output); sprintf(atcmd_output,msg_txt(1383),sd->status.name); // -- User '%s' Permissions clif->message(fd, atcmd_output); for( i = 0; i < perm_size; i++ ) { - if( sd->extra_temp_permissions&pc_g_permission_name[i].permission ) { - sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); + if( sd->extra_temp_permissions&pcg->permissions[i].permission ) { + sprintf(atcmd_output,"- %s",pcg->permissions[i].name); clif->message(fd, atcmd_output); } } @@ -8425,9 +8425,9 @@ ACMD(addperm) { } if( add ) - sd->extra_temp_permissions |= pc_g_permission_name[i].permission; + sd->extra_temp_permissions |= pcg->permissions[i].permission; else - sd->extra_temp_permissions &=~ pc_g_permission_name[i].permission; + sd->extra_temp_permissions &=~ pcg->permissions[i].permission; sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary. @@ -9663,7 +9663,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message if( !pc->get_group_level(sd) ) { if( x >= 1 || y >= 1 ) { /* we have command */ info = atcommand->get_info_byname(atcommand->check_alias(command + 1)); - if( !info || info->char_groups[pc_group_get_idx(sd->group)] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */ + if( !info || info->char_groups[pcg->get_idx(sd->group)] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */ return false; } else return false;/* display as normal message */ @@ -9743,8 +9743,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message // type == 1 : player invoked if (type == 1) { int i; - if ((*command == atcommand->at_symbol && info->at_groups[pc_group_get_idx(sd->group)] == 0) || - (*command == atcommand->char_symbol && info->char_groups[pc_group_get_idx(sd->group)] == 0) ) { + if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] == 0) || + (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] == 0) ) { return false; } if( pc_isdead(sd) && pc->has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) { @@ -9942,13 +9942,13 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command continue; } - idx = pc_group_get_idx(group); + idx = pcg->get_idx(group); if (idx < 0 || idx >= sz) { ShowError("atcommand_db_load_groups: index (%d) out of bounds [0,%d]\n", idx, sz - 1); continue; } - if (pc_group_has_permission(group, PC_PERM_USE_ALL_COMMANDS)) { + if (pcg->has_permission(group, PC_PERM_USE_ALL_COMMANDS)) { atcmd->at_groups[idx] = atcmd->char_groups[idx] = 1; continue; } @@ -9986,8 +9986,8 @@ bool atcommand_can_use(struct map_session_data *sd, const char *command) { if (info == NULL) return false; - if ((*command == atcommand->at_symbol && info->at_groups[pc_group_get_idx(sd->group)] != 0) || - (*command == atcommand->char_symbol && info->char_groups[pc_group_get_idx(sd->group)] != 0) ) { + if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] != 0) || + (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] != 0) ) { return true; } @@ -9999,8 +9999,8 @@ bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtComm if (info == NULL) return false; - if ((type == COMMAND_ATCOMMAND && info->at_groups[pc_group_get_idx(sd->group)] != 0) || - (type == COMMAND_CHARCOMMAND && info->char_groups[pc_group_get_idx(sd->group)] != 0) ) { + if ((type == COMMAND_ATCOMMAND && info->at_groups[pcg->get_idx(sd->group)] != 0) || + (type == COMMAND_CHARCOMMAND && info->char_groups[pcg->get_idx(sd->group)] != 0) ) { return true; } diff --git a/src/map/map.c b/src/map/map.c index 2a2f98bdc..781cc0ff9 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5342,6 +5342,7 @@ void map_hp_symbols(void) { HPM->share(skill,"skill"); HPM->share(vending,"vending"); HPM->share(pc,"pc"); + HPM->share(pcg,"pc_groups"); HPM->share(party,"party"); HPM->share(storage,"storage"); HPM->share(trade,"trade"); @@ -5396,6 +5397,7 @@ void map_load_defaults(void) { skill_defaults(); vending_defaults(); pc_defaults(); + pc_groups_defaults(); party_defaults(); storage_defaults(); trade_defaults(); diff --git a/src/map/pc.c b/src/map/pc.c index 41f4a1a96..1ed66a313 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -72,7 +72,7 @@ struct map_session_data* pc_get_dummy_sd(void) { struct map_session_data *dummy_sd; CREATE(dummy_sd, struct map_session_data, 1); - dummy_sd->group = pc_group_get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times + dummy_sd->group = pcg->get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times return dummy_sd; } @@ -82,7 +82,7 @@ struct map_session_data* pc_get_dummy_sd(void) */ int pc_get_group_level(struct map_session_data *sd) { - return pc_group_get_level(sd->group); + return pcg->get_level(sd->group); } /** @@ -93,7 +93,7 @@ int pc_get_group_level(struct map_session_data *sd) */ int pc_set_group(struct map_session_data *sd, int group_id) { - GroupSettings *group = pc_group_id2group(group_id); + GroupSettings *group = pcg->id2group(group_id); if (group == NULL) return 1; sd->group_id = group_id; @@ -104,9 +104,9 @@ int pc_set_group(struct map_session_data *sd, int group_id) /** * Checks if player has permission to perform action. */ -bool pc_has_permission(struct map_session_data *sd, enum e_pc_permission permission) +bool pc_has_permission(struct map_session_data *sd, unsigned int permission) { - return ((sd->extra_temp_permissions&permission) != 0 || pc_group_has_permission(sd->group, permission)); + return ((sd->extra_temp_permissions&permission) != 0 || pcg->has_permission(sd->group, permission)); } /** @@ -114,7 +114,7 @@ bool pc_has_permission(struct map_session_data *sd, enum e_pc_permission permiss */ bool pc_should_log_commands(struct map_session_data *sd) { - return pc_group_should_log_commands(sd->group); + return pcg->should_log_commands(sd->group); } int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data) { @@ -10203,7 +10203,7 @@ void do_final_pc(void) { db_destroy(pc->itemcd_db); - do_final_pc_groups(); + pcg->final(); ers_destroy(pc->sc_display_ers); return; @@ -10241,7 +10241,7 @@ void do_init_pc(void) { pc->night_timer_tid = timer->add_interval(timer->gettick() + day_duration + (map->night_flag ? night_duration : 0), pc->map_night_timer, 0, 0, day_duration + night_duration); } - do_init_pc_groups(); + pcg->init(); pc->sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:sc_display_ers", ERS_OPT_NONE); } diff --git a/src/map/pc.h b/src/map/pc.h index 8eb7e692a..05e8ba7b4 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -751,7 +751,7 @@ struct pc_interface { bool (*can_give_items) (struct map_session_data *sd); bool (*can_use_command) (struct map_session_data *sd, const char *command); - bool (*has_permission) (struct map_session_data *sd, enum e_pc_permission permission); + bool (*has_permission) (struct map_session_data *sd, unsigned int permission); int (*set_group) (struct map_session_data *sd, int group_id); bool (*should_log_commands) (struct map_session_data *sd); diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index be02b5f15..78d111b1c 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -16,52 +16,10 @@ #include "map.h" // mapiterator #include "pc.h" // pc->set_group() -// Cached config settings for quick lookup -struct GroupSettings { - unsigned int id; // groups.[].id - int level; // groups.[].level - char *name; // copy of groups.[].name - unsigned int e_permissions; // packed groups.[].permissions - bool log_commands; // groups.[].log_commands - int index; // internal index of the group (contiguous range starting at 0) [Ind] - /// Following are used/available only during config reading - config_setting_t *commands; // groups.[].commands - config_setting_t *permissions; // groups.[].permissions - config_setting_t *inherit; // groups.[].inherit - bool inheritance_done; // have all inheritance rules been evaluated? - config_setting_t *root; // groups.[] -}; - -const struct pc_permission_name_table pc_g_permission_name[NUM_PC_PERM] = { - { "can_trade", PC_PERM_TRADE }, - { "can_party", PC_PERM_PARTY }, - { "all_skill", PC_PERM_ALL_SKILL }, - { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT }, - { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL }, - { "join_chat", PC_PERM_JOIN_ALL_CHAT }, - { "kick_chat", PC_PERM_NO_CHAT_KICK }, - { "hide_session", PC_PERM_HIDE_SESSION }, - { "who_display_aid", PC_PERM_WHO_DISPLAY_AID }, - { "hack_info", PC_PERM_RECEIVE_HACK_INFO }, - { "any_warp", PC_PERM_WARP_ANYWHERE }, - { "view_hpmeter", PC_PERM_VIEW_HPMETER }, - { "view_equipment", PC_PERM_VIEW_EQUIPMENT }, - { "use_check", PC_PERM_USE_CHECK }, - { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE }, - { "all_commands", PC_PERM_USE_ALL_COMMANDS }, - { "receive_requests", PC_PERM_RECEIVE_REQUESTS }, - { "show_bossmobs", PC_PERM_SHOW_BOSS }, - { "disable_pvm", PC_PERM_DISABLE_PVM }, - { "disable_pvp", PC_PERM_DISABLE_PVP }, - { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD }, - { "hchsys_admin", PC_PERM_HCHSYS_ADMIN }, -}; - -static DBMap* pc_group_db; // id -> GroupSettings -static DBMap* pc_groupname_db; // name -> GroupSettings - static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd() +struct pc_groups_interface pcg_s; + /** * Returns dummy group. * Used in dummy map sessions. @@ -78,7 +36,7 @@ GroupSettings* pc_group_get_dummy_group(void) */ static inline GroupSettings* name2group(const char* group_name) { - return strdb_get(pc_groupname_db, group_name); + return strdb_get(pcg->name_db, group_name); } /** @@ -116,7 +74,7 @@ static void read_config(void) { continue; } - if (pc_group_exists(id)) { + if (pcg->exists(id)) { ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i); config_setting_remove_elem(groups, i); --i; @@ -162,15 +120,15 @@ static void read_config(void) { group_settings->root = group; group_settings->index = i; - strdb_put(pc_groupname_db, groupname, group_settings); - idb_put(pc_group_db, id, group_settings); + strdb_put(pcg->name_db, groupname, group_settings); + idb_put(pcg->db, id, group_settings); } group_count = config_setting_length(groups); // Save number of groups - assert(group_count == db_size(pc_group_db)); + assert(group_count == db_size(pcg->db)); // Check if all commands and permissions exist - iter = db_iterator(pc_group_db); + iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; int count = 0, i; @@ -201,8 +159,8 @@ static void read_config(void) { const char *name = config_setting_name(permission); int j; - ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); - if (j == ARRAYLENGTH(pc_g_permission_name)) { + ARR_FIND(0, pcg->permission_count, j, strcmp(pcg->permissions[j].name, name) == 0); + if (j == pcg->permission_count) { ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name); config_setting_remove(permissions, name); --i; @@ -215,7 +173,7 @@ static void read_config(void) { // Apply inheritance i = 0; // counter for processed groups while (i < group_count) { - iter = db_iterator(pc_group_db); + iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *inherit = NULL, *commands = group_settings->commands, @@ -280,7 +238,7 @@ static void read_config(void) { } // while(i < group_count) // Pack permissions into GroupSettings.e_permissions for faster checking - iter = db_iterator(pc_group_db); + iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *permissions = group_settings->permissions; int i, count = config_setting_length(permissions); @@ -293,8 +251,8 @@ static void read_config(void) { if (val == 0) // does not have this permission continue; - ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); - group_settings->e_permissions |= pc_g_permission_name[j].permission; + ARR_FIND(0, pcg->permission_count, j, strcmp(pcg->permissions[j].name, name) == 0); + group_settings->e_permissions |= pcg->permissions[j].permission; } } dbi_destroy(iter); @@ -308,7 +266,7 @@ static void read_config(void) { config_setting_t **commands = NULL; CREATE(groups, GroupSettings*, group_count); CREATE(commands, config_setting_t*, group_count); - iter = db_iterator(pc_group_db); + iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { groups[i] = group_settings; commands[i] = group_settings->commands; @@ -332,7 +290,7 @@ static void read_config(void) { * @param group group * @param permission permission to check */ -bool pc_group_has_permission(GroupSettings *group, enum e_pc_permission permission) +bool pc_group_has_permission(GroupSettings *group, unsigned int permission) { return ((group->e_permissions&permission) != 0); } @@ -353,7 +311,7 @@ bool pc_group_should_log_commands(GroupSettings *group) */ bool pc_group_exists(int group_id) { - return idb_exists(pc_group_db, group_id); + return idb_exists(pcg->db, group_id); } /** @@ -361,7 +319,7 @@ bool pc_group_exists(int group_id) */ GroupSettings* pc_group_id2group(int group_id) { - return idb_get(pc_group_db, group_id); + return idb_get(pcg->db, group_id); } /** @@ -398,13 +356,79 @@ int pc_group_get_idx(GroupSettings *group) } /** + * Insert a new permission + * @return inserted key or 0 upon failure. + **/ +unsigned int pc_groups_add_permission(const char *name) { + uint64 key = 0x1; + unsigned char i; + + for(i = 0; i < pcg->permission_count; i++) { + if( strcmpi(name,pcg->permissions[i].name) == 0 ) { + ShowError("pc_groups_add_permission(%s): failed! duplicate permission name!\n",name); + return 0; + } + } + + if( i != 0 ) + key = (uint64)pcg->permissions[i - 1].permission << 1; + + if( key >= UINT_MAX ) { + ShowError("pc_groups_add_permission(%s): failed! not enough room, too many permissions!\n",name); + return 0; + } + + i = pcg->permission_count; + RECREATE(pcg->permissions, struct pc_groups_permission_table, ++pcg->permission_count); + + pcg->permissions[i].name = aStrdup(name); + pcg->permissions[i].permission = (unsigned int)key; + + return (unsigned int)key; +} +/** * Initialize PC Groups: allocate DBMaps and read config. * @public */ -void do_init_pc_groups(void) -{ - pc_group_db = idb_alloc(DB_OPT_RELEASE_DATA); - pc_groupname_db = stridb_alloc(DB_OPT_DUP_KEY, 0); +void do_init_pc_groups(void) { + const struct { + const char *name; + unsigned int permission; + } pc_g_defaults[] = { + { "can_trade", PC_PERM_TRADE }, + { "can_party", PC_PERM_PARTY }, + { "all_skill", PC_PERM_ALL_SKILL }, + { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT }, + { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL }, + { "join_chat", PC_PERM_JOIN_ALL_CHAT }, + { "kick_chat", PC_PERM_NO_CHAT_KICK }, + { "hide_session", PC_PERM_HIDE_SESSION }, + { "who_display_aid", PC_PERM_WHO_DISPLAY_AID }, + { "hack_info", PC_PERM_RECEIVE_HACK_INFO }, + { "any_warp", PC_PERM_WARP_ANYWHERE }, + { "view_hpmeter", PC_PERM_VIEW_HPMETER }, + { "view_equipment", PC_PERM_VIEW_EQUIPMENT }, + { "use_check", PC_PERM_USE_CHECK }, + { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE }, + { "all_commands", PC_PERM_USE_ALL_COMMANDS }, + { "receive_requests", PC_PERM_RECEIVE_REQUESTS }, + { "show_bossmobs", PC_PERM_SHOW_BOSS }, + { "disable_pvm", PC_PERM_DISABLE_PVM }, + { "disable_pvp", PC_PERM_DISABLE_PVP }, + { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD }, + { "hchsys_admin", PC_PERM_HCHSYS_ADMIN }, + }; + unsigned char i, len = ARRAYLENGTH(pc_g_defaults); + + for(i = 0; i < len; i++) { + unsigned int p; + if( ( p = pcg->add_permission(pc_g_defaults[i].name) ) != pc_g_defaults[i].permission ) + ShowError("do_init_pc_groups: %s error : %d != %d\n",pc_g_defaults[i].name,p,pc_g_defaults[i].permission); + } + + pcg->db = idb_alloc(DB_OPT_RELEASE_DATA); + pcg->name_db = stridb_alloc(DB_OPT_DUP_KEY, 0); + read_config(); } @@ -425,10 +449,19 @@ static int group_db_clear_sub(DBKey key, DBData *data, va_list args) */ void do_final_pc_groups(void) { - if (pc_group_db != NULL) - pc_group_db->destroy(pc_group_db, group_db_clear_sub); - if (pc_groupname_db != NULL) - db_destroy(pc_groupname_db); + if (pcg->db != NULL) + pcg->db->destroy(pcg->db, group_db_clear_sub); + if (pcg->name_db != NULL) + db_destroy(pcg->name_db); + + if(pcg->permissions != NULL) { + unsigned char i; + for(i = 0; i < pcg->permission_count; i++) + aFree(pcg->permissions[i].name); + aFree(pcg->permissions); + pcg->permissions = NULL; + } + pcg->permission_count = 0; } /** @@ -440,8 +473,8 @@ void pc_groups_reload(void) { struct map_session_data *sd = NULL; struct s_mapiterator *iter; - do_final_pc_groups(); - do_init_pc_groups(); + pcg->final(); + pcg->init(); /* refresh online users permissions */ iter = mapit_getallusers(); @@ -454,3 +487,31 @@ void pc_groups_reload(void) { } mapit->free(iter); } + +/** + * Connect Interface + **/ +void pc_groups_defaults(void) { + pcg = &pcg_s; + + /* */ + pcg->db = NULL; + pcg->name_db = NULL; + /* */ + pcg->permissions = NULL; + pcg->permission_count = 0; + /* */ + pcg->init = do_init_pc_groups; + pcg->final = do_final_pc_groups; + pcg->reload = pc_groups_reload; + /* */ + pcg->get_dummy_group = pc_group_get_dummy_group; + pcg->exists = pc_group_exists; + pcg->id2group = pc_group_id2group; + pcg->has_permission = pc_group_has_permission; + pcg->should_log_commands = pc_group_should_log_commands; + pcg->get_name = pc_group_get_name; + pcg->get_level = pc_group_get_level; + pcg->get_idx = pc_group_get_idx; + pcg->add_permission = pc_groups_add_permission; +} diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 8f350c2b6..28c82d619 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -32,34 +32,54 @@ enum e_pc_permission { PC_PERM_HCHSYS_ADMIN = 0x200000, }; -/// Total number of PC permissions (without PC_PERM_NONE). -/// This is manifest constant for the size of pc_g_permission_name array, -/// so it's possible to apply sizeof to it [C-FAQ 1.24] -/// Whenever adding new permission: 1. add enum entry above, 2. add entry into -/// pc_g_permission_name (in pc.c), 3. increase NUM_PC_PERM below by 1. -#define NUM_PC_PERM 22 - -struct pc_permission_name_table { - const char *name; - enum e_pc_permission permission; +// Cached config settings for quick lookup +struct GroupSettings { + unsigned int id; // groups.[].id + int level; // groups.[].level + char *name; // copy of groups.[].name + unsigned int e_permissions; // packed groups.[].permissions + bool log_commands; // groups.[].log_commands + int index; // internal index of the group (contiguous range starting at 0) [Ind] + /// Following are used/available only during config reading + config_setting_t *commands; // groups.[].commands + config_setting_t *permissions; // groups.[].permissions + config_setting_t *inherit; // groups.[].inherit + bool inheritance_done; // have all inheritance rules been evaluated? + config_setting_t *root; // groups.[] }; -/// Name <-> enum table for PC permissions -extern const struct pc_permission_name_table pc_g_permission_name[NUM_PC_PERM]; +struct pc_groups_permission_table { + char *name; + unsigned int permission; +}; typedef struct GroupSettings GroupSettings; -GroupSettings* pc_group_get_dummy_group(void); -bool pc_group_exists(int group_id); -GroupSettings* pc_group_id2group(int group_id); -bool pc_group_has_permission(GroupSettings *group, enum e_pc_permission permission); -bool pc_group_should_log_commands(GroupSettings *group); -const char* pc_group_get_name(GroupSettings *group); -int pc_group_get_level(GroupSettings *group); -int pc_group_get_idx(GroupSettings *group); +struct pc_groups_interface { + /* */ + DBMap* db; // id -> GroupSettings + DBMap* name_db; // name -> GroupSettings + /* */ + struct pc_groups_permission_table *permissions; + unsigned char permission_count; + /* */ + void (*init) (void); + void (*final) (void); + void (*reload) (void); + /* */ + GroupSettings* (*get_dummy_group) (void); + bool (*exists) (int group_id); + GroupSettings* (*id2group) (int group_id); + bool (*has_permission) (GroupSettings *group, unsigned int permission); + bool (*should_log_commands) (GroupSettings *group); + const char* (*get_name) (GroupSettings *group); + int (*get_level) (GroupSettings *group); + int (*get_idx) (GroupSettings *group); + unsigned int (*add_permission) (const char *name); +}; + +struct pc_groups_interface *pcg; -void do_init_pc_groups(void); -void do_final_pc_groups(void); -void pc_groups_reload(void); +void pc_groups_defaults(void); #endif // _PC_GROUPS_H_ diff --git a/tools/HPMHookGen/HPMHookGen.pl b/tools/HPMHookGen/HPMHookGen.pl index cf50a9e77..eef490e29 100755 --- a/tools/HPMHookGen/HPMHookGen.pl +++ b/tools/HPMHookGen/HPMHookGen.pl @@ -265,6 +265,8 @@ foreach my $file (@files) { # Loop through the xml files $key = "ircbot"; } elsif ($key =~ /log_interface/) { $key = "logs"; + } elsif ($key =~ /pc_groups_interface/) { + $key = "pcg"; } else { $key =~ s/_interface//; } @@ -367,6 +369,7 @@ foreach my $file (@files) { # Loop through the xml files my %exportsymbols = map { $_ => &{ sub ($) { return 'battlegrounds' if $_ =~ /^bg$/; + return 'pc_groups' if $_ =~ /^pcg$/; return $_; }}($_); } @keys; |