MUPE – Multi-User Publishing Environment
• MUPE is an application platform for rapid development of (mobile) multi-user context-aware applications and services.
• All parts of MUPE are written in Java (J2ME in clients)
• Everything is available under the Nokia Open Source license 1.0.
• MUPE server contains a simple virtual world, that is extended for each application.
• Scripted client UI script language – one client for all applications.
• Context information is added to the system from the network, or from each user client.
• Communications data compressed
• http://www.mupe.net
• http://pong.hiit.fi/mupedev
Key Features
• Optimised for the wireless network
• Minimized network data traffic (data compression) – compulsory for services whose price depends of it
• Optimised graphics (download at connection)
• Dynamic content (objects in the client can be referred at a later time)
• Persistent content – all content is serialized
• Only server side application programming
• Support for camera, sound, video with MMAPI
• Public screen support
Architecture
MUPE Application Platform Overview
Client MUPEServer
MUPECore
End-user devices:mobile phones
with J2ME
Middleware:connections
MUPE applicationfunctionality
Wireless network
Context
External producers
MUPE in more detail
Client Manager
World ManagerClient
Client Client Client
MUPEServer
Context Manager
Context producer
Client ManagerClient Manager
Context producerContext producer
Wir
ele
ss c
onn
ect
ion
Inte
rnet
MUPEMUPEMUPE
Connection middleware
MUPE Server1.21
How the server works?
• Clients make method calls to the server, and the server replies with a valid UI script.
• All connected users can get push messages if using TCP
Server: Static/Dynamic separated
• Clients make method calls to the server objects(or receives PUSH message)
• Server returns a valid UI script
• UIs can be created with XML – no need for programming/compilation
• Added application logic – Java (J2SE) programming
Java(J2SE)
DYNAMIC:Application
logic
XML
STATIC:UI &
Interaction
MUPE Application Programming
APIs
MUPEClient
Client APIclientMethodName(User caller, …)
XMLmethodName(User caller, …)
MUPE Server
internal
XML API
XML FileXML FileXML FileXML FileXML File
Structure
RoomUser Service
Base
World
* 1
*
*
1
0..1
owne
d by
cont
ains
ContextManager
Parser
1
1
Group
Item
Grouping-
Service
MessageMessaging-
Service
AbstractWorld
BaseExtensions
The basic MUPE Server
• A Fully functioning virtual world
• Easily customisable for new content with Java and XML (only server side programming needed – no J2ME programming required)
User Room Item Service
MUPE Virtual World Content Super Classes
Building a new MUPE Server
MyUser
MyRoom
MyContextManager
World
User
Room
ContextManager
AbstractWorld
The World Creation
Parser World
World()AbstractWorld()
World Object ID
Object Name Builder Methods
(Must be implemented in World)
0 World -
1 Room createDefaultRoom()
2 ContextManager createContextManager()
others - createWorldContent()
AbstractWorld
createDefaultRoom()
createContextManager()
createWorldContent()
User Connections – A new Instance of the User object
els
ew
here
World Object ID Object Name Builder Method
N User clientCreateUser
Parser
World
clientCreateUser()Phone
Push
• TCP allows the server to push information to each connected user
Each content object has 1 Class file and N XML files
MyUser Xml/content/MyUser/Description.xml
Creator.xmlEditor.xml
Etc.
• All objects that can have a UI must have an XML file
• All objects that can be created on the move must have creator.xml
• All objects that can be accessed directly must have description.xml
• All objects that can be edited must have Editor.xml
• Any number (or none) of other XML files allowed
• The superclass ones are used if none defined and needed
Creating Applications With MUPE
The connection (handled by the framework)
Client Server
clientSubscribe
XML UI: character creation
User::clientCreate {1} {$(nickname.text)}
XML UI: default room
reconnection
Client Server
clientActivate(caller, passcode)
XML UI: default room(or last room user was in)
Basic user creation
<template type='form' id=''><editfield title='Nickname' id='nickname' /><command type='ok' text='Ready'>
<g_send type='tcp' type='request'> User::clientCreate
{1} {$(nickname.text)} </g_send>
</command></template>
public User(User caller, Base location, String name)
XML Script for Character Creation
MUPE Server: Class Constructor
Customize the user creation
<template type='form' id=''><editfield title='Nickname' id='nickname' /><choicegroup id='type' title='Character type'>
<i_choice name='0' text='Fighter' /> <i_choice name='1' text='Thief' /><i_choice name='2' text='Wizard' /><i_choice name='3' text='Gnome' />
</choicegroup><command type='ok' text='Ready'>
<g_send type='tcp' type='request'> Player::clientCreate
{1} {$(nickname.text)} {$(type.selected)}</g_send>
</command></template>
public String Player(User caller, Base location,String nickname, int type)
XML Script for Character Creation
MUPE Server: Class Constructor
Player(…, 1, ”Bob”, 3)
Server Side Dynamic XML methods
<template type='form' id=''><string text=‘!#XMLGetContents#!’><command type='ok' text='Ready'>
<g_send type='tcp' type='request'>!#XMLGetID#!::someMethodname
{withStringParameter}</g_send>
</command>!#XMLGetRoomCommands#!
</template>
public String XMLGetContents(User caller)
Description.xml - A Room description with dynamic calls
MUPE Server: XML Embedded Method
public String XMLGetRoomCommands(User caller)
Allows the UIs to be created with references to the Java code.The code is evaluated prior to sending to the clients.
public String XMLGetID(User caller); // provided by the framework always
Server Side Dynamic XML methods
<template type='form' id=''><string text=‘You see a treasure chest. It is locked and made of
Iron.’<command type='ok' text='Ready'>
<g_send type='tcp' type='request'>133::someMethodname {withStringParameter}
</g_send></command><command type=‘menu’ text=‘pick lock’>
<g_send>133::clientAction {picklock}</command><command type=‘menu’ text=‘Hit’>
<g_send>133::clientAction {hit}</command><command type=‘menu’ text=‘pick up’>
<g_send>133::clientAction {pickup}</command>
</template>
The evaluated UI Script
Server Side Dynamic XML methods with parameters
!#XMLGetRoomCommands {param0} {param1}#!
<string id=‘!#param0#!’ text=‘!#param1#!’ /><command text=‘!#param1#!’>
<g_send>!#param0#!::clientMethod {1}</g_send></command>
public String XMLGetRoomCommands(long caller, long param0, String param1)
!#XMLGetRoomCommands {!#XMLGetID#!} {param1}#!
Server Side Dynamic XML file inclusion
<template type='form' id=''><string text=‘You see a treasure chest. It is locked and made of
Iron.’<command type='ok' text='Ready'>
<g_send type='tcp' type='request'>clientPoll
</g_send></command>
!#/commands.xml#!</template>
The evaluated UI Script
<command type=‘menu’ text=‘pick lock’><g_send>133::clientAction {picklock}
</command><command type=‘menu’ text=‘Hit’>
<g_send>133::clientAction {hit}</command><command type=‘menu’ text=‘pick up’>
<g_send>133::clientAction {pickup}</command>
Commands.xml:
parameterised XML files
<!--param0 = idparam1 = xparam2 = yparam3 = cropxparam4 = cropyparam5 = cropwidthparam6 = cropheightparam7 = framewidthparam8 = frameheightparam9 = any other attributes, such as selectable="true“param10 = Any hooks, atributes, etc inside the item-->
<image id='!#param0#!' x='!#param1#!' y='!#param2#!' resource='bm_all'
cropx='!#param3#!' cropy='!#param4#!' cropwidth='!#param5#!' cropheight='!#param6#!'
framewidth='!#param7#!' frameheight='!#param8#!' !#param9#! >
!#param10#!
</image>
getDynamicXML(<filename>, <caller>, <parms …>);
getDynamicXML(”ui_icon.xml”, this, XMLGetID(0),2,3,4,5,6,7,8,9,10);
The general problem
Client
ID=4 ID=st1
ID=kot
ID=bob
Server
RoomID=34
User ID=11
User ID=17
RoomID=31
User ID=7
User ID=67
ContextManager ID=2
?
?
How to know which object’s methods to call?
Easy solution: always use same id:s on client and server
Client
ID=11
Server
RoomID=34
User ID=11
User ID=17
RoomID=31
User ID=7
User ID=67
SuperUser ID=2
<image id=’11’ … />
What object is called on the server side?
Client Server
134::clientMakeSomething {param1} {234}
<I_settext id=‘str1’ text=‘update text’ />
Determine object - evaluate
<OBJECT ID>::<clientMethodName> {param1} {param2} … {param N}(exceptions: clientActivate, clientCreate, clientSubscribe, clientPoll)
Bag of tricks
WHO? How to get ID? Server/Client side determination?
Default Room 1 N/A
Me $(service.username) Client
This object !#XMLGetID#! Server
This (The object, inside which the part of the script is)
$(this.id) or $(this.<attr_name>)
Client
Selected Item $(selected.id) Client
ContextManager
2 Server
• The client needs to determine what object to call on theserver side
• Many things can be determined in the server side already
• UI/Interaction & User self need to be determined on the client side
Client Side Database $(service.<key>)
Key Description Value
service Service (server) name
String: “MupeDungeon”
Username The user ID in the server
Int:
15243
password password String:
“svfdgvqwefw”
For every application
Key Description Value
baseurl Where to get the content
String: “http://mupe.no-ip.org/mupe”
… … …
Application defined:
MUPE Applications
Game #1 MUPE Dungeon
Game #2: FirstStrike
Preview: FirstStrike with a public screen
Introduction to MUPE Client XML Scripts
Single UI
Template id=‘main’
type=‘form’
Template id=‘main’
type=‘canvas’
<template type='form' id=''><editfield title='Nickname' id='nickname' /><choicegroup id='type' title='Character type'>
<i_choice name='0' text='Fighter' /> <i_choice name='1' text='Thief' /><i_choice name='2' text='Wizard' /><i_choice name='3' text='Gnome' />
</choicegroup><command type='ok' text='Ready'>
<g_send type='tcp' type='request'>Player::clientCreate {1} {$(nickname.text)} {$
(type.selected)}</g_send>
</command></template>
Multi UI
Template id=‘main’
uigroup=‘g1’
Template id=‘chat’
uigroup=‘g1’
Template id=‘avatar’
uigroup=‘g1’
<setactive ui='chat' />
Update Item
Template id=‘main’
uigroup=‘g1’
Template id=‘chat’
uigroup=‘g1’
<string id=‘w’ />
Template id=‘avatar’
uigroup=‘g1’
<i_settext id=‘w’ ui='chat' text=‘hello, world’ />
Add UI
Template id=‘main’
uigroup=‘g1’
Template id=‘chat’
uigroup=‘g1’
<string id=‘w’ />
Template id=‘avatar’
uigroup=‘g1’
<template … />
Template id=‘newUI’
uigroup=‘g1’
Object Creation into template
<object_name id=‘<ID>’ … />
<string id=‘123’ text=‘Hello World.' />
<string id=‘123’><parms>
<text>‘Hello World.‘</text></parms>
</string/>
Object Attributes
<image id=‘1' resource='bm_all' x='5%' y='25%'>
<i_attribute name='description' value='Buy beer' />
</image>
System hooks
<i_hook name='on_resource_loaded'>
<i_equal attr='resource_id' value='res_tile'>
<i_event id='timebar' hook='start' />
</i_equal>
</i_hook>
Item hooks: phone buttons<i_hook ui='game_canvas' id='player' name='on_left_down'>
<!– handler -->
</i_hook>
name='on_left_down‘
'on_right_down‘
'on_up_down‘
'on_down_down‘
'on_fire_down‘
…
Standard (system provided) item hooks
<i_hook name='on_show'>
<i_hook name= 'on_hide‘
'on_select‘
'on_selector_enter‘
'on_selector_leave‘
…
Item hooks: custom
<i_hook name='timetick'>
<!– implement -->
</i_hook>
<i_hook name='timeout'>
<!– implement -->
</i_hook>
<i_event id='timebar' hook='timetick' />
<i_event id='timebar' hook='timeout' />
Timers: finalise
<g_starttimer id='timeout' times='8' time='1000' finalise='true'>
<i_event id='timebar' hook='timetick' />
<break />
<i_event id='timebar' hook='timeout' />
</g_starttimer>
Timers: initialise
<g_starttimer id='move_tmr' times='16' time='100' initialise='true'>
<g_allowuserinput value='false' />
<i_event id='timebar' hook='stop' />
<g_send type='tcp' >!#param1#!::clientMoveChar {!#param2#!} {!#param3#!}</g_send>
<break />
<i_setframe id='player' delta='1' />
<g_move id='player' deltax='!#param2#!' deltay='!#param3#!' />
</g_starttimer>
Item traversal: Foreach
<g_foreach group='maincanvas'>
<g_setselectable group='maincanvas' id='$(this.id)' value='false' />
</g_foreach>
Comparison operators
<i_equal id=’12’ attr='type' value='sound'>
<resource id='res_snd1' type='wave‘ url='$(reference.content)' />
<g_show group='object_open_view' id='av_play_button' />
<g_show group='object_open_view' id='av_stop_button' />
</i_equal>
Graphics: resources
<resource type='image' id='res_fighter' url='$(service.baseurl)/fight.png' />
<resource type='image' id='res_blackmonster' url='$(service.baseurl)/b_monst.png' />
<resource type='image' id='res_yellowghost' url='$(service.baseurl)/y_ghost.png' />
<resource type='wave' id='res_fireball_sound' url='$(service.baseurl)/fireball.wav' />
<resource type='wave' id='res_sword_sound' url='$(service.baseurl)/sword.wav' />
Graphics: images from resources
<image id='img4' x='30' y='130' cropx='16' cropy='32' cropwidth='16' cropheight='16' resource='res'/>
<image id='img2' x='40' y='40' resource='res' framewidth='16' frameheight='16' cropx='0' cropy='16' cropwidth='48' cropheight='16' selectable='true'/>
Use only a single resource for graphics if possible!
1
21 22 23 24 4
31 32 33 34
Animation
<i_setframe id=‘img2' delta='1' />
Items vs. Global
Dynamic update:<i_ …> = Item dependant (I.e. id=‘’)e.g. <I_settext id=‘string’ … >
<g_ …> = Global functionalitye.g. <g_allowuserinput />, <g_send … />
Tilemap<tilemap ui='game_canvas' id='map' x='16' y='16'
rows='9' columns='9' tilewidth='16' tileheight='16'
bgcolor='white' opaque='true'><i_addtile resource='res_tile' />
<i_addtile resource='res_forest' />
<i_row index='0' data='0,0,0,_,_,_,0,0,0' /><i_row index='1' data='0,1,1,_,_,_,1,1,0' /><i_row index='2' data='0,1,1,_,_,_,1,1,0' /><i_row index='3' data='_,_,_,_,0,_,_,_,_' /><i_row index='4' data='_,_,_,0,1,0,_,_,_' /><i_row index='5' data='_,_,_,_,0,_,_,_,_' /><i_row index='6' data='0,1,1,_,_,_,1,1,0' /><i_row index='7' data='0,1,1,_,_,_,1,1,0' /><i_row index='8' data='0,0,0,_,_,_,0,0,0' />
</tilemap>
Current Development
Location Extension for MUPE Client
• The J2ME location API (JSR-179) will be implemented
• Client can determine it’s location and call a method on server
• Client can use LANDMARKS to determine a known location prior to a method call.
• Two games in development highlighting these features
Bluetooth Extension for MUPE Client
• At least device discovery implemented• Can determine which other connected users are close by
• Games utilising this feature in development
Context Producers
Problem: Even though the client can determine the context, this is battery consuming
Solution: Make components to the network that can feed this information to the system
• Developments:• Ekahau Positioning• Bluetooth positioning
Central server for locating MUPE services
• A central MUPE search tool for locating the services.
Setup
• The big screen device is a standard MUPE client
• Run it on the Wireless Toolkit Emulator (version 2.2 or higher).
• Get UI files from http://www.mupe.net and place them on the folder wtklib\devices
• Specify from the WTK EmulatorProjectSettings… User Defined Key Value pair: [type - observer]
• Connect&use like any other client.
Public Screens
ObserverUser
ObserverRoom
PC
World
Public Screen Connections – A new Instance of the User object
els
ew
here
World Object ID Object Name Builder Method
N ObserverUser clientCreateUser
Parser
World
clientCreateUser()Phone
Content differentiation for Observerpublic String XMLGetContents(User caller) throws MupeException {
String retStr = "";
if(caller instanceof ObserverUser) {
// content for the public screen!
} else if(caller instanceof User) {
// normal Users
}
return retStr;
}