Groups
Create parties, invite, accept, promote, assign roles and raid subgroups, with invitations that expire on the fixed step, hooks to veto decisions, and a lookup of an actor's group.
Groups and raids (social.party) #
What it is for #
social.party keeps the membership of player groups for a game: who leads, who is a tank, a healer or a damage dealer, who is online, which subgroup of a raid each member sits in, and which invitations are still open. One coordinator owns the membership of every group in its world, so an actor can never be in two parties at once. The kit holds rules and state only: it draws nothing, and it has no clock of its own (the game drives time with step).
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "social.party" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "social.party",
config: { "maxParties": 64, "inviteFrames": 3600 } }
It requires game.engine and provides the exclusive service social.party. A coordinator called default exists as soon as the kit starts, built from the configuration above.
First example #
<!-- test: kits/social_party/tests/social_party.rs::a_party_is_made_joined_and_projected_for_the_hud -->
social.party.request("default", { "op": "create", "party": "p", "actor": "ann", "role": "tank" })
social.party.request("default", { "op": "invite", "party": "p", "actor": "ann", "target": "bob" })
social.party.request("default", { "op": "accept", "party": "p", "actor": "bob", "role": "damage" })
social.party.groupFor("bob") // { "party": "p", "members": { "ann": {...}, "bob": {...} } }
social.party.groupFor("zed") // null: not grouped
Creating a second party for someone already grouped is refused.
Settings #
| Setting | Type | Default | Meaning |
|---|---|---|---|
maxParties | integer 1 to 256 | 64 | groups one coordinator can hold |
inviteFrames | integer 1 to 36000 | 3600 | lifetime of an invitation, in fixed simulation frames |
Unknown keys and out-of-range values are reported when the configuration is validated.
Services #
social.party(service), methods:create(id, config): makes another coordinator namedid(at most 128).configmay name apresetof the social_party_presets collection; the other keys ofconfigoverride it.request(id, command): runs a command on that coordinator and returns{ state, events }. An unknown coordinator is an error.step(id?): advances one fixed frame (defaultdefault) and returnsnull; invitations that reach their end vanish.groupFor(actor):{ party, members }of that actor in thedefaultcoordinator, ornull.ids(): the coordinator names.remove(id): deletes one and returns whether it existed.
Commands of request #
Every command is an object with an op; unknown fields are refused. Group commands carry party and the acting actor.
op | Fields | Rule |
|---|---|---|
create | role | makes the party, the actor leads; refused if the actor is grouped, the party exists or maxParties is reached |
invite | target | leader only; the target must be ungrouped; at most 40 open invitations; capacity 5 (40 in a raid) |
accept | role | the invited actor joins, taking the first subgroup with room |
leave | none | the first remaining member in alphabetical order leads if the leader leaves; an empty party disappears |
kick | target | leader only; the leader cannot be kicked |
promote | target | leader hands over leadership to a member |
role | target, role | the leader, or the member for themselves; roles are tank, healer, damage |
subgroup | target, subgroup | leader only; 0 to 7 in a raid, 0 otherwise; at most 5 per subgroup |
online | online | a member marks themselves online or offline |
configure | raid, loot | leader only; loot is personal or round_robin; leaving raid mode needs at most 5 members, all in subgroup 0 |
Read-only commands: status (the whole state), config, save, preview (runs a command on a copy and discards it), load.
Events #
Each decision that is not a read emits an event; the engine ticks alone expire nothing.
social.party.created { instance, preset }
social.party.removed { instance }
social.party.changed { instance, op, result }
social.party.refused { instance, op, by, reason }
Hooks and modding #
Two hooks let a game or a mod decide before the kit does:
social.party.create: asked before a coordinator is made; the payload hasinstance,presetandconfigand theconfigcan be changed. A cancelling tap makescreatefail with "creation refused".social.party.request: asked before every command that changes something; the payload hasinstance,opandcommand, and thecommandcan be rewritten. A cancelling tap returns{ ok: false, cancelled: true, by, reason }and emits the refused event.
Content can send a command with the verb social_party_request and test that a coordinator exists with the condition social_party_exists:
{ "social_party_request": { "instance": "default", "command": { "op": "leave", "party": "p", "actor": "bob" } } }
Engines #
The rules are the same Rust module on the web, in the native player and in the engine wrappers; there is nothing to draw.
When it does not do what you expect #
- An invitation never expires: nothing ticks it by itself. Call
steponce per fixed frame from the host that owns the group. acceptfails with "invitation absent or expired": more thaninviteFramessteps passed, or the actor was never invited.invitefails with "leader required": only the leader invites, kicks, promotes or configures.createfails with "party limit": raisemaxParties(at most 256).groupForonly looks at thedefaultcoordinator; userequestwithstatusfor others.- A load that does not match the kit configuration is refused and live state is kept.
Limits #
- Roles are
tank,healeranddamage; a party holds 5 members, a raid 40 in 8 subgroups of 5. - No chat, matchmaking or loot rolling:
lootonly records the chosen mode for the game to apply. - Reconcile actors with your server when you remove a coordinator.
Versions #
Kit version 1.0.0; it relies on game.engine 1.x. The party is part of the game save.