Appearance
Appearance
You may want to add features that speed up development or help debug the game, but shouldn't be made available on the version delivered to players. The Metaplay SDK provides a few different ways to prevent these features from leaking out of your development environment and into production.
The server only allows development-only features if the runtime option Environment:EnableDevelopmentFeatures
is set to true
. This is the case when running the server locally or in development environments but not in production or staging.
This flag affects many of the built-in Metaplay development features as well. For example, in-app purchases using the InAppPurchasePlatform.Development
pseudo-platform only work when this option is set to true
. Similarly, the development pseudo-platform for social logins also requires it to be enabled.
We recommend that your custom development-only features also be activated byEnableDevelopmentFeatures
option. Here's how you can do this:
EnvironmentOptions envOpts = RuntimeOptionsRegistry.Instance.GetCurrent<EnvironmentOptions>();
if (envOpts.EnableDevelopmentFeatures)
{
// Your dev-only code
}
else
{
// Deny request because development features not enabled
}
ModelActions
Metaplay provides a canonical way of marking development-only ModelAction
s by using the [DevelopmentOnlyAction]
attribute. Actions with this attribute are rejected on the server if EnableDevelopmentFeatures
is false
. Developer players can execute these actions regardless of the flag.
For example:
[ModelAction(ActionCodes.PlayerGainGemsDebug)]
[DevelopmentOnlyAction]
public class PlayerGainGemsDebug : PlayerAction
{
public int Amount { get; set; }
public PlayerGainGemsDebug() { }
public PlayerGainGemsDebug(int amount) { Amount = amount; }
public override MetaActionResult Execute(PlayerModel player, bool commit)
{
if (commit)
player.Avatar.NumGems += Amount;
return ActionResult.Success;
}
}
When implementing new model types, you need to implement this attribute check separately in each model actor's action validation. For example, for the player model, the PlayerActorBase
has a default implementation for ValidateClientOriginatingAction
, which checks if development actions are allowed:
protected virtual void ValidateClientOriginatingAction(PlayerActionBase action)
{
...
// Development actions are only allowed if so configured or if the player is marked as a developer
ModelActionSpec actionSpec = ModelActionRepository.Instance.SpecFromType[action.GetType()];
bool isDevelopmentOnlyAction = actionSpec.HasCustomAttribute<DevelopmentOnlyActionAttribute>();
if (isDevelopmentOnlyAction)
{
_log.Info("Executing development-only action: {Action}", action.GetType().ToGenericTypeString());
EnvironmentOptions envOpts = RuntimeOptionsRegistry.Instance.GetCurrent<EnvironmentOptions>();
if (!envOpts.EnableDevelopmentFeatures && !GlobalStateProxyActor.ActiveGameConfig.Get().IsPlayerDeveloper(Model.PlayerId))
throw new InvalidOperationException($"Client tried to run development-only action {action.GetType().ToGenericTypeString()}, but Development-Only actions are not enabled.");
}
}
(Parts marked with (...)
in the above snippet represent code omitted here for brevity.)
After you have implemented some testing features for your development environment, you can take a look at the Working with Developer Players page to see how to use test features in production environments.
Happy developing!