Appearance
Appearance
Introducing the new Metaplay Portal!
Metaplay Portal provides the following key benefits:
If you want to migrate existing projects to be managed from the portal or want to start a new project, please talk to us!
You can sign up to the portal at https://portal.metaplay.dev.
New feature: Server Errors on Dashboard adds a new page to see recent server errors directly from the LiveOps Dashboard for easy visibility into current internal server issues. Go to the overview page in the Dashboard to see the recent error count and to access the errors page.
Async Matchmaker Improvements: The async matchmaker has been improved to support more advanced matchmaking needs, such as supporting storing multiple matchmaker states per player, returning fake results when no suitable match is found, and more. See Deep Dive: Async Matchmaker for more information.
Major improvement: GameConfigKeyValue
Parsing from spreadsheets now supports nested members and multi-cell collections, bringing it to feature parity with GameConfigLibrary
sheet syntax.
MetaplayCoreOptions.supportedLogicVersions
to force a synchronized update of your game client and server.INFO
Note: If you have a service contract signed with Metaplay, your SDK integration has already been updated to reflect any backwards incompatible API changes in the Metaplay SDK in the SDK upgrade pull request of your project. Otherwise, please see the migration guide for a full list of changes, along with the HelloWorld and Idler samples for references on how to apply the changes.
We recommend upgrading to the latest versions of the infrastructure and game server Helm chart:
infra-modules
v0.2.12. metaplay-gameserver
v0.5.2. The minimum required versions are infra-modules
v0.2.2 and metaplay-gameserver
v0.4.4.
NodePackages
folder has been renamed to Frontend
as the old name was often confused with node_modules
.@metaplay/subscriptions
module is now completely standalone and can be used outside of the Live-Ops Dashboard project.@metaplay/subscriptions
module now supports passing an HTTP headers object to the fetcher policy when creating new subscription options. Good for passing authentication tokens in requests to external resources, for example.@metaplay/subscriptions
module now automatically delays data fetching when the user is not focused on the page. This reduces unnecessary web traffic and improves browser performance for heavy pages.MCard
has new data-testid
props for easier automated testing: card-loading-indicator
, card-title
, card-badge
, card-subtitle
.MOverviewCard
has new data-testid
props for easier automated testing: overviewcard-loading-indicator
, overviewcard-title
, overviewcard-subtitle
.MetaListCard
component now supports generics for better type safety and editor hints when working with list item templates.MButton, MIconButton, and MTextButton
components. These are styled button elements suitable for creating buttons and links in the Live-Ops Dashboard.MActionModal
, designed for actions requiring user confirmation.MActionModalButton
, a composite component that connects the functionality of MButton
and MActionModal
components.PlayerListCard
has been improved to show more useful information about players.@metaplay/subscriptions
module now has an initializeSubscriptions()
function that needs to be called before using any of the subscriptions. This is automatically done by the core SDK code.data-cy
have been renamed to data-testid
as the old naming schema was Cypress specific and we are now using the industry standard testid
.meta-button, meta-action-modal-button, b-button and b-link
components with the new MButton, MIconButton, MTextButton and MActionModalButton
components.@metaplay/subscriptions
module now correctly handles multiple chained dynamic subscriptions.EntityShardGroup
at a time and within each group, all entities and entity shards belonging to that group are initialized in parallel.PushNotification.UseLegacyApi
runtime option, see Working with Runtime Options for more info about runtime options.GameConfigLibrary
sheets.--MetaplayValidateXXX
command line flags. In this release the following validations were added: RuntimeOptions
: The various .yaml runtime options files embedded in the server image are now validated against the corresponding options classes in the code.DatabaseModelChanges
: Adding EFCore migrations after doing changes to the DB model classes is now enforced.GameConfig
: The built-in game config archive is validated against the config code by attempting to import the archive during the build.Backend/Deployments/
directory when integrating the Metaplay SDK.MetaActionResult
now has a virtual boolean IsSuccess
property which can be overridden in custom action result types. The SDK uses this to recognize successful action execution, instead of comparing directly with MetaActionResult.Success
as before..version
file in MetaplaySDK/.version
and not in the package root.FileUtil.WriteAllBytesAtomicAsync()
could sometimes execute really slowly on Windows due to the system File.Replace()
taking a long time in certain scenarios. It now uses File.Move()
which does not suffer from the same issues.Application._logger
now respects the logging configuration specified in the server's Logging
runtime options (such as the Json
log format), as soon as the runtime options have been loaded. Until now, it erroneously always used the default logging configuration. In practice this affected a few specific log messages logged from Application
and its subclasses like ServerMainBase
.UnityEngine.SystemInfo.batteryLevel
has been significantly reduced. Querying the battery level can be slow on Android devices.ModelJournal<T>.Follower.ConflictResolutionMode
has been removed and all journals assume ContinueEvenIfConflicts
.IEntityClientContext.OnEntityDetached
hook has been added to allow custom handling for entities becoming inactive for the client, such as in the case a Player leaves a Guild or leaves a certain Division entity.MultiplayerEntityClientContext.LatencySample.NetworkLatency
for observing network latency in MultiplayerEntityClientContext
when latency measurement is enabled.LatencySimulationMessageTransport
to allow simulation of latency. This can be used through MetaplaySDKBehaviour
or by injecting it using MetplaySDK.Connection.CreateTransportHooks
before MetaplayClient.Connect()
is invoked.AuthenticationType
is set to None
. You can also disable the ability for users to assume other roles in these environments.ClusteringMode.Disabled
option skips the initialization of the Akka.NET clustering. Useful for apps like BotClient that don't use clustering.PlayerSegmentSizeEstimatorActor
, NotificationCampaignJob
and AsyncMatchmakerActorBase
. This should result in less rejected players due to errors during segment size estimates, notification campaigns and async matchmaker player scans.metaplay_cluster_services_running_current
metric as it doesn't make much sense anymore.PlayerLocation
now contains the continent.EntityActor.OnSubscriberTerminated
and EntityActor.OnSubscriberUnsubscribed
hooks that are called in addition to the general EntityActor.OnSubscriberLost
.Dockerfile.server
now supports targeting a different platform/architecture than that of the build host. This is useful for the ability to build server images to be run in the cloud on ARM development setups. The target platform of the docker build can be specified by the --platform
flag.GoogleSheetFetcher
now always ensures it downloads the full sheet.private_blob_file_serve.read
that controls access to files served through the PrivateBlobFileServe. By default the permissions is granted to all default roles.--MetaplayValidateDatabaseModelChanges
. This is used by the docker build to catch missing migrations.--MetaplayValidateRuntimeOptions
. This is used by the docker build to catch options syntax errors during the image build.--MetaplayValidateGameConfig
for quick validation that a game config archive file deserializes properly. This is used by the docker build to catch outdated config archives during the image build.DEBUG
mode.RandomPCG.GetWeightedIndex()
now allows zero and negative weights without throwing, such elements are ignored by the method and can never be returned.MetaGeneratedUI
now allows you to exclude specific types from abstract fields by using the MetaFormExcludeAbstractType
attribute.LocalizationsBuild.BuildAsync(CancellationToken ct)
method, the new signature is LocalizationsBuild.BuildAsync(LocalizationsBuildParameters buildParams, CancellationToken ct)
.DnsCache.GetHostAddressesAsync
will now always return the loopback address when localhost
, 127.0.0.1
, ::1
, or [::1]
is resolved, regardless of what other local addresses correspond.PersistedMultiplayerEntityBase.ExecuteActionAfterPendingActions
for conveniently executing follow-up actions from ServerListeners.GameConfigKeyValue
sheets now require a header row specifying Member
and Value
columns. GameConfigKeyValue
sheets now ignore rows where the value cell is empty, leaving the C# member to its initial value. Previously it used to parse the member from the empty string. pnpm storybook
in the MetaplaySDK/NodePackages/MetaUiNext folder.INFO
Note: If you have a service contract signed with Metaplay, your SDK integration has already been updated!
To ensure your project has up-to-date migrations for the database schema, generate the migration code with the following:
# Install or update the EFcore tool:
Backend/Server$ dotnet tool install -g dotnet-ef
Backend/Server$ dotnet tool update -g dotnet-ef
# Then, generate the migration code:
Backend/Server$ dotnet ef migrations add MetaplayReleaseXX
Then, add the generated files into your project's source control. Note that the migration files may come up empty, depending on the features used by your game. If they are empty, you can safely discard the generated files instead. For example, using Git:
Backend/Server$ git add .
Backend/Server$ git commit -m "Database schema migrations"
The migration steps will be automatically applied when you deploy the updated game server into an environment.
If you are using Metaplay managed environments, you'll need to add a set of configuration files for the cloud environments.
Please follow the guide in Release 27 Migration Guide for Managed Environments to add the Helm values files for each environment and the runtime options files for the staging
and production
environments.
The GameConfigKeyValue
sheet syntax improvements involve certain changes to sheet content and potentially C# code.
Please follow the Release 27 Game Config Migration Guide.
MetaActionResult
Types MetaActionResult
has added a virtual bool IsSuccess()
method that returns true when the result should be considered successful. By default, only the predefined MetaActionResult.Success
is considered successful.
If you have any classes inheriting from MetaActionResult
, you should override the IsSuccess()
in them, if they can represent a successful result:
public class MySuccessActionResult : MetaActionResult
{
// This action should always be considered a successful one
public override bool IsSuccess() => true;
}
If you are specifying custom dashboard permission mappings in your runtime options .yaml files, add a mapping for the newly introduced permission api.system.view_error_logs
to control which roles can view the server error logs.
See Dashboard User Authentication for further information. When using the SDK-provided default roles, the permissions is automatically granted for GameAdmin
and GameViewer
roles and no further action is required.
The clustering initialization has been simplified:
Remove the InitClusterServices()
from your project, usually in ServerMain.cs
. The entities to initialize are now automatically detected.
If you have used any ClusterServiceLocal
at the end of the InitClusterServices()
list, these can be replaced with the following virtual methods:
protected virtual override Task StartApplicationAsync() { ... }
protected virtual override Task StopApplicationAsync() { ... }
Related to the above clustering simplifications, there were some modifications to how the server-side custom entities are configured.
If you use custom entities in your game, please follow the Release 27 Migration Guide for Custom Entities to update your custom entities to the new APIs.
References to the NodePackages
folder in the MetaplaySDK need to be updated to the new name of the folder Frontend
:
In pnpm-workspace.yaml
, replace
- MetaplaySDK/NodePackages/*
with:
- MetaplaySDK/Frontend/*
In vite.config.ts
, update path in eslintPlugin
exclude filters:
exclude: [
'**/node_modules/**',
'**/NodePackages/**', // Added our own monorepo packages to ESLint ignore list so they don't get linted twice.
]
with:
exclude: [
'**/node_modules/**',
'**/Frontend/**', // Added our own monorepo packages to ESLint ignore list so they don't get linted twice.
]
Check for any other references to the old NodePackages
directory and rename them to Frontend
as well. For example, the Visual Studio Code .code-workspace
file may contain such references.
In Dashboard/package.json
, apply the following diff:
@@ -1,18 +1,18 @@
{
"name": "game-dashboard",
"private": true,
"version": "1.0.0",
"license": "Metaplay SDK Software License",
"type": "module",
"engines": {
- "node": "18.x"
+ "node": "20.x"
},
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"lint": "eslint . --fix",
"backend": "dotnet run --project ../Server",
"bots": "dotnet run --project ../BotClient -MaxBots=10",
"test-unit": "vitest run",
"test-e2e": "cypress run"
@@ -21,36 +21,37 @@
"@metaplay/core": "workspace:^",
"@metaplay/eslint-config": "workspace:^",
"@metaplay/game-server-api": "workspace:^",
"@metaplay/meta-ui": "workspace:^",
"@metaplay/meta-ui-next": "workspace:^",
"@metaplay/subscriptions": "workspace:^",
"@metaplay/tailwind-plugin": "workspace:^",
"@metaplay/typescript-config": "workspace:^",
"@shoelace-style/shoelace": "^2.11.2",
"@vitejs/plugin-vue": "^4.5.2",
- "@vue/compat": "^3.3.11",
- "@vue/language-plugin-pug": "1.8.25",
- "@vue/runtime-dom": "^3.3.11",
+ "@vue/compat": "^3.4.19",
+ "@vue/language-plugin-pug": "1.8.27",
+ "@vue/runtime-dom": "^3.4.19",
"autoprefixer": "^10.4.16",
"cypress": "^12.17.4",
- "eslint": "^8.47.0",
+ "cypress-recurse": "^1.35.2",
+ "eslint": "^8.57.0",
"install": "^0.13.0",
"npm": "^9.6.7",
"pinia": "^2.1.7",
"postcss": "^8.4.31",
"pug": "^3.0.2",
- "tailwindcss": "^3.3.6",
+ "tailwindcss": "^3.4.0",
"typescript": "5.1.6",
- "vite": "^5.0.9",
+ "vite": "^5.0.12",
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-static-copy": "^0.17.0",
"vitest": "^1.0.4",
- "vue": "^3.3.11",
+ "vue": "^3.4.19",
"vue-router": "^4.2.5",
- "vue-tsc": "1.8.25"
+ "vue-tsc": "1.8.27"
},
"dependencies": {
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.6"
}
}
In Dashboard/vite.config.ts
, apply the following diff:
import { defineConfig } from 'vite'
import vue, { type Options as VuePluginOptions } from '@vitejs/plugin-vue'
import eslintPlugin, { type Options as EslintPluginOptions } from 'vite-plugin-eslint'
// https://vitejs.dev/config/
export default defineConfig({
+ define: {
+ __VUE_OPTIONS_API__: 'true',
+ __VUE_PROD_DEVTOOLS__: 'false',
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
+ },
plugins: [
data-cy
With data-testid
The Cypress-specific attribute data-cy
has been replaced with the more commonly used data-testid
across all components and tests. This is needed to enable migration to Playwright in the future.
Replace any usage of data-cy
with data-testid
:
In your dashboard components, replace component declarations like this:
SomeComponent(data-cy="my-id")
with this:
SomeComponent(data-testid="my-id")
In tests, replace queries like this:
cy.get('[data-cy=my-element]')
with this:
cy.get('[data-testid=my-element]')
button and modal
components with MetaUiNext components We are deprecating the following components in the near future. Replace all occurrences of the components in the list below, with the corresponding MetaUiNext components:
b-button
with MButton, MIconButton, or MTextButton
.b-link
with MButton or MTextButton
.b-modal
with MActionModal
.meta-button
with MButton, MIconButton, or MTextButton
.meta-action-modal-button
with MActionModalButton
or a combination of MButton, MIconButton or MTextButton
with the MActionModal
component.For a comprehensive guide on how to use these new components, run pnpm storybook
in the MetaplaySDK/NodePackages/MetaUiNext folder.