Lobby Example

This code example demonstrates how to create a typical multiuser lobby with Reactor. The lobby shows a room list that includes the number of users in each room, and provides a way to join and leave rooms.

Here's what the lobby looks like (try opening it in several browser windows if you want to see the effect of joining and leaving the rooms in the lobby):

Note: this example focuses on the Reactor API, and therefore shows only the bare minimum code required to create a lobby user interface.

The Code

Here's the code for the lobby:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package {
  import flash.display.Sprite;
  import flash.events.MouseEvent;
  import flash.text.TextField;
 
  import net.user1.logger.Logger;
  import net.user1.reactor.*;

  // A simple Union example application showing how to build a basic
  // lobby with Reactor.
  public class UnionLobby extends Sprite {
    protected var reactor:Reactor;
    protected var roomList:TextField;
    protected var joinRoomA:TextField;
    protected var leaveRoomA:TextField;
    protected var createTestRoom:TextField;
    protected var removeTestRoom:TextField;
    protected var testRoomID:String;
   
    // Constructor.
    public function UnionLobby () {
      // Create the interface.
      createUI();
     
      // Create the Reactor object and connect to Union.
      reactor = new Reactor();
      reactor.getLog().setLevel(Logger.DEBUG);
      reactor.addEventListener(ReactorEvent.READY, readyListener);
      reactor.connect("tryunion.com", 80);
    }
   
    // Event listener triggered when the connection is ready.
    protected function readyListener (e:ReactorEvent):void {
      // Ask to be notified when a room with the qualifier "lobbyexample" is
      // added to or removed from the server. In response to this
      // watchForRooms() call, the RoomManager will trigger
      // RoomManagerEvent.ROOM_ADDED and RoomManagerEvent.ROOM_REMOVED events.
      reactor.getRoomManager().watchForRooms("lobbyexample");

      // Register for the RoomManagerEvent.ROOM_ADDED and
      // RoomManagerEvent.ROOM_REMOVED events.
      reactor.getRoomManager().addEventListener(RoomManagerEvent.ROOM_ADDED,
                                                roomAddedListener);
      reactor.getRoomManager().addEventListener(RoomManagerEvent.ROOM_REMOVED,
                                                roomRemovedListener);
     
      // Create three example rooms that will appear in the lobby. Use a
      // RoomSettings object to specify that the rooms should not
      // "die on empty"; otherwise, each room would automatically be removed
      // when its last occupant leaves.
      var roomSettings:RoomSettings = new RoomSettings();
      roomSettings.removeOnEmpty = false;
      reactor.getRoomManager().createRoom("lobbyexample.roomA", roomSettings);
      reactor.getRoomManager().createRoom("lobbyexample.roomB", roomSettings);
      reactor.getRoomManager().createRoom("lobbyexample.roomC", roomSettings);
    }
   
    // Event listener triggered when a room is added to the
    // room manager's room list.
    protected function roomAddedListener (e:RoomManagerEvent):void {
      // There's a new room, so update the on-screen room list.
      updateRoomList();
      // Ask to be notified when the new room's client-count changes. Once the
      // room is observed, if other clients join the room, this client will
      // be notified. UpdateLevel values specify how much information this
      // client should be told about the room. This is a lobby, so we want
      // the room's occupant count only.
      var updateLevels:UpdateLevels = new UpdateLevels();
      updateLevels.clearAll();
      updateLevels.occupantCount = true;
      e.getRoom().observe(null, updateLevels);
      // Register to be notified any time the new room's client count changes.
      e.getRoom().addEventListener(RoomEvent.OCCUPANT_COUNT,
                                   roomClientCountListener);
    }
   
    // Event listener triggered when a room is removed from the
    // room manager's room list.
    protected function roomRemovedListener (e:RoomManagerEvent):void {
      // A room is gone, so update the on-screen room list.
      updateRoomList();
    }

    // The number of clients in one of the rooms changed, so update
    // the on-screen room list to show the new client count.
    protected function roomClientCountListener (e:RoomEvent):void {
      updateRoomList();
    }
   
    // Display the list of rooms in a text field.
    protected function updateRoomList ():void {
      roomList.text = "";
      for each (var room:Room in
                reactor.getRoomManager().getRoomsWithQualifier("lobbyexample")) {
        roomList.appendText(room.getRoomID()  
                            + " (" + room.getNumOccupants() + ")\n");
      }
    }
   
    // Join-Room button click listener.
    protected function joinRoomAClickListener (e:MouseEvent):void {
      var roomA:Room = reactor.getRoomManager().getRoom("lobbyexample.roomA");
      if (roomA != null) {
        roomA.join();
      }
    }
   
    // Leave-Room button click listener.
    protected function leaveRoomAClickListener (e:MouseEvent):void {
      var roomA:Room = reactor.getRoomManager().getRoom("lobbyexample.roomA");
      if (roomA != null) {
        roomA.leave();
      }
    }
   
    // Create-Room button click listener.
    protected function createTestRoomClickListener (e:MouseEvent):void {
      // Create a new test room with a random room id. By default, a client that
      // creates a room is granted permission to remove that room, so this client
      // will be allowed to remove the test room. Room-removal permissions
      // can be configured in Union Server's union.xml configuration file.
      testRoomID = testRoomID || ("lobbyexample.test" + Math.floor((Math.random()*100000)).toString());
      var roomSettings:RoomSettings = new RoomSettings();
      roomSettings.removeOnEmpty = false;
      reactor.getRoomManager().createRoom(testRoomID, roomSettings);
    }
   
    // Remove-Room button click listener.
    protected function removeTestRoomClickListener (e:MouseEvent):void {
      var testRoom:Room = reactor.getRoomManager().getRoom(testRoomID);
      if (testRoom != null) {
        testRoom.remove();
      }
    }
   
    // Create the user interface
    protected function createUI ():void {
      // A text field for the room list
      roomList = new TextField();
      roomList.background = true;
      roomList.border = true;
      roomList.x = 150;
      roomList.y = 20;
      roomList.width = 150;
      roomList.height = 100;
      addChild(roomList);
     
      // The join-room button
      joinRoomA = new TextField();
      joinRoomA.selectable = false;
      joinRoomA.background = true;
      joinRoomA.border = true;
      joinRoomA.x = 180;
      joinRoomA.y = 130;
      joinRoomA.width = 90;
      joinRoomA.height = 20;
      joinRoomA.text = "Join Room A";
      joinRoomA.addEventListener(MouseEvent.CLICK, joinRoomAClickListener);
      addChild(joinRoomA);
     
      // The leave-room button
      leaveRoomA = new TextField();
      leaveRoomA.selectable = false;
      leaveRoomA.background = true;
      leaveRoomA.border = true;
      leaveRoomA.x = 180;
      leaveRoomA.y = 160;
      leaveRoomA.width = 90;
      leaveRoomA.height = 20;
      leaveRoomA.text = "Leave Room A";
      leaveRoomA.addEventListener(MouseEvent.CLICK, leaveRoomAClickListener);
      addChild(leaveRoomA);
     
      // The create-room button
      createTestRoom = new TextField();
      createTestRoom.selectable = false;
      createTestRoom.background = true;
      createTestRoom.border = true;
      createTestRoom.x = 170;
      createTestRoom.y = 190;
      createTestRoom.width = 110;
      createTestRoom.height = 20;
      createTestRoom.text = "Create Test Room";
      createTestRoom.addEventListener(MouseEvent.CLICK, createTestRoomClickListener);
      addChild(createTestRoom);
     
      // The remove-room button
      removeTestRoom = new TextField();
      removeTestRoom.selectable = false;
      removeTestRoom.background = true;
      removeTestRoom.border = true;
      removeTestRoom.x = 170;
      removeTestRoom.y = 220;
      removeTestRoom.width = 110;
      removeTestRoom.height = 20;
      removeTestRoom.text = "Remove Test Room";
      removeTestRoom.addEventListener(MouseEvent.CLICK, removeTestRoomClickListener);
      addChild(removeTestRoom);
    }
  }
}