summaryrefslogtreecommitdiff
path: root/src/map/pc_groups.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/pc_groups.c')
-rw-r--r--src/map/pc_groups.c201
1 files changed, 131 insertions, 70 deletions
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;
+}