Difference between revisions of "Game Cloud"

From Virtual World Web Wiki
Jump to: navigation, search
Line 170: Line 170:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
When creating an interaction this way you can also optionally specify a group identifier to which the user must belong for the Interaction to be visible. You can also optionaly specify a [[CSS Selector]] which must match the participant's DOMController node in the scene. This allows for all kinds of clever ways of setting up who can see what interactions. See [[Cloud Global]] for more information on <code>Cloud.RegisterInteraction</code>.
 +
 +
You can also use [[ParticipantExtended]]'s <code>RegisterInteraction</code> method to register an interaction visible to only one participant.
  
 
==== Engagements ====
 
==== Engagements ====

Revision as of 18:56, 11 September 2019

The Game Cloud is a Layer Two component that extends your server to add many common massively multiplayer role playing game (MMORPG) features as well as a suite of server world scripting extensions that simplify game programming.

Game Cloud Scripting

The Game Cloud offers a large extension to the server JavaScript environment. The main API access points are through the two global objects Cloud and Bot. I will provide scripting examples throughout this document. For more information about writing scripts for use in the world see Scripts and the World Scripting Reference.

Game Cloud Applications

The Game Cloud groups configuration and data storage into containers called Applications. An application can be developed, configured, and tested on your development server, and then published to your live server when you're ready. All of the application's associated objects move with the application as a single unit when transferred.

Developing an Application

Game Cloud applications are created and configured mostly through the Admin Web. Expand Game Cloud on the left navigation menu, and select Applications. Create a test application to get started. See Identifiers and Scope below for advice on selecting a good identifier for your application.

Once created, you can begin creating other Game Cloud objects (features) that will become part of your application. The objects you create will then be available for your world scripts to interact with. More complete examples of how this works will be given below.

Identifiers and Scope

The Game Cloud makes heavy use Identifiers which are strings of text that uniquely identify some object within a scope. Your application will have an identifier, as will most of the things you create within your application.

Good identifiers should use namespacing to help ensure they are unique. Identifiers should not contain spaces. I recommend you use a format like this:

company.application.feature.name

For Example

vww.ref.quests.firstquest

This helps ensure that things created by different companies or teams don't interfere with each other.

Generally speaking, identifiers are global in scope. This means they should be unique across all applications on your server. This is because an application groups objects for transfer, but does not provide a naming container. This is so that scripts and features from one application can interact with scripts and features from another application.

Data Storage and Scope

The Game Cloud offers several ways for your scripts to store and retrieve data. These are explained in Metadata and Data Storage sections. Data storage is always associated with (scoped to) an application. When a script wants to work with application data, it must first set an application context like so:

Cloud.SetApplication("vww.ref.apps.example");

Generally, application data is considered to be "server local". This means that your application's stored data is not transferred between servers with the application. This is because the data stored by your scripts represents the runtime state of your world. What is transferred is the ``configuration`` of your Game Cloud features and also any Metadata stored with your application.

Application Features

Metadata

Application Metadata is a simple way for you to set some key / value pairs in the admin that will be available to your script at run-time. These values cannot be changed by your scripts. You can think of these as configuration values. They are configured on your application's Summary tab.

Your scripts must first set their application context, and then can query these values like so:

Cloud.SetApplication("vww.ref.apps.reference");
 
var message = Cloud.GetMetadata("StartupMessage");
 
Debug.Log("Starting up with message: " + message);
Chat.GetLocalChannel().Broadcast(message);

The example above shows how the value of the StartupMessage metadata item can be retrieved and used to broadcast a chat message into the instance local chat. For more information see Cloud Global, Chat Global, ChatChannelExtended and Debug Global in the World Scripting Reference.

Data Storage

Application Data Storage allows your scripts to store and retrieve key / value pairs associated with different objects. There are three different stores of application data:

Application Global Data: Stored globally for your entire application. Their keys must be unique within the scope of your entire application. Use the DataExists, GetData, SetData and DeleteData methods on the Cloud Global object.
Persona Scoped Data: Stored for each Persona (avatar). This allows you to store information on a specific character in the game world. Their keys must be unique withing the scope of a single persona. Use the DataExists, GetData, SetData and DeleteData methods on any ParticipantExtended object.
Account Scoped Data: Stored for each user account. This allows your application to store some value shared among all Personae (avatars) of a user, so no matter which avatar they're logged in as, these values will be available. Their keys must be unique withing the scope of a single user account. Use the AccountDataExists, GetAccountData, SetAccountData and DeleteAccountData methods on any ParticipantExtended object.

Your scripts must first set their application context, and then can work with these values like so:

Cloud.SetApplication("vww.ref.apps.reference"); // set your application context
 
var maxPlayers = Number(Cloud.GetMetadata("MaxPlayers"));
Log.WriteDebug("Starting up. Maximum Players: " + maxPlayers);
 
Instance.OnEnter = function(/*ParticipantExtended*/ part){
    // A new participant has joined the scene
    if(Cloud.DataExists("PlayerCount")){
        var count = Number(Cloud.GetData("PlayerCount")) + 1;
        if(count >= maxPlayers) {
            part.SendChatMessage("Sorry, only " + maxPlayers + " players allowed.");
            return;
        }
        Cloud.SetData("PlayerCount", String(count));
        part.SendChatMessage("Welcome, there are " + count + " players.");
    }else{
        Cloud.SetData("PlayerCount", "1");
        part.SendChatMessage("Welcome, you are the only player.");
    }
 
    part.SetData("Playing", "true");
    Chat.GetLocalChannel().Broadcast(part.Name + " joined the game!");
 
    if(part.DataExists("PlayCount")){
        var plays = Number(part.GetData("PlayCount")) + 1;
        part.SetData("PlayCount", String(plays));
        part.SendChatMessage("You have played before.");
    }else{
        part.SetData("PlayCount", "1");
        part.SendChatMessage("This is your first play.");
    }
};
Instance.OnLeave = function(/*ParticipantExtended*/ part){
    if(!part.DataExists("Playing"))
        return;
    part.DeleteData("Playing");
    Cloud.SetData("PlayerCount", String(Number(Cloud.GetData("PlayerCount")) - 1));
}

The example above shows a simple data access example that limits the number of players that can be involved in some activity. When a user enters the room the OnEnter event fires. We check if the global application data contains a PlayerCount key/value pair, and if so, we increment it, otherwise we initialize it to 1. If there have reached the configured maximum number of players, we abort, otherwise we execute similar logic to keep track of how many times this particular player has played our game. We mark the player as "Playing" so that when they leave we can decrement the global PlayerCount. This code does not demonstrate working with account scoped data, but it works the same as the persona scoped data, except as explained above you use the the GetAccountData, SetAccountData, AccountDataExists, DeleteAccountData methods on ParticipantExtended.

Debugging Data Storage

You can view and manipulate stored data via the Admin Web. Application global data can be found on the App Data tab of your application in the Game Cloud Applications section of the admin. Account and Persona scoped data can be found by looking up the account or persona, and then selecting Data Entries from the Game Cloud tab-drop-down.

Dependencies

You can mark any Layer One object as a dependency of your application. This serves two purposes: First, it ensures the object will be transferred with your Game Cloud application when it's transferred between servers. So if your application expects certain scenes, object types, to be available, you can make sure they're copied with your app. Second, it allows you to specify an identifier so the object can be more easily referenced from script. Many Game Cloud methods take object type IDs (GUIDs) as parameters. These are difficult to recognize, type, and work with. Dependencies help with this.

For example, let's suppose you wanted to instantiate a Primitive Cube object with Object Type ID 82c5194e-814b-11e8-a953-000d3af7ccfb into the root of the scene:

Cloud.Instantiate(Instance.Scene, "82c5194e-814b-11e8-a953-000d3af7ccfb");

That's great, but hard to read, and you can't be sure this object will be available on the server. If you create a dependency for this object type, and give it a name, let's say vww.ref.dep.primitivecube, then we can refer to it in script by using the Cloud.Map method, which maps an identifier to its object GUID.

Cloud.Instantiate(Instance.Scene, Cloud.Map("vww.ref.dep.primitivecube"));

This object type (the Primitive Cube) is now guaranteed to be transferred between servers along with your application. You can also always change which object an identifier refers to without having to update your code, since your code is no longer directly referencing GUIDs.

Groups

You can mark a Layer One Entity Group as important to your application. It will be included as a dependency of your application and transferred between servers along with your application. You can then refer to this group by its identifier from script. For example, if you added the "Admin" system group to your application and gave it an identifier like vww.ref.groups.admin, you could then refer to it from script like so:

Instance.OnEnter = function(/*ParticipantExtended*/ part){
    // A new participant has joined the scene
    if(part.CheckGroup("vww.ref.groups.admin")){
        part.SendChatMessage("Welcome back. You have admin access.");
    }
};

Please note: you cannot use the JoinGroup or LeaveGroup methods of the ParticipantExtended to affect groups that are marked as protected in the admin. This prevents a script from making a user an Admin, or revoking a user's developer role for example.

Abilities

Abilities are a powerful feature of the Game Cloud. An ability is something the user can ***do***, some action they can take. Abilities are actually defined by Layer One, but they're exposed for easy scripting and used heavily by the Game Cloud.

An ability has the following properties:

Identifier used to refer to the ability within the Game Cloud
Ability Identifier Used to create the Layer One ability. The Ability Identifier is a translation string, and becomes the display name of the ability in the UI.
Ability Group Places the ability into the ability tree in some group. Groups can help to enable / disable groups of related abilities at once and help with visual grouping in the UI.
Cooldown The number of seconds before the ability can be used again.
Icon Resource An image used for the ability on a quickbar or ability book in the UI.
Metadata Name value pairs that are delivered along with the ability to the client, and help the UI decide how to display them.

Ability Groups, which can also be defined on the Abilities Tab of your application allow you to create visual groupings of abilities in the UI.

There are 2 ways that a user can be given abilities from the Game CLoud:

Interactions

Interactions are a way of associating abilities with objects or NPCs in the scene. Generally, you specify a CSS Selector which selects objects in the scene you want to be interactable, and then specify which ability to attach. There are two ways to do this, either globally for all participants in the scene, or directly to a specific participant. So for example, you could specify that all boxes in the room, should have an "open" interaction, for everyone. Or you could specify that one specific participant should be able to "sit" on chairs in the scene.

Here's a simple example:

/**@type {InteractionMappingExtended}*/
var interaction = Cloud.RegisterInteraction(".openable", "vww.ref.abilities.open");
 
interaction.OnInteraction = function(/*ParticipantExtended*/part, /*DOMObjectExtended*/ target){
    part.SendChatMessage("You open the box. There's nothing inside.");
    Log.WriteDebug("The user clicked on box with ID " + target.ID);
}

When creating an interaction this way you can also optionally specify a group identifier to which the user must belong for the Interaction to be visible. You can also optionaly specify a CSS Selector which must match the participant's DOMController node in the scene. This allows for all kinds of clever ways of setting up who can see what interactions. See Cloud Global for more information on Cloud.RegisterInteraction.

You can also use ParticipantExtended's RegisterInteraction method to register an interaction visible to only one participant.

Engagements

When a user enters various states in an engagement, they can have specified abilities added, removed, enabled or disabled. This is helpful for making the special abilities available during an interaction, situation or quest of some kind.

For more information see Engagement System below.

Tokens

Quests

Achievements

Dialogs

Locks

Avatar System

Engagement System

Other Helpful Utilities

Bound Objects

Bound objects are simply a way to connect an Object Type to Worldspace so that whenever an Instance of a Scene is created, a Reference to the object is inserted into the DOM at the scene node. What's especially handy is that you can define an Area Group, add several several Scenes to it and then use this feature to cause any Object Type you like to be added to the scenes at run-time. You could also, for example, bind an Object Type to your system's Root World to cause it to show up in every scene in your world. This is especially helpful for Object Types that contain scripts that you want to appear in many (or all) scenes.