Skip to main content

Data Mutation & Model Extending

This page covers two related topics: mutating game data through Update() and Delete(), and extending models with domain behaviour as named RPC methods.


Data mutation​

When to use​

Use mutation when you need to persist changes to game data as state:

  • updating fields on objects returned by a query and saving them with Update()
  • applying a single inline update operation with Update(handler)
  • removing objects included in a selection with Delete()
info

This is the standard path when the outcome must be a stored state change that can later be retrieved and, where applicable, observed through the data layer.

Baseline rule​

PlayServ does not require special techniques to modify data. The flow is:

  1. retrieve data
  2. change fields using standard setters
  3. call Update()

Update a selection​

Select a set of objects, modify them, then persist the changes.

var women = PlayServ.Model<Player>()
.Where(player => player.Age > 18)
.Where(player => player.Gender == "Woman");

// update data
women.Map(girl => {
girl.Age = 18;
});
women[0].Age = 21;

// persist changes
women.Update();

Update with a handler​

You can also update using a single Update(...) call with an inline handler.

women.Update(girl => {
girl.Age = 18;
});

Delete​

To delete all objects included in the selection:

women.Delete();

Model extending​

When to use​

Use model extending when you need to attach domain behaviour to a model type and execute it as an RPC method:

  • defining behaviour as an extension method on a model via the RPC handler API
  • invoking that behaviour from client code on a retrieved entity — for example, player.Shoot(...)
info

Model extending allows gameplay operations to be expressed as an explicit action — a method — executed through the RPC handler pipeline, including abort behaviour.

How it works​

A model can be extended with custom RPC methods tied to an entity type — for example, NPC spawns, player shoots, chest opens. When these RPC methods execute, the model data acts as their context.

This path is appropriate when the operation represents a named action associated with an entity type, rather than a direct field update.

Server: define an extension method

PlayServ.Server.Model<Player>()
.DoShoot(vector => {
return false; // abort pipeline
});

Client: call the extension method

var player = await PlayServ.GetPlayer(playerId);
player.Shoot(vector3d);

Next step​

Continue with Query Language & Data Retrieval to understand how selections are constructed before mutation.

For related topics: