Table of Contents

, , ,

Start Page » Game Development with the Drag[en]gine » Service Listing » Mod.io

Mod.io

The ServiceModio Service Module provides access to the Mod.io. With this service module modding support is added to a game.

The service has the unique identifier Mod.io.

Support for this service is provided in the DragonScript Script Module using the class ServiceModio. This service implements the following interfaces:

Initialization

Automatic

The BaseGameApp class automatically creates the ServiceModio service instance if the following values are present in the configuration.ptree.xml file:

Tag Value
modio.gameid Game identifier
modio.appkey AppKey

The values for all these tags can be found on the game admin page.

An example configuration.ptree.xml file looks like his:

<?xml version='1.0' encoding='UTF-8'?>
<parameterTree>
   <boolean path='defaultEnableGI'>true</boolean>
   <boolean path='defaultEnableAuralization'>true</boolean>
 
   <!-- Mod.io -->
   <string path='modio.gameid'>1234</string>
   <string path='modio.appkey'>1234567890abcdef12345678</string>
</parameterTree>

If the provided initialization data is incorrect creating the ServiceModio service fails. This does not fail starting the application. Wait until all the services have finished initializing:

func void initGame()
   // super call starts automatic initialize services
   super.initGame()
 
   // add listener called once all services have finished initialize, no matter if successfull or not
   getBaseGameServices().setActionInitialized(BlockActionListener.new(block ActionEvent event
       // services have initialized
       launchApplication()
   end))
 
   // you can now do other things in the mean time like showing startup logos or videos
end   

You can then check first if the ServiceModio service has been created using:

   if getBaseGameServices().getModio() != null
      // ServiceModio is ready to be used
   end

Manual

The ServiceModio service can be manually created either by using the new constructor on the ServiceModio class using ServiceModio.InitParameters setup with the initialization data or by calling initModio() on BaseGameApp. Using initModio is preferred if manual creation is required.

ServiceUser

The service module provides user management support. Supported is logging in, logging, retrieving user information and retrieving user resources.

Login

The user can log in using different methods. The loginUser() call accepts a ServiceUserCredentials instance. Depending on the set parameters one of the possible login methods is used.

Authentication Provider

If in the credentials parameter the member authToken is set logging in is done using the authentication token from one of the supported Authentication Provider Service modules. For this to work you have to call getAuthToken() on the target ServiceUser to asynchronously retrieve an authentication token. Once received in the listener assign the token to the authToken member as-is.

ServiceMods

The service module provides modding support. This is done by adding virtual file system containers during the game engine launch process populated with all active modifications.

Modifications can be either unsubscribed, subscribed or disabled.

Unsubscribed modifications are not installed.

To install a modification call subscribeMod() using the modification identifier.

Once subscribed a call to activateMods() activates all subscribed and enabled modifications. These changes apply immediately. If the modification contains script changes you have to also warm-restart the game scripts using Engine.restart(). Warm restarting restarts the game but otherwise keeps the game engine loaded. Calling modHasMatchingFiles() helps to determine what files a modification contains to figure out what reloading or restarting actions are required.

Modifications can be temporarily disabled using setModDisabled(). Disabled modifications are still subscribed to but they will not be activated during activateMods() calls.

Installed modifications can be examined using getActiveMods() (which mods are active right now), getSubscribedMods() (which mods has the user subscribed to) and getSystemMods() (all modifications installed on the system no matter by which user).

Modifications can be browsed by calling listAllMods(). This lists modifications page wise and thus needs multiple consecutive calls to browse through large lists.

Modifications can also be rated by the user using submitModRating(). Ratings can be revoked by calling revokeModRating().

Offensive modifications can be reported using reportMod().

Modifications can be purchased using purchaseMod() if monetization is enabled for the game.

Subscribed modifications are downloaded and installed in the background. If you do not want this to happen, for example to not disturb a running game, you can call setPauseModManagement() to temporarily disable modification management. Background handling can only potentially cause problems if modifications are updated. Installing a modification does not cause problems since modifications need to be activated before they affect the game content.

DragonScript UI Classes

To make modding even easier for you a full set of UI panels and windows has been added. See MMPanelModManagement, MMWindowModManagement and the linked UI classes.

You only have to show an instance of MMWindowModManagement to provide all the functionalities outlined above. To alter the look of the window and panels add matching designers to your guitheme. See the modmanagement.guitheme.xml for the designers provided by the game engine. The respective UI class API documentation also contains the supported designers.

Script Modifications

To support script modding you have to do a bit more. An example you can find in DEMoCap.

Basically it is recommended to require modifications to subclass a Modification class of sorts provided by your game which is located in a specific namespace. This can look something like this:

namespace MyGame
pin Dragengine.Scenery
 
/** Base class for modifications creating specific script objects. */
class Modification
   func new()
   end
 
   /** Create element classes and add them to element class list. */
   func void createAndAddElementClasses(GameApp app)
   end
 
   /** Initialize game. */
   func void initGame(GameApp app)
   end
 
   /** Launch application. */
   func void launchApplication(GameApp app)
   end
 
   // the above are some example functions. add more depending on what modifications can modify in your game
end

You can then use introspection to find all active modifications by checking for which class in this specific namespace subclasses your Modification class. Code for doing this typically looks like this:

namespace MyGame
 
class MyGameApp extends BaseGameApp
   public var Array modifications
 
   public func new()
      modifications = Array.new()
      findModifications()
   end
 
 
   /** Find modificaitons. */
   private func void findModifications()
      var Class c, ns
      try
         ns = Introspection.Class.new("MyGame.Modifications")
      catch Exception e
         return
      end
 
      var int i, count = ns.getClassCount()
      var Modification mod
      for i = 0 to count
         c = ns.getClass(i)
         if c.getClassType() != Class.CLASS
            continue
         end
 
         try
            mod = c.getFunction("new", Array.new()).call(null, Array.new()) cast Modification
            if mod == null
               throw ENullPointer.new("constructor returned object")
            end
            modifications.add(mod)
         catch Exception e
            Engine.log("Failed loading modification class " + c.getName())
            throw e
         end
      end
   end
end

There are other possibilities to do this. For example you can also require modifications to provide an parameter tree file (.ptree.xml) in a specific directory. This file could then contain the fully qualified class name of the modification besides other information. Using introspection you can then load this class similar to the example above.