Table of Contents
The class
BigWorld
.Proxy
on the
BaseApp extends
BigWorld
.Base
to support
player-controlled entities. By deriving an entity from
BigWorld
.Proxy
, you can
implement player characters, their accounts, and any other relevant
player-controlled objects on the server.
An entity derived from
BigWorld
.Proxy
is created
from the database whenever a client logs in to the server. For details on
how BigWorld determines which Proxy to load, see User Authentication and Billing System Integration. Proxies created
in this way (see below for other ways of creating proxies) which have a
property called password
, will have the value of that
property set to the login password.
An instance of
BigWorld
.Proxy
needs neither
a cell entity, nor a client one. A proxy entity can be created using the
method
BigWorld
.createBase
, just
like any other entity. For more detail on this method, see Entity Instantiation on the BaseApp.
Like other base entities, saving and loading proxy entities from the database is possible. Initially, these reloaded proxy entities will be created without an attached client. An existing proxy can later hand its client over to the reloaded one, in which case the reloaded proxy will be the one handling the client connection.
This allows you to have, for example, an
Account
entity that people can log in to, and a
Character
entity that people can select from a menu
in order to use in the game.
To pass the control of a client from one proxy to another, use the
method giveClientTo
, as in the example
below:
clientControlledProxy.giveClientTo( nonClientControlledProxy )
Whenever a client moves between proxies, or the cell entity of the
proxy that a client is attached to is destroyed, the client receives a
call on onEntitiesReset
to clear out its current
knowledge of the world. This effectively interrupts all game
communications, and forces the client to refresh. If only the cell entity
has been destroyed, then the client's knowledge of its proxy is
retained.
If giveClientTo
does not succeed because of
a problem with the destination proxy,
onGiveClientToFailure
will be called on the
origin proxy.

BaseApp managing bases and proxies
Whenever a proxy with an attached client has a corresponding cell entity, an extra object called witness is attached to the cell entity.
This object manages the entity's AoI, and sends updates to the proxy, which forwards them on to the client.
The updates consist of the bulk of game-related messages, such as:
-
Entity position updates.
-
Entity property updates.
-
Method calls.
-
Space data changes.
-
Notifications of entities entering and leaving the AoI.
By default, every cell entity is considered to be controlled by the server. When an entity incorporates a witness object, it is considered to be controlled by the client attached to the corresponding proxy.
However, the control of an entity may be explicitly assigned and
queried, using the entity attribute .controlledBy
. This
attribute may be set to None, to indicate server
control, or to a BaseEntityMailBox
to indicate
control by the client attached to that proxy. Within this context, control
implies ownership of and responsibility for the entity's position and
direction. Clients (and proxies) are informed of changes to the set of
entities that they are allowed to control. Proxies may read this set
through their attribute wards.
When an entity is controlled by a client, setting the attribute
Entity
.topSpeed
to a value
greater than zero enables the physics checking. By default the
topSpeed
enables physics checking on all 3 axis,
however this may not always be appropriate. For example, if the gravity of
your game environment enables a Y-axis acceleration that results in a top
speed exceeding the maximum allowable X/Z-axis top speed. In order to
accommodate this there is a secondary attribute named
Entity
.topSpeedY
which takes
precedence when set to a value greater than zero.
topSpeedY
will only be used when both
topSpeed
and topSpeedY
are greater
than zero.
Entity movement is validated in the following ways:
-
Speed
The first check is regarding the speed, to ensure that it does not exceed
topSpeed
andtopSpeedY
. There is a small amount of variance allowed in speed to account for up to 150ms of network jitter. Care is taken so that this latency debt is not exploited by allowing the player to travel faster than the top speed for a brief period of time.
-
Geometry of the scene
The second check is made against the geometry of the scene, to ensure that the entity only leaves its current chunk through a well-defined portal.
In spite of being very fast, this check does have consequences for level design. Barriers that control character mobility must be represented at the level of chunks. For example, a chunk with a wall across it, and a door giving access to the other side, is not protected by this physics checking system. In order to implement this in a manner to enable physics validation, two chunks should be used one on each side of the wall, with the door as a portal between them.
-
Custom physics validator
If a custom physics validator has been developed, it will then be called between the top speed and the geometry checks. The custom physics validator is called with the following parameters:
-
Pointer to the entity.
-
Pointer to the vehicle (NULL if the entity is not on a vehicle).
-
The position to which the entity wants to move.
-
The time elapsed since the last physics check.
The custom physics validator should return true if the entity is allowed to move to the new position, or false if it is not allowed.
To install a custom physics validator, a CellApp extension module must be written. During the initialisation of the extension module, the global function pointer
g_customPhysicsValidator
(declared inbigworld/src/server/cellapp/entity.hpp
) should be set to point to the custom physics validator function. For more details, see Extending BigWorld Server. -
Other scenarios in which physics checking is applied include:
-
Control of multiple entities by the same client (such as wards).
-
Movement between vehicles (the ghost methods
onPassengerAlightAttempt
andonPassengerBoardAttempt
are additionally called). -
Movement to another space.
When a server script directly sets the position or direction of an
entity that is controlled by a client, the CellApp treats that as a
physics correction. A new position and direction (sometimes referred to as
the pose) are forced down to the client, and no
future position and direction updates are accepted until the correction is
acknowledged. This feature can be very useful for teleporting a player in
response to some action or event on the server. Notably, the methods
Entity
.teleport
,
Entity
.boardVehicle
and
Entity
.alightVehicle
also
adhere to this mechanism. Server-side teleports are the only way to move
an entity between spaces.
While in most cases movement controllers would also result in downstream-forced positions, their use on client-controlled entities is neither recommended nor supported, since they continually set the position via a system intended for one-off adjustments.
Due to the manner in which physics validation occurs, if a top
speed has been exceeded, the server will force a position update to the
client with the last known valid position. This however has the
unfortunate side effect of producing an entity which doesn't fall if the
top speed has been exceeded in the Y-axis. Setting the
topSpeedY
to be higher than
topSpeed
will help in this situation, but eventually,
the Y-velocity will be greater than topSpeedY
due to
acceleration due to gravity when falling for long periods.
In order to produce a work around for this, it is recommended to
write a custom physics validator while setting a large value for
topSpeedY
. The custom physics validator could then
perform its own validation and update the entity position with a
decreasing Y-position prior to returning false, and
the updated position would then be forced to the client.