Skip to main content

Extending SDK Components

This mechanism allows developers to extend component behaviour without modifying the component itself.

When you need to extend a component's functionality, PlayServ uses handlers. A handler lets you attach custom logic to a component method without rewriting the component itself.


When to extend SDK components

Use component extending when you need to:

  • add custom rules around an existing component method — for example, allow or deny a join
  • introduce game-specific behaviour into a standard component flow
  • attach multiple independent handlers to the same extension point

Extend a component method

Example: extend the Join method for a group component.

// Extend the Join method
PlayServ.Server.Group("Game")
.ExtendMethod(PlayServ.Server.Group.Join, user => {
return false; // abort pipeline
})

// sugar
.DoJoin(user => { ... });

When the component executes the Join operation, the pipeline runs as follows:

  1. the component starts its processing cycle
  2. registered handlers are executed
  3. if a handler returns false, the pipeline stops
  4. the operation is cancelled
warning

A handler can abort the middleware pipeline. Returning false stops further processing and cancels the operation.


How handlers are executed

A handler is executed as part of a middleware pipeline. This is what makes it possible to register more than one handler for the same extension point and still keep each handler implementation minimal.


Works across components

This approach applies to any component. Some components reserve specific RPC methods in their API and explicitly mark them as extendable. These methods are used in the component's lifecycle and are invoked by the component itself under certain conditions.

note

Some components expose explicit extension points as reserved RPC methods. These methods are part of the component lifecycle and are invoked by the component itself under specific conditions.


Example: controlled Join for a match room

Scenario: you have a match room that players can enter. The client uses the standard Join() call, but the server must decide whether joining is allowed. Typical gameplay rules include:

  • the match has already started
  • the room is full
  • the user is banned from this mode
  • the user does not meet rank or level requirements

You do not replace the Groups component or introduce a separate custom RPC method. Instead, you extend the standard Join method and apply server-side rules while keeping the client call unchanged.

Flow:

  1. the client calls Join() on the target group
  2. the server executes the Join middleware pipeline
  3. if any rule fails, the handler returns false and the pipeline is aborted
  4. if all rules pass, the join is allowed and the handler completes

Client:

await PlayServ.Group("Game").Join();

Server:

PlayServ.Server.Group("Game")
.ExtendMethod(PlayServ.Server.Group.Join, user => {

// Gameplay checks
bool roomIsFull = false;
bool matchAlreadyStarted = false;
bool userIsBanned = false;
bool requirementsNotMet = false;

if (roomIsFull || matchAlreadyStarted || userIsBanned || requirementsNotMet)
return false; // abort pipeline -> Join is rejected

return true; // allow Join to proceed
})

// sugar: the Join handler itself
.DoJoin(user => {

// Optional: actions on successful join
// e.g. attach user to match context

return true; // accept user into the group
// return false; // reject
});

Next step

Continue with Groups to see how extendable methods fit into the full groups component lifecycle.

For related topics: