package Screens { import fl.controls.Button; import flash.display.Sprite; import flash.events.*; import Services.*; import Services.Sounds.WeaponSoundObjects.UserChannels; /** * Controller for the view w_room. Responsible for: * - Updating LevelService with the proper data and number of players (level.users) * - Allowing users of a room to chat with each other * - Allowing the host (first person in room) to edit game properties * - Managing one host (in the event of players entering/leaving room) * - Starting a multiplayer game * * Links to: * <- LobbyScreen * -> MultiScreen */ public class RoomScreen extends Sprite { private var widget : w_room = new w_room(); //Graphical view for this screen private var usernames : Array = new Array();//Array of strings that are the usernames of the users in this room private var ready : Array = new Array(); //Array of the ready state of users private var host : Boolean; //Boolean indicating if this client is the host of the room // Services private var user : UserService = SystemController.getInstance().userService; private var client : ClientService = SystemController.getInstance().clientService; private var level : LevelService = SystemController.getInstance().levelService; private var panel : WeaponPanelService = SystemController.getInstance().weaponPanelService; /** * Initialize the RoomScreen */ public function RoomScreen() { addEventListener(Event.ADDED_TO_STAGE, init); addChild(widget); widget.s_difficulty.minimum = 1; widget.s_level.minimum = 1; widget.s_level.maximum = 10; widget.s_players.minimum = 2; widget.s_players.maximum = 4; // Add event listeners widget.input_txt.addEventListener(KeyboardEvent.KEY_DOWN, checkEnter); widget.chat_btn.addEventListener(MouseEvent.CLICK, sendChat); widget.back_btn.addEventListener(MouseEvent.CLICK, gotoLobby); widget.s_difficulty.addEventListener(MouseEvent.CLICK, updateSettings); widget.s_level.addEventListener(MouseEvent.CLICK, updateSettings); widget.s_players.addEventListener(MouseEvent.CLICK, updateSettings); widget.start_btn.addEventListener(MouseEvent.CLICK, playerReady); widget.start_btn.enabled = true; //TODO disable this button for the host until all other users are ready widget.addChild(SystemController.getInstance().weaponPanelService.widget); } /** * Set some properties before the screen is displayed * @param e - Event.ADDED_TO_STAGE */ private function init(e:Event):void { widget.x = stage.stageWidth / 2; widget.y = stage.stageHeight / 2; widget.chat_txt.text = ""; widget.chat_txt.verticalScrollPosition = widget.chat_txt.maxVerticalScrollPosition; widget.addChild(panel.widget); panel.update(); if(!host){ widget.s_difficulty.enabled = false; widget.s_level.enabled = false; widget.s_players.enabled = false; } } /** * Receive the user list from the server, or regenerate the user list after a user * leaves or joins this room. * @param userlist (String) a "|" separated list of usernames. Ex: "chad|tim|cole|" */ public function setUserList(userlist : String):void { usernames = userlist.split("|"); ready = new Array(); level.users = new Array(); for (var i : uint = 0; i < usernames.length; i++) { if (String(usernames[i]).length == 0) continue; ready.push(false); if (String(usernames[i]).match(user.name)) { if (i == 0) { host = true; widget.s_difficulty.enabled = true; widget.s_level.enabled = true; widget.s_players.enabled = true; } else { host = false; widget.s_difficulty.enabled = false; widget.s_level.enabled = false; widget.s_players.enabled = false; } level.users.push(user); user.widget.shroud.visible = false; user.index = i; } else { var new_user : UserService = new UserService(); new_user.name = String(usernames[i]); level.users.push(new_user); new_user.widget.shroud.visible = false; new_user.index = i; } } ready[0] = true; syncButtonsWithReadyStatus(); } /** * A user has joined this room. Add this name to the user list and regenerate the userlist. * If this is the host, send the new user the properties of the room. Ignore this message * if the user entering is the current user (wait for userlist). * @param username (String) name of the user joining. */ public function userJoin(username : String):void { //Ignore this command if the user is entering the room if (usernames.length == 0) return; // Add this person to the userlist var userList:String = ""; for (var i : int = 0; i < usernames.length; i++) { if (String(usernames[i]).length == 0) continue; userList += String(usernames[i]) + "|"; } setUserList(userList + username + "|"); // Send setup commands (S* commands) if (host) { SystemController.getInstance().clientService.socketSend("SM:" + widget.s_level.value); SystemController.getInstance().clientService.socketSend("SD:" + widget.s_difficulty.value); SystemController.getInstance().levelService.difficulty = widget.s_difficulty.value; SystemController.getInstance().clientService.socketSend("SP:" + widget.s_players.value); SystemController.getInstance().clientService.socketSend("CHAT:System: User " + username + " has joined the room."); } } /** * A user has left this room. Regenerate user list. * @param username (String) username of the user who left */ public function userLeft(username : String):void { var userList:String = ""; for (var i : int = 0; i < usernames.length; i++) { if (username.match(String(usernames[i])) || String(usernames[i]).length == 0) { continue; } userList += String(usernames[i]) + "|"; } setUserList(userList); if (host) SystemController.getInstance().clientService.socketSend("CHAT:System: User " + username + " has left the room."); } /** * Handles the event when the host changes the settings of the room (difficulty, level, # players, etc). * This function is only called by the host, as the widgets are not enabled for other players. * @param e - MouseEvent.CLICK */ private function updateSettings(e:MouseEvent) : void { if (host) { client.socketSend("SM:" + widget.s_level.value); client.socketSend("SD:" + widget.s_difficulty.value); level.difficulty = widget.s_difficulty.value; client.socketSend("SP:" + widget.s_players.value); } } //Listen for enter when user is chatting private function checkEnter(e:KeyboardEvent):void { if (e.keyCode == 13) sendChat(null); } //Sends a chat private function sendChat(e:MouseEvent):void { var msg : String = widget.input_txt.text; var username : String = SystemController.getInstance().userService.name; widget.input_txt.text = ""; SystemController.getInstance().clientService.socketSend("CHAT:" + username + ": " + msg); } /** * Remote handler for receiving a chat message * @param msg (String) the chat message */ public function receiveChat(msg : String):void { if (widget.chat_txt.verticalScrollPosition == widget.chat_txt.maxVerticalScrollPosition) { widget.chat_txt.appendText(msg + "\n"); widget.chat_txt.verticalScrollPosition = widget.chat_txt.maxVerticalScrollPosition; } else { widget.chat_txt.appendText(msg + "\n"); } } /** * Remote Handler for receiving a message that sets a property of the room or level. * @param cmd (String) S* command (name of the property) * @param value (String) Value of the property */ public function receiveSetProperty(cmd : String, value : String):void { if (cmd != "SR") { //Reset ready list for (var i : int = 0; i < ready.length; i++) ready[i] = false; ready[0] = true; } switch(cmd) { case "SM": if (!host) widget.s_level.value = parseInt(value); break; case "SD": if (!host) widget.s_difficulty.value = parseInt(value); break; case "SP": if (!host) widget.s_players.value = parseInt(value); break; case "SR": ready[parseInt(value)] = true; break; } syncButtonsWithReadyStatus(); } /** * Enables and disables back button and ready/start button according to the * stutus of the players. */ private function syncButtonsWithReadyStatus():void { if (host) { widget.start_btn.label = "Start"; for (var i : int = 0; i < ready.length; i++) if (!Boolean(ready[i])) { widget.start_btn.enabled = false; return; } widget.start_btn.enabled = true; widget.back_btn.enabled = true; } else { if (ready[user.index]) { //Ready non-host widget.back_btn.enabled = false; widget.start_btn.enabled = false; widget.start_btn.label = "Ready"; } else { //Not Ready non-host widget.back_btn.enabled = true; widget.start_btn.enabled = true; widget.start_btn.label = "Ready"; } } } /** * Run when a user clicks the "Go Back" button * @param e - MouseEvent.CLICK */ private function gotoLobby(e:MouseEvent):void { client.socketSend("JOINROOM:Lobby"); host = false; usernames = new Array(); SystemController.getInstance().animateChangeScreen(this, ScreenIndex.LOBBY, true); } /** * Run when the user clicks the "Ready" or "Start" button. * When the host clicks this button, it starts the game. When a non-host * clicks this button, it locks them into the room (forcing them to wait for the host to click "Start"). * Players become unlocked if a user leaves/exits or a property changes. * @param e - MouseEvent.CLICK */ private function playerReady(e:MouseEvent):void { level.setLevel(widget.s_level.value); if (!host) { // If not host, let other players know you're ready client.socketSend("SR:" + user.index); } else { // If host, start the game client.socketSend("Sstartgame:"); } } /** * Remote handler for message indicating the multiplayer game should start. */ public function start():void { SystemController.getInstance().fadeChangeScreen(this, ScreenIndex.MULTI); //Reset ready for (var i : int = 0; i < ready.length; i++) ready[i] = false; ready[0] = true; syncButtonsWithReadyStatus(); } } }