Appearance
Release 12
June 4th, 2021
Appearance
June 4th, 2021





SupportedLogicVersions ********when releasing the first game update that includes R12.**EntityActor message handling methods are now marked with various attributes instead of using magic names to identify the handlers. This makes the usage more explicit (and less prone to errors) as well as improves debuggability as the different handlers are now easy to identify in any stack traces, based on the method names alone. The old special method names are not allowed to avoid accidentally relying on them (the methods would not do anything anymore). [CommandHandler] replaces the old HandleCommand()[MessageHandler] replaces the old HandleMessage()[EntityAskHandler] replaces the old HandleEntityAsk()[EntitySynchronizeHandler] replaces the old HandleEntitySynchronize()[PubSubMessageHandler] replaces the old HandlePubSubMessage()PlayerEventBase instead of PlayerEventLogEntryPayload, and the event types need to have the [AnalyticsEvent(...)] attribute.EventTitle property has been removed. By default, the name of the event class is used to determine the title, but to use a custom title, the displayName parameter can be given to the AnalyticsEvent.playerModel.EventStream.Event(...) instead of playerModel.ServerListener.OnLoggableEvent(...).[MetaImplicitMembersRange] and [MetaImplicitMembersDefaultRangeForMostDerivedClass] attributes are required on ImplicitMembers-flagged serializable base classes. See the section [MetaSerializable] Attribute in Deep Dive: Data Serialization for more information. ImplicitMembers.pager_targets map are now pagerduty_alertmanager_key, pagerduty_cloudwatch_key, opsgenie_alertmanager_key, and opsgenie_cloudwatch_key. All other PagerDuty and Opsgenie keys in configurations have been deprecated. _alertmanager_ keys are used to configure Prometheus AlertManager and the _cloudwatch_ keys are used for AWS CloudWatch Alarm configurations. These are separated as the paging system side configurations are often different (e.g. PagerDuty requires the integration to be specifically of type CloudWatch for CloudWatch integrations, whereas Prometheus AlertManager integrates through a more generic integration point).GameDatabase class, and all Metaplay query code is in MetaDatabase class. The SDK database queries can now be performed with MetaDatabase.Get().SomeQueryAsync() and game-specific queries with GameDatabase.Get().SomeCustomQuery(). CloudCore and Game.Server project sources have been split to Metaplay/ for Metaplay SDK source files and Game/ for any game-specific source files, improving the core vs userland separation.game_specific folder by the same component file name. Integration hooks for existing components provided through the new integration api. Customization documentation here: Customizing the LiveOps Dashboard FrontendMetaDatabase.Get(QueryPriority.Xyz). For any expensive or long-running queries, QueryPriority.Low should be used.MainGameConfigBuilder class has been introduced, which takes care of building and creating a binary archive of MainGameConfig. This clarifies the separation of the offline build step and the runtime loading (from binary archive). The class and the related GameConfigBuilderServices class are both userland classes and can be modified according to the game's needs.GameConfigBuilder MonoBehaviour / prefab). This significantly simplifies the implementation and usage of the feature.GoogleSheetFetcher now uses more efficient batch fetching of multiple sheets in a single operation. Use batch fetching in the example project. The fetcher (including the related DLLs) now lives under Editor/, so it doesn't get included in the builds.IOnDeserialized interface has been replaced by a [MetaOnDeserialized] attribute that can be used on methods of a serializable type. The new attribute works also on nested objects, unlike IOnDeserialized which was only called for the top-level deserialized object.[MetaOnMemberDeserializationFailure] attribute allows handling deserialization failures of individual members. This enables player and guild event logs to tolerate the removal or a backwards-incompatible change of an event type while still leaving the player or guild entity otherwise usable.Random Players and Random Guilds lists that were shown on the Players and Guilds Dashboard pages are now hidden behind the "Developer Mode" toggle - they were not particularly useful or interesting to non-developers.StringId interning code has been optimized to not allocate any memory for already-interned values: previously unnecessary memory allocations happened during the interning.GameOnSessionStarted method has been added to PlayerModel. This method is invoked when a player logs in and starts a session, as opposed to the existing GameOnRestoredFromPersistedState method (previously called GameOnStateRestored) which is called whenever the PlayerActor is woken up for any reason (including due to access from the LiveOps Dashboard).
Broadcasts and Push Notifications dashboard pages have been re-worked to make them more consistent and easier to use.

More tooltips on various times and durations all over the LiveOps Dashboard to avoid doing mental math!

Player's login history now includes their locations if you have IP Geolocation enabled.
)
Broadcast Log on the Dashboard's Player Details page shows which broadcasts a player has or has not received.

Infrastructure and Helm chart compatibilities for this release:
infra-modules version 0.1.2 or later for infrastructuremetaplay-gameserver Helm chart version 0.2.0 or later for deploymentinfra-modules version 0.1.4 or later for infrastructuremetaplay-gameserver Helm chart version 0.2.2 or later for deployment[MetaOnMemberDeserializationFailure] attribute for member-level deserialization failure handling.MetaplaySDK.RunOnUnityThreadAsync for deferring Func<>s to Unity thread.MetaplaySDK.LocalizationManager to manage OTA updates to localization files.MetaplaySDK in the running editor to observe guild state.meta-time component that replaces the previous time-ago and duration components.ConfigParser.RegisterParseFunc is now private. Config library reference id parsers are registered automatically. Custom config parsers must be now be registered in CustomConfigParsers.RegisterCustomParsers (called from LogicInit) with ConfigParser.RegisterCustomParseFunc.Global singleton registry class, along with all usage of it.[CommandHandler], [MessageHandler], [EntityAskHandler], [EntitySynchronizeHandler], [PubSubMessageHandler]. These replace the old magic-named methods HandleCommand(), HandleMessage(), etc. The magic-named methods are no longer allowed (to avoid accidentally relying on it).GetAll method in GameConfigLibrary<TKey, TInfo> (for IGameConfigLibrary) with an EnumerateAll method that doesn't construct a new collection, and a GetInfoByKey method for getting a single item.PlayerModelBase.PlayerId to make it predictably available.IOnDeserialized interface with a [MetaOnDeserialized] attribute for methods, which supports on-deserialization hooks also for nested objects instead of only the top-level deserialized object.MetaSerializableFlags.ImplicitMembers, a [MetaImplicitMembersRange(start, end)] is now required on base classes with data members. It is optional on the ultimate concrete class, but if omitted, [MetaImplicitMembersDefaultRangeForMostDerivedClass(start, end)] must be present on a base class or interface. The purpose of these range allocations is to allow adding members to base classes without changing the implicitly-tagged members on derived classes.[IgnoreDataMember] in any step of the ancestor chain.[Sensitive] fields, not just strings.PlayerModel. Remove PlayerAvatar: move player profile info into PlayerModel and resources into PlayerWalletModel.navigation.js.ClusterConfig.GetNodeShardIds() which caused some node loss to not properly trigger Entity subscription loss events with some cluster topologies.