Jump to content

[Feature] New GM System


Maki

Recommended Posts


  • Group:  Members
  • Topic Count:  146
  • Topics Per Day:  0.03
  • Content Count:  1195
  • Reputation:   467
  • Joined:  11/15/11
  • Last Seen:  

http://rathena.org/board/topic/56677-new-gm-system/page__pid__67983#entry67983

As stated by Jonne:

Well, I would find it to be time to change the atcommand or GM system. So you actually group Users and not give them levels and like this you can better handle giving out atcommands and create a hierarchie which is not just drop-down. So the admin for example has all rights. He then creates a group called EventGM. Those have certain commands. Then he created a group called SupportGM. They have completly different commands, but they are not considered 'lower'. Also, EventGMs don't automatically have the commands of SupportGMs and so on.

This system was once introduced on eAthena as MOD and I think if someone could provide a fully working system for rAthena it should replace the old system officially.

Who's in?

Gepard:

Proposal:

config file to define groups

<group_id>:<group_name>{:<inherit_from_another_group_id>}

atcommand_conf - use group names instead of levels

gm_conf - use group names instead of levels

login table - `group_id` instead of `level`

/me also thinks it would be nice to be able to add GM Commands to Guilds/characters, so it does not have to be account-specific giving you more control/freedom *-*

+∞!

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  69
  • Topics Per Day:  0.02
  • Content Count:  1315
  • Reputation:   372
  • Joined:  12/10/11
  • Last Seen:  

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

I don't think it's cooked enough to be included in rAthena. There is no documentation for that GeoIP.dat file, the way it's handled (ip->country translation) looks quite awful (consider using built-in DB system maybe?), and I definitely would consider moving SQL queries to char-server.

So yes, I think we could add this if it's reworked. And we also need to sort out possible license issue with that GeoIP data.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  9
  • Topics Per Day:  0.00
  • Content Count:  379
  • Reputation:   304
  • Joined:  11/10/11
  • Last Seen:  

I was going to post in the other topic, but since there is one here... /no1

The group system is a good idea /wah

If it's base on account + guild + character + party (or others), can we have multiple group in same time (and what group name should we use in this case) ?...

But we have to keep the gmlevel (not for atcommand but) for gm permission (ex: GM 20 can't kick gm 99), trade and logs, old script compatibility (getgmlevel()), control panel (our problem ?), etc.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

It would be reasonable to make a transition period, where GM level funcionality would be still available but marked as deprecated, throwing Warnings and stuff every time it's used.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

Another idea is to add a `level` to group definition file. It would be a way to order groups, so that only higher level group could @kick lower level, but not the other way. This could also provide a backwards compatibility for scripts - most of the use something like if (getgmlevel()) or if (getgmlevel()>=99).Just set "level" = 99 for the top group and done :(

Link to comment
Share on other sites

  • 4 weeks later...

  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

To improve GM system, we'll need a better format for config files. I think we should choose one that is human-readable, easy to edit with text editor and provides some more functionality that simple .ini which only has sections and key-value pairs.

Maybe http://www.hyperrealm.com/libconfig/ ?

I also thought about YAML, but it seems too complex for our needs. XML is out of question, it's not really readable nor editable. LUA - bleeeh.

Writing own parser is reinventing the wheel.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  11
  • Topics Per Day:  0.00
  • Content Count:  427
  • Reputation:   123
  • Joined:  11/17/11
  • Last Seen:  

Well, I don't really know if semicolons in a config file is desirable. Users may think it is a language and somehow interpreted and use experssions. And it does not support multi threading. Of course rA is not multi threaded right now, but at least do not create new obstacles for someone who decide to work on this area in the future. (Although probably we will not want to access a config file from multiple threads, so my first argument is more important.)

Anyways it would be awesome if the config lib we choose would natively support importing configs.

Edit: Just found out, it supports @include :D

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

Trailing semicolons are optional. Users should not have to think/guess, because config file should be properly documented, so no problem here.

Multithreading is not an issue at the moment. rAthena in general is not thread-safe, so adding multithreading would be a great overhaul anyway. Proper handling of configuration, which is very rarely written to, would be the least problem.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  11
  • Topics Per Day:  0.00
  • Content Count:  427
  • Reputation:   123
  • Joined:  11/17/11
  • Last Seen:  

Considering trailing semicolons are optional, I vote yes for libconfig.

It may also help to make new atcommand alias reading cleaner.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

Ok, I've started working on new GM system. As soon as I finish it, I'll post a diff here for other devs to review changes.

Progress:

  • libconfig - Visual Studio done, autotools & cmake - to do,
  • groups config file format - done,
  • reading groups config file - done,
  • group ihneritance - 50%,
  • allowed commands per group - done,
  • other permissions per group - 0%,
  • atcommand config file format & reading - 75%
  • command aliases - done
  • command logging - 0%
  • replacing gmlevel with group_id - 5%

Config files at the moment look like that:

groups.conf

groups: (
{
id: 0
name: "Players"
commands: {
 autotrade: false
 iteminfo: true
}
permissions: {
 can_trade: true
}
},
{
id: 1
name: "Supporters"
inherit: ( "Players" )
commands: {
 autotrade: true
 broadcast: true
}
permissions: {
 can_trade: false
}
},
{
id: 5
name: "testgroup"
inherit: ( "Supporters" )
commands: {
 kick: [true, false]
 ban: [false, true]
}
permissions: {
 can_trade: true
}
}
)

new atcommand.conf

// The symbol that will be used to recognize commands.
// You can set any one character except control-characters (0x00-0x1f),
// '%', '$' (party/guild chat speaking) and '/' (standard client commands).
// atcommand_symbol represents @commands used locally
// charcommand_symbol represents #commands used on other players.
atcommand_symbol : "@"
charcommand_symbol: "#"
// Command aliases
// <commandname> : [ "<alias>", ... ]
aliases: {
mobinfo: ["monsterinfo", "mi"]
iteminfo: ["ii"]
time: ["date", "serverdate", "servertime"]
autotrade: ["at"]
help: ["h"]
help2: ["h2"]
jumpto: ["goto", "warpto"]
mount: ["mountpeco"]
who: ["whois"]
npctalk: ["npctalkc"]
gvgon: ["gpvpon"]
gvgoff: ["gpvpoff"]
jobchange: ["job"]
load: ["return"]
mapmove: ["rura", "warp"]
dye: ["ccolor"]
hairstyle: ["hstyle"]
haircolor: ["hcolor"]
monster: ["spawn"]
blvl: ["lvup", "blevel", "baselvl", "baselvup", "baselevel", "baselvlup"]
jlvl: ["jlevel", "joblvl", "joblvup", "joblevel", "joblvlup"]
glvl: ["glevel", "guildlvl", "guildlvup", "guildlevel", "guildlvlup"]
allskill: ["allskills", "skillall", "skillsall"]
allstats: ["allstat", "statall", "statsall"]
block: ["charblock"]
unblock: ["charunblock"]
ban: ["banish", "charban", "charbanish"]
unban: ["unbanish", "charunban", "charunbanish"]
unjail: ["discharge"]
homlevel: ["hlvl", "hlevel", "homlvl", "homlvup"]
homevolution: ["homevolve"]
mutearea: ["stfu"]
monsterignore: ["battleignore"]
}

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  11
  • Topics Per Day:  0.00
  • Content Count:  427
  • Reputation:   123
  • Joined:  11/17/11
  • Last Seen:  

Is multiple inheritance supported? if so, [ ] should be used, to reflect it is a list actually (like aliases).

atcommand: true, atcommand: false? I assume all atcommands are off by default. Does false means disable an inherited command? In that case we can warn users if there is no such command enabled in the base groups ( because it may be a typo ).

I guess [False, true] is for atcommand, charcommand. If only one value present it is both at and charcommand I guess.

I like the concept so far.

Anyways server owners (don't need to be a core dev) out there. Someone who feels like working on default/recommended groups I'm bet Gepard would welcome if you'd share it /ok

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

Yeah, multiple inheritance is supported, that's why it is

inherit: ( "othergroup" )

You can put more than one, so

inherit: ( "othergroup", "anothergroup" )

is ok.

Does not matter if () or [] are used. Both lists and arrays will work.

Recursive inheritance is also supported, ie in the example, group 5 will inherit from group 1 and - through group 1 - from group 0 as well.

All commands are off by default. True means enable this command for this group, false means disable (used to override inherited settings).

[false, true] is for atcommand, charcommand, yup. And no, one value is for atcommand only, because most commands will be either disabled for remote use (don't wanna players running commands on other players) or just don't have a remote version (that needs a cleanup on its own, by the way).

I'm also considering adding a special superuser (admin) group, that would have all commands enabled by default (so there would be no need to enable all of them one by one) or, alternatively, a setting "all_commands: true" that would do the same for any group.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  11
  • Topics Per Day:  0.00
  • Content Count:  427
  • Reputation:   123
  • Joined:  11/17/11
  • Last Seen:  

Thanks for the clarifications, yeah, thinking about it, one value for atcommand only makes more sense. It would be a pain to manually disable charcommands for every command in players' groups.

Anyways does porting the whole conf folder to libconf involved in this project? It is not in the progress list.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

There are some problems with porting everything to libconfig.

Main issue is "import". Libconfig supports "include", but it's a bit different. Most importantly, it does not allow to include in a way that would create duplicate settings. In rAthena, duplicate setting from import file simply overwrites the previous default setting and it's intended behavior. With libconfig it would require an additional code to merge the imported settings into main settings and sadly, API does not provide such function.

rAthena conf files are really simple, it's just a bunch of scalar settings, all on the same level. No nesting, no lists, arrays, groups, nothing. To take advantage of libconfig, one requires a bit complicated configuration. It also explains why "include" works the way it works. "Importing" a list (like groups list in groups.conf) is not really possible, without overwriting it as a whole (there's no way to delete a member). But if we're overwriting it anyway, there's no need for import file that's specifically intended to change only some of settings while keeping other untouched. So actually there's no point in having rA-style import in libconfig, unless you use it .ini-style.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  169
  • Topics Per Day:  0.04
  • Content Count:  1260
  • Reputation:   750
  • Joined:  11/19/11
  • Last Seen:  

Looks excellent

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

Time for more detailed description of changes I've done so far.

General description:

  • The whole concept of GMs and non-GMs as well as GM levels has been abondoned in favor of more role- and privilege-oriented player groups.
  • Player groups are independent of each other, so unless you decide to do so, they don't have to share any privileges like it was with top-down GM level hierarchy. There is, however, a way to say which group is higher, and which is lower: it's group level.
  • Each group has following atributes:
    • ID — unique number, the same that is used in `login`.`group_id`
    • name
    • level — it can be interpereted as (GM) level of all group members
    • commands settings — what commands can group members use
    • permissions settings — what other permissions group members have
    • inherited groups — permissions and commands from which groups are inherited

    [*]Groups are configured in 'conf/groups.conf' file.

    [*]Each account belongs to exactly one group. In `login` table, `level` column has been renamed to `group_id`.

    [*]In login-server configuration file 'conf/login_athena.conf' "min_level_to_connect" setting has been replaced with "group_id_to_connect" setting, which allows you to define account group id that is required to connect to server.

    [*]In char-server configuration file 'conf/char_athena.conf' "gm_allow_level" setting has been replaced with "gm_allow_group" setting, which allows you to define group id that is allowed to bypass the server limit of online users.

    [*]Atcommand configuration file no longer defines GM levels required to use the command. Permissions to use commands are defined for each player group separately in group configuration file.

    [*]GM configuration file (conf/battle/gm.conf) no longer defines GM levels required to get some privileges (like trading or partying). See full list:

    lowest_gm_level, atcommand_gm_only, gm_all_skill, gm_all_equipment, gm_skill_unconditional, gm_join_chat, gm_kick_chat, gm_can_party, gm_cant_party_min_lv, gm_cant_drop_min_lv, gm_cant_drop_max_lv, disp_hpmeter, hack_info_GM_level, any_warp_GM_min_level, who_display_aid, gm_viewequip_min_lv, gm_check_minlevel

    These permissions are defined for each player group separately in group configuration file.

    [*]Player title defined by 'conf/battle/gm.conf' settings "title_lvl1" to "title_lvl8" and 'conf/msg_athena.conf' (335~342) are replaced with group names.

    [*]Group level is used only:

    • when determining if player can override trade restrictions defined in 'db/item_trade.txt'
    • when determining if player can use @command on another player (existing rule that low-level player can not use some commands, eg @kick on high-level player has been kept) or see another player with @who commands (if they have "hide_session" privilege).
    • as a return value for getgmlevel() script command
    • when determining if player can use commands in a map with nocommand mapflag set

    [*]Modified GM whisper system to deliver messages basing on permissions, not level.

    [*]Remote trade request is now possible only if player is allowed to use @trade command as well.

    [*]Added a proper permission to use /changemaptype command.

    [*]clif_displaymessage is now capable of displaying multiline messages

    [*]all ACMD_FUNCs are static now, and the only way to invoke them is with is_atcommand(); all client commands (starting with /) are now translated into corresponding atcommands (with exception of /kick used on monster, as there is no atcommand to kill single monster). List of commands:

    /mapmove, /mm

    /b, /nb

    /resetskill, /resetstate

    /lb, /nlb

    /kill

    /shift

    /remove

    /summon

    /recall

    /item, /monster

    /hide

    /rc

    [*]Removed nonsense "bot check" triggering when player blocked (/ex) Server.

    [*]Merged @monster, @monsterbig and @monstersmall.

    [*]Removed @adjcmdlvl command.

    [*]Replaced @adjgmlvl command with @adjgroup, which allows to temporarily move player to another group.

    [*]@help command requires "commandname" param and shows more detailed info about commands.

Technical details:

  • All occurences of GM level have been replaced either with Group ID (in login and char-server) or Group Level (in map-server). Login-server and char-server are not aware of player groups, they just know the group_id of the account.
    • In map-server group level is used only if there is a need to compare "level" of two players (to preserve the rule that low-level GM can not use commands like @kick on high-level GM), and in script command getgmlevel().

    [*]Player groups implementation

    • Player groups are implemented in separate source file and only provide functions to:
      • check if group can use command
      • check if group has permission to do something
      • get group name
      • get group level
      • initialize groups (for server startup)
      • finalize groups (for server shutdown)

      [*]Player groups use libconfig to load configuration from config file to memory.

      • group permissions are cached and packed in one unsigned int to faster lookup
      • group allowed commands are looked up by name by libconfig API directly from configuration struct
      • inheritance rules are evaluated once, at config load; there is a simple check against inheritance cycles

    [*]Atcommand changes

    • atcommands use libconfig to load configuration from config file to memory
    • atcommand aliases now use a separate DBMap that points to the same AtCommandInfo structs as original commands

    [*]"GM" permissions ("can trade", "can party" etc) are defined as enum now.

If you're interested in even more details, just ask or wait until I post a diff, which should be ready soon.

I need however an opinion on libconfig. It looks like libconfig package for Debian (dunno about other distros) has not been updated in a while, so users will have to compile it from source anyway. So maybe it's better to just link it statically in both Linux and Windows? It's LGPL, so we can include its code in rAthena and change it to GPL.

  • Upvote 3
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

I could replace @adjgmlvl with @changegroup or smth like that. It would temporarily (until relog) move player to another group.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  11
  • Topics Per Day:  0.00
  • Content Count:  427
  • Reputation:   123
  • Joined:  11/17/11
  • Last Seen:  

I vote for static linking. It hasn't got a big size.

Anyways I think a command instead of @adjgmlvl would be needed (well, not really needed, but it would be nice to not loose functionality), to add a player to a group.

group allowed commands are looked up by name by libconfig API directly from configuration struct

I hope this does not mean IO load on each atcommand.

I feel a bit sad, we can not port other confs to use libconfig =(.

Edit: jman and gepard was faster :( adjgmlvl concerns are answerd

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

group allowed commands are looked up by name by libconfig API directly from configuration struct

I hope this does not mean IO load on each atcommand.

I feel a bit sad, we can not port other confs to use libconfig =(.

Allowed commands are represented internally as a node of the libconfig config_t, which is a dynamically allocated tree-like struct to hold all settings and their values.

So, "looked up by name by libconfig API" means "libconfig will be responsible for finding a correct node and its value in its own struct". No file io involved. I just didn't find any reasons to move it to DBMap (string->value).

Other confs could be ported, but as I said, they are not complicated enough to make it worth it.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  69
  • Topics Per Day:  0.02
  • Content Count:  1315
  • Reputation:   372
  • Joined:  12/10/11
  • Last Seen:  

Just wondering, how would this affect script commands that relate to GM levels exactly?

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

To provide some compatibility, each group has a level property, so if scripts requires a GM level with getgmlevel(), it will compare it agains a level of the group player belongs to. For example, "admin" group could have level=99, and "players" group level=0.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  69
  • Topics Per Day:  0.02
  • Content Count:  1315
  • Reputation:   372
  • Joined:  12/10/11
  • Last Seen:  

To provide some compatibility, each group has a level property, so if scripts requires a GM level with getgmlevel(), it will compare it agains a level of the group player belongs to. For example, "admin" group could have level=99, and "players" group level=0.

Thanks!

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  11
  • Topics Per Day:  0.00
  • Content Count:  427
  • Reputation:   123
  • Joined:  11/17/11
  • Last Seen:  

Hmm I wonder if it worth, to give users the flexibility, to create custom settings for groups. For example "featureX: true", and script could query that. Of course script could also check for group name/id, but then what's with inherited groups also check for those?

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  392
  • Reputation:   285
  • Joined:  12/19/11
  • Last Seen:  

I don't think it's worth it. How many group will server have, on average? 5, maybe 10. A script command to get group_id would be enough. Then, if you'd like to enable some NPCs for specified groups only, you could do

if( getgroupid() == X || getgroupid() == Y ) ...

Link to comment
Share on other sites

×
×
  • Create New...