Appearance
Appearance
#if METAPLAY_R10_SEGMENTATION_AND_OFFERS_EXAMPLE
guards. See Implementing Player Segments for more information.Activables
to serve custom game-specific shop configurations to players. See Getting Started with In-Game Offers for more information.Numerous LiveOps Dashboard improvements. For example:
Player incidents have their own dedicated page. 3-02_at_16.32.45.pn
Player incident types are now clickable, so you can dig into the instances of the given type.
Game configs have a more mobile-friendly layout with collapsible sections for easier navigation around very large configs.
![](images/r10-configs-mobile-layout.png)
Game server cluster high level information added to the environments page
![](images/r10-server-cluster-info.png)
Game icon added to the top left corner for a bit of personality ✨
![](images/r10-game-icon.png)
The production environment is now highlighted with red color in order to avoid accidentally doing things in production when the intention was to modify another environment.
New data-based workflow and LiveOps Dashboard tools to easily work with roles and permissions. For more information, have a look at Dashboard User Authentication
![You can use the "assume roles" feature to quickly test how the dashboard looks for your custom defined roles.](images/r10-assume-roles.png)
You can use the "assume roles" feature to quickly test how the dashboard looks for your custom defined roles.
Added support for Sign in with Apple and Google Sign-In social logins.
The server can now resolve a player's country based on their IP address. See Implementing Player IP Geolocation.
Added support for IPv6-enabled dualstack load balancers for game servers. This can be enabled in the metaplay-gameserver Helm chart version 0.2.0 by setting Helm value experimental.gameServerIpv6Enabled
to true
. This requires that the underlying infrastructure is at infra-modules v0.1.2 or later (and more specifically metaplay-operator v0.0.7 or later). When enabled, the game server's load balancer will be changed from IPv4-only to dualstack mode and the game server deployment will register a [deployment]-ipv6.[domain]
DNS AAAA record for the IPv6 load balancer endpoint (for example, when enabled idler-develop.p1.metaplay.io
would additionally receive a idler-develop-ipv6.p1.metaplay.io
endpoint).
Updated Loki and Grafana in infra-modules v0.1.2 to enable more powerful querying of structured and unstructured logs. This is enabled by Loki 2.0's more powerful query time label extraction and parsing.
RuntimeOptionsBase
.load_config_file
references from Kubernetes and Helm providers to fix deprecated settings in providers. We have added minimum requirements of >=2.0 for both Helm and Kubernetes providers in the modules. If you have pinned either of the providers to pre-2.0 versions, you will need to un-pin them or move them to allow >=2.0 versions prior to updating.experimental.metaplayOperator
and experimental.healthzProbeEndpoints
parameters. The chart now assumes the presence of a metaplay-operator Kubernetes operator in the cluster and assumes the game server to implement standard /healthz
API endpoints for health checking. This affects only very old game server and infrastructure versions.database.backend
option and forces it to now always be MySql
. This means that the possibility to run Sqlite
backend is now deprecated and deployments in e.g. p1.metaplay.io
with the new chart will always use the MySQL database backends.The new EntitySynchronize allows performing operations on multiple EntityActors such that no other operation may intervene in the middle of the multi-entity operation. This is useful for building pseudo-transactionality between multiple entities, e.g., It does not guarantee that the operation is fully executed in error scenarios, though.
Metaplay now performs compatibility version checks with the infrastructure and Helm chart versions, to avoid potential issues from accidentally mixing and matching incompatible versions.
Role-based authorization for users of the Admin API and LiveOps Dashboard has been overhauled to provide a solution that is easier to configure and more clear to use for developers, CS agents, and CS admins.
Authorization for the Admin API and LiveOps Dashboard now takes place even when user authentication is disabled (eg: when developing and testing with a local server) making it much easier to spot authorization issues before they get to a deployed server. Developers are able to assume different user roles during testing so that they can see the LiveOps Dashboard exactly as their users would.
Akka.NET has been upgraded to v1.4.16, which significantly improves CPU usage in low-utilization situations. This should give more realistic CCU/core performance numbers in load tests at lower CPU utilization.
The serializer now supports nullable primitive types, such as int?
and F64?
.
Serialization limits of string and byte array sizes have been increased to 64 MB in order to help with large entity archive exports. At the same time, the server now has stricter size limit checks for payloads sent by the client.
MetaActionResult
is now a class to have a human-readable name and enable including parameters for more complex operations. Common results are instantiated as static readonly
members to avoid memory allocation overhead during runtime. The pre-allocated ActionResults can be defined like this in the game's ActionResult
class:
public static readonly MetaActionResult InvalidProducerId = new MetaActionResult(nameof(InvalidProducerId));
The underlying Entity system (mainly EntityShard
class) has been made more robust by protecting it against malformed requests and data in multiple places.
GameConfigs (including localization data) can now be persisted in binary, making the parsing much faster and allocate much less memory. It is also more robust as the potentially culture-dependent parsing can be done as a preprocess, and the runtime only loads the binary.
New GameConfigBuilder makes Google Sheet parsing more robust and easily customizable with game-specific parsing passes. The new builder is also much less dependent on Unity, making it easier to invoke from outside of Unity (eg, from the server or CLI-based tools).
The device Id is now remembered for each registered Firebase Messaging token. When switching player accounts by social authentication, the messaging token for the detached device is now correctly removed. This fixes notification campaigns sending duplicate notifications to devices that have switched accounts.
Notification campaigns now clean up unregistered Firebase Messaging tokens. Over time, this helps notification campaigns avoid spending unnecessary time attempting to send notifications to invalid tokens.
GameConfigLibrary
now holds the items in the same order as in the source items it was created from. Previously the order was unspecified (as in Dictionary
).
When constructing an OrderedDictionary
from an IEnumerable
and multiple entries have the same key, an exception is now thrown instead of keeping the last entry.
Core Metaplay parts of PlayerModel
have been split into a base class called PlayerModelBase
.
PlayerModel
were renamed: for example, PlayerModel.Tick()
is now called PlayerModel.GameTick()
.MetaMembersOrderKludge
attribute was added on PlayerModel
. You can remove this, but doing so will break protocol compatibility and require clients to be updated to the latest version.In-app purchases now support recording the actual resolved contents at claim time, for customer service purposes. See Getting Started with In-App Purchases, section Recording Resolved Purchase Contents.
In-app purchases now support dynamic purchase rewards, for features such as special offers. See Getting Started with In-App Purchases, section Dynamic-Content Purchases.
MetaActionResult
type is now a class, making it possible to attach more complex data to the results. ActionResult
s have been converted.GameConfigLibrary
is now well-specified, whereas previously it was whatever order the underlying Dictionary
provided. OrderedDictionary
now throws when constructed from an IEnumerable
that contains duplicate keys. Server/Game.Server/bin/PublicBlobStorage/GameConfig
by default, instead of Server/Game.Server/bin/GameConfigStorage
. GameConfigStorage
folder under PublicBlobStorage
and name it GameConfig
.InAppPurchases
database table from varchar(160)
to varchar(512)
. MessagingErrorCode
to better help diagnose configuration problems.PlayerModel.LastKnownLocation
indicates the country of the latest login. Disabled by default.HandlePubSubMessage(EntitySubscriber, Message)
, HandlePubSubMessage(EntitySubscription, Message)
handlers in entity actors for handling subscription and subscriber messages. If new handlers are not defined, the normal HandleMessage
and OnUnknownMessage
handlers are used as previously.int?
.CsvReader
now checks that each cell is fully consumed by its parser, and throws if it's not. This guards against buggy parsers and typos in configs. This is a potentially breaking change.OrderedDictionary(IEnumerable<KeyValuePair<TKey, TValue>>)
now throws if the enumerable contains multiple key-value mappings with the same key, instead of keeping the last one.BlobStorageOptions
, supporting also a separate private S3 bucket in addition to the public CDN S3 bucket.TransientError.Unknown
has been removed and replaced with TransientError.TlsError
that contains more information of the TLS handshake failure. Incorrect message order in the login sequence is now a SessionError
.static readonly
members, to avoid allocation overhead.SidebarNavGroupItem
component for better legibility and easier maintenance2020-12-15 03:00:02.468 Z
.EntityActor.Initialize()
for PersistedEntityActor
s.EntityActor.ExecuteInBackground()
now executes the operation on the current Actor context (assuming it's valid).None
could be persisted in database by SocialAuthenticateResolveConflict
when no pending conflict exists.PlayerModel.Language == null
, set it to default in PlayerActor.RestoreFromPersisted()
to ensure players always have a language set.