summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/atcommand.c54
-rw-r--r--src/map/map.c2
-rw-r--r--src/map/pc.c16
-rw-r--r--src/map/pc.h2
-rw-r--r--src/map/pc_groups.c201
-rw-r--r--src/map/pc_groups.h66
-rwxr-xr-xtools/HPMHookGen/HPMHookGen.pl3
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;