Wednesday, June 20, 2012

Creating an Online Multiplayer game in ABAP


Update: I've fixed the SAP Link Nugget, it should work fine now.


You'll need the following plugins to import the nugget:


Warning: This blog post is going to be techy, but also fun. I will show how I realized an idea that has been in my head for quite some time: creating a multiplayer game in ABAP. Who wouldn't want to play games with his/her colleagues while your boss thinks you're very busy working in SAP?




In this blog post we will create an ABAP version of good old Tic-tac-toe, where two users can compete for eternal fame.

To make it more interesting we'll teach the old ABAP dog a new trick: Instead of using a clumsy refresh button, the opponent will automatically be notified when the other player has made a move using a technique called long-polling.

The end result


First of all, have a look at the end result:

Why create a game in ABAP?

First of all: It's fun.

Secondly, it is always good to see how far you can push the technology you're using. The technique demonstrated here can also be applied to more serious applications, such as collaboration tasks or working with near-realtime information.

Even though the traditional SAP Gui isn't the major SAP UI that is was, the mechanism shown applies to any UI technology and can also be applied in Web Dynpro, the Web UI, HTML5, etc.

How does it work?

Note: I won't deal with the basics of a tic-tac-toe game, these are easy enough to figure out and if you're interested, just ask in the comments or take a look at the supplied ABAP source code.

Normally, in SAP Gui (but also a lot of other UI technology) the client will trigger a refresh to see if there is new data. This is a called Pull mechanism and it is ok for most data-driven applications. Not for collaboration tasks and near realtime communication.

The following figure shows how a Pull mechnanism works:



We have a SAP Netweaver ABAP server and two SAP Gui clients that both compete in the same game. As said, there is no real mechanism to push an event or data from the ABAP stack to a SAP Gui.

This means that the while the first player is making a move, the seconds player will have no way to know when it is his turn. Therefore, either a refresh button or a refresh at a fixed interval is needed for the game to progress.

Long-polling to the rescue

The following figure shows how long polling works:



The left figure shows how a traditional pull system would work. The client (SAP Gui) would periodically initiate a  refresh of data from the server to find out wether the other player has made a move yet. This will lead to a lot of unneeded data transfer and also a poor user experience: The user will have to press the refresh button a lot or have to endure a lot screen flicker while the Gui is polling for updates.

The figure on the right shows long polling. In this situation, the client (SAP Gui) is still iniating data transfer, but rather than answering the query directly, the server is going to delay until the desired situation is true: the other player has made a move, it is now your turn.

Note that all the while, the connection stays open. The connection can stay open indefinetely or or just a while longer than the expected time needed for a single move.

To make it more concrete, these are the ABAP objects used to create the game:



The UI for the user is in the ABAP program ZTICTACTOE, which consists of a few simple screens. Data is stored in two tables:

  • ZTICTACTOELOBBY is used in matchmaking. When a user starts the program, he is entered in the lobby and matched to an already waiting user. If there are no other players the user will wait until another player enters the lobby.
  • ZTICTACTOEGAME stores the gamestate: the state of the board, the current player etc.

The lock object EZTICTACTOE is what controls the long polling. The player that has to make a move has acquired a SAP lock on the game (as identified by the ID of the ZTICTACTOEGAME table). While that player is making a move, the ZTICTACTOE session of the other player will try to acquire the lock every second until he succeeds. If this is the case, the screen will be refreshed and the other player can make a move.

Show me the code

No blog post is complete without some source code:

The Function Module ZCHECK_GAME_LOCK tries to acquire a lock on the game, and will perform a while loop until it is successfull or it will give up after 60 seconds (MAX_SECONDS):

* for up to MAX_SECONDS, check if anyone has a lock on the given game
  WHILE sy-uzeit <= lv_end.
    WAIT UP TO 1 SECONDS.
    CLEAR: lt_enq.
    CALL FUNCTION 'ENQUEUE_READ';
      EXPORTING
        gclient               = sy-mandt
        gname                 = 'ZTICTACTOEGAME';
        garg                  = lv_argument
        guname                = '';
      TABLES
        enq                   = lt_enq
      EXCEPTIONS
        communication_failure = 1
        system_failure        = 2
        OTHERS                = 3.

    CHECK sy-subrc = 0 AND lt_enq IS INITIAL.
    RETURN.
  ENDWHILE.

The report will call Function Module Z_CHECK_GAME_MATCH in an asynchronous way:

  CALL FUNCTION 'ZCHECK_GAME_LOCK';
    STARTING NEW TASK 'WAITING';
    DESTINATION 'NONE';
    PERFORMING return_from_wait ON END OF TASK
    EXPORTING
      game_id               = gs_game-game_id
    EXCEPTIONS
      communication_failure = 1
      system_failure        = 2.

When the Function Module is finished (either it is the players turn or 60 seconds have passed), the return_from_wait routine is executed:

FORM return_from_wait USING taskname.
  SET USER-COMMAND 'REFRESH'.
ENDFORM.                    'return_from_wait

This routine simply refreshes the screen. Two outomces are possible:

  • If it is now the players turn, the UI will change accordingly and the user is allowed to make a move. 
  • If 60 seconds have passed and the other player still didn't make a move, the program simply calls the ZCHECK_GAME_LOCK Function Module again.

The complete source code can be downloaded here as a SAP Link nugget.

Have fun!

6 comments:

  1. I've tried to install the SAPlink nugget. But it dumps with the runtime error OBJECTS_OBJREF_NOT_ASSIGNED_NO. What I've found that in the Nugget the exported Function Group just contains:



    in another project that I've exported to compare the result it looked like:



    Perhaps you need to update to the latest SAPlink version from https://cw.sdn.sap.com/cw/groups/saplink.

    Best regards
    Gregor

    ReplyDelete
    Replies
    1. Gregor,

      I will have a look in the weekend. I must admit that i made the nugget some time ago, so I'll have to do some digging :)

      regards,

      Wilco

      Delete
    2. Whoop Whoop! That weekend took about a year! I've fixed the nugget, and tested it on a couple of ABAP Systems.

      Delete
  2. Very Interesting. I like it.

    Regards,
    Harshit Kumar

    ReplyDelete
  3. Hello;

    It looks like an excellent job, but the link seems to be broken. I'm not familiar with the nugget system, so can you re-upload it somewhere else?

    Thank you best regards

    ReplyDelete
    Replies
    1. I've fixed the link, so you can download the nugget again. A nugget is basically an xml file containing ABAP objects. This xml can be interpreted by the SAP Link program (see: https://cw.sdn.sap.com/cw/docs/DOC-145448). The cool thing about a nugget is that it can contain all kinds of ABAP Objects: Programs, Data dictionary definitions, Classes etc.

      Delete