/** * Dispatches the currently stored list of games from the locally generated list */ public void UpdateDocentGamesList() { EscEvent evt = new EscEvent("games", gamesList); string initPayloadString = evt.ToString(); GameInterface.dispatchEvent("docent", initPayloadString); }
//! Returns TRUE if the peer has more EscEvents, else returns FALSE public EscEvent GetNextEvent() { EscEvent evt = this.events [0]; this.events.RemoveAt(0); return(evt); }
/** * Dispatches a EscEvent to a controller client with initial payload attributes provided by the Game class. * * @param client the client to be initialized * @param initPayload the initialization key/value pairs to be dispatched */ public void InitializeController(Client client, Dictionary <string, string> initPayload) { string msgInit = API_KEYWORD_INIT.Substring(0, API_KEYWORD_INIT.Length - 1); EscEvent evt = new EscEvent(msgInit, initPayload); string initPayloadString = evt.ToString(); WriteToLog(" sending message: " + initPayloadString + " to " + client.Username()); // LoadSave.savedData.Add (Time.time.ToString () + " : OUT :" + client.Username () + " " + initPayloadString + "\n"); GameInterface.dispatchEvent(client.Username(), initPayloadString); }
//! Dispatch a custom Esc Event message to the specified peer public int DispatchEventToClient(EscEvent evt, Peer endpoint) { WriteToLog(" sending message: " + evt.ToString() + " to " + endpoint.Username()); if (evt.ToString().Length > 256) { Debug.LogWarning("ServerConnection : DispatchEventToClient EscEvent length exceeds limit!"); } // LoadSave.savedData.Add (Time.time.ToString () + " : OUT :" + evt.ToString () + "\n"); return(GameInterface.dispatchEvent(endpoint.Username(), evt.ToString())); }
/** * Invoked by the ESC Launcher application when a Quit action is triggered or when a new game is loaded. * Dispatches an event to the plugin which then propagates it to all connected client controllers. */ public void DocentQuitGame(string gameId) { Dictionary <string, string> dict = new Dictionary <string, string>(); dict.Add("game", gameId); EscEvent evt = new EscEvent("quit", dict); GameInterface.dispatchEvent("game-engine", evt.ToString()); if (null != OnDocentGameEnd) { OnDocentGameEnd(gameId); } }
//! Dispatches an EscEvent to the game engine to stop game public void DocentStopGame(string gameId) { Dictionary <string, string> dict = new Dictionary <string, string>(); dict.Add("game", gameId); EscEvent evt = new EscEvent("stop", dict); GameInterface.dispatchEvent("game-engine", evt.ToString()); GameInterface.writeLog("stop game"); if (null != OnDocentGameStop) { OnDocentGameStop(gameId); } }
/** * Dispatches a list of parameters to the docent remote control to initialize it * * @param gameId the unique game name identifier * @param mode1 the first mode toggle integer * @param mode2 the second mode toggle integer * @param mode3 the third mode toggle integer * @param param1 the first custom string paramter * @param param2 the second custom string paramter * @param param3 the third custom string paramter * * !DEPRECATED! */ public void DocentApplyAdvancedSettings(string gameId, int mode1, int mode2, int mode3, string param1, string param2, string param3) { Dictionary <string, string> dict = new Dictionary <string, string>(); dict.Add("game", gameId); if (-1 != mode1) { dict.Add("mode1", mode1.ToString()); } if (-1 != mode2) { dict.Add("mode2", mode2.ToString()); } if (-1 != mode3) { dict.Add("mode3", mode3.ToString()); } if ("" != param1) { dict.Add("param1", param1.ToString()); } if ("" != param1) { dict.Add("param2", param1.ToString()); } if ("" != param1) { dict.Add("param3", param1.ToString()); } EscEvent evt = new EscEvent("start", dict); GameInterface.dispatchEvent("game-engine", evt.ToString()); if (null != OnDocentApplyAdvancedSettings) { OnDocentApplyAdvancedSettings(gameId); } }
/** * Dispatches an EscEvent to the game engine to start the game * * @param gameId the unique game name identifier * @param round the round setting to dispatch * @param difficulty the difficulty setting to dispatch */ public void DocentStartGame(string gameId, int round, int difficulty) { Dictionary <string, string> dict = new Dictionary <string, string>(); dict.Add("game", gameId); if (-1 != round) { dict.Add("round", round.ToString()); } if (-1 != difficulty) { dict.Add("difficulty", difficulty.ToString()); } EscEvent evt = new EscEvent("start", dict); GameInterface.dispatchEvent("game-engine", evt.ToString()); if (null != OnDocentGameStart) { OnDocentGameStart(gameId); } }
/** * Converts a string to an EscEvent * @param serializedEvent a string message that will be converted * @return EscEvent from a string */ public static EscEvent FromString(string serializedEvent) { EscEvent output; string[] colonDelimiter = new string[] { ":" }; string[] vars = serializedEvent.Split(colonDelimiter, StringSplitOptions.None); if (2 == vars.Length) { output = new EscEvent(vars[0], vars[1]); } else if (1 == vars.Length) { output = new EscEvent(vars[0]); } else { output = new EscEvent(); } return(output); }
/** * Handles any client connection changes that occur during each frame update. * If the state listener is connected, it will call its update function. * If the Controller Interface has any status changes, it will invoke the OnConnected and OnDisconnected callbacks accordingly. * If the Controller Interface has any presence events, it will invoke the OnHandlePresence callback. * If the Controller Interface receives a game registration event message it will invoke the OnRegistered callback. * If the Controller Interface receives a game registration event message it will invoke the OnInitialized callback. * Consumes network events and converts them to EscEvent objects to be processed by the controller. * Will propagate any client state changes to the server while respecting the state update frequency. * * @see Esc.Client * @see Esc.StateListener * @see Esc.ClientConnection.SetStateUpdateFrequency */ public void Update() { // consume new state changes if (this.stateListener.IsConnected()) { this.stateListener.Update(); } // attempt a reconnection if necessary if (this.willReconnect) { this.willReconnect = false; ControllerInterface.startClientInterface(ClientConnection.serverAddress); } else if (!ControllerInterface.isConnected()) { // reconnect? } // process status changes while (ControllerInterface.hasMoreStatusChanges()) { int stat; if (0 == ControllerInterface.getNextStatusChange(out stat)) { switch (stat) { case 0: // connected break; case 1: // TLS connected break; case 2: // disconnected if (null != OnDisconnected) { OnDisconnected(); } if (this.autoReconnect) { willReconnect = true; } break; case 3: // roster loaded if (null != OnConnected) { OnConnected(); } break; case 4: // error break; default: break; } } } // process presence events while (ControllerInterface.hasMorePresenceEvents()) { StringBuilder user = new StringBuilder(48); int presence; if (0 == ControllerInterface.getNextPresenceEvent(user, (uint)user.Capacity, out presence)) { string username = user.ToString(); this.server = new Server(username); if (this.server.Username() == username) { this.server.SetStatus(presence); OnHandlePresence(presence); } } } // process all incoming events while (ControllerInterface.hasMoreEvents()) { StringBuilder user = new StringBuilder(48); StringBuilder message = new StringBuilder(256); if (0 == ControllerInterface.getNextEvent(user, (uint)user.Capacity, message, (uint)message.Capacity)) { string username = user.ToString(); string msgString = message.ToString(); // handle registration if (msgString.StartsWith(API_KEYWORD_REGISTERED)) { string[] commaDelimiter = new string[] { "," }; string parameterString = msgString.Substring(API_KEYWORD_REGISTERED.Length); string[] parameters = parameterString.Split(commaDelimiter, StringSplitOptions.None); if (parameters.Length != 3) { Debug.LogError("ClientConnection: Registration message is malformed."); } // Establish connection to server with the remote IP address string remoteIpAddress = parameters[0]; this.client.SetRemoteEndpoint(remoteIpAddress); this.clientIndex = Convert.ToInt32(parameters[1]); this.gameId = parameters[2]; // Load different level if game id is different than the game scene name if (!this.gameId.Equals(this.gameSceneName)) { if (Application.CanStreamedLevelBeLoaded(this.gameId)) { Application.LoadLevel(this.gameId); } break; } string registrationMessage = API_KEYWORD_REGISTERED + this.clientIpAddress; ControllerInterface.dispatchEvent(username, registrationMessage); if (null != OnRegistered) { OnRegistered(); } } // handle initialization else if (msgString.StartsWith(API_KEYWORD_INIT)) { if (null != OnInitialized) { OnInitialized(); } } // handle loading another game else if (msgString.StartsWith(API_KEYWORD_GAME_ID)) { string parameterString = msgString.Substring(API_KEYWORD_GAME_ID.Length); if (!parameterString.Equals(this.gameSceneName)) { if (Application.CanStreamedLevelBeLoaded(parameterString)) { Application.LoadLevel(parameterString); } } } EscEvent evt = EscEvent.FromString(msgString); this.server.AppendEvent(evt); } } // check frequency of state update frequency if (cumulativeStateTime > stateUpdateFrequency) { if (null != this.client && this.client.StateVarsAreStale()) { this.client.PropagateStateVars(clientIndex); } cumulativeStateTime = 0.0f; } else { cumulativeStateTime += Time.deltaTime; } // check interval of device update frequency if (cumulativeDeviceTime > deviceUpdateFrequency) { if (ControllerInterface.isDeviceCharging()) { if (null != OnPlugged) { OnPlugged(); } ControllerInterface.dimScreen(); } else { if (null != OnUnplugged) { OnUnplugged(); } if (ControllerInterface.isDeviceWifiConnected()) { if (null != OnWifiConnected) { OnWifiConnected(); } ControllerInterface.brightenScreen(); } else { if (null != OnWifiDisconnected) { OnWifiDisconnected(); } ControllerInterface.dimScreen(); } } cumulativeDeviceTime = 0.0f; } else { cumulativeDeviceTime += Time.deltaTime; } }
/** * Dispatch a custom EscEvent to the game launcher * * @param evt an event to dispatch * @return zero on success, failure otherwise */ public int DispatchEventToGameLauncher(EscEvent evt) { return(ControllerInterface.dispatchEvent(GAME_LAUNCHER, evt.ToString())); }
/** * Dispatch a custom EscEvent message to the specified network peer * * @param evt an event to dispatch * @param endpoint the network peer that will receive the event * @return zero on success, failure otherwise */ public int DispatchEventToClient(EscEvent evt, Peer endpoint) { return(ControllerInterface.dispatchEvent(endpoint.Username(), evt.ToString())); }
/** * Handles docent connection messages that occur during each frame update. * * @see Esc.ServerConnection */ public new void Update() { // Read games plist every once second if (GameInterface.isConnected()) { if (cumulativeTime > CHECK_GAMES_LIST_INTERVAL) { cumulativeTime = 0.0f; ReadGamesPlist(); } else { cumulativeTime += Time.deltaTime; } } // Dispatch heartbeat ping to Medialon system if necessary if (medialonTime > MEDIALON_PING_INTERVAL) { medialonTime = 0.0f; DispatchMedialonPing(); } else { medialonTime += Time.deltaTime; } // Reconnect if necessary if (this.willReconnect) { this.willReconnect = false; GameInterface.startLauncherInterface(); } while (GameInterface.hasMoreStatusChanges()) { int stat; if (0 == GameInterface.getNextStatusChange(out stat)) { switch (stat) { case 0: // connected //GameInterface.writeLog("socket connection established"); break; case 1: // TLS connected break; case 2: // disconnected if (null != OnDisconnected) { OnDisconnected(); } if (this.autoReconnect) { willReconnect = true; } break; case 3: // roster loaded; if (null != OnConnected) { OnConnected(); } break; case 4: // error break; default: break; } } } while (GameInterface.hasMoreEvents()) { StringBuilder user = new StringBuilder(64); StringBuilder message = new StringBuilder(256); if (user == null || user.Capacity == null || message == null || message.Capacity == null) { return; } if (0 == GameInterface.getNextEvent(user, (uint)user.Capacity, message, (uint)message.Capacity)) { string username = user.ToString(); string msgString = message.ToString(); if (username.Equals("docent")) { if (msgString.StartsWith(API_KEYWORD_GAME)) { EscEvent evt = EscEvent.FromString(msgString); //Debug.Log("message: " + msgString); string gameIdValue = ""; string option = ""; int round = -1; int difficulty = -1; //! advance settings strings int mode1 = -1; int mode2 = -1; int mode3 = -1; string param1 = ""; string param2 = ""; string param3 = ""; foreach (KeyValuePair <string, string> pair in evt.attributes) { switch (pair.Key) { case "game": gameIdValue = pair.Value; break; case "option": option = pair.Value; break; case "round": round = Convert.ToInt32(pair.Value); break; case "difficulty": difficulty = Convert.ToInt32(pair.Value); break; case "mode1": mode1 = Convert.ToInt32(pair.Value); break; case "mode2": mode2 = Convert.ToInt32(pair.Value); break; case "mode3": mode3 = Convert.ToInt32(pair.Value); break; case "param1": param1 = pair.Value; break; case "param2": param2 = pair.Value; break; case "param3": param3 = pair.Value; break; } } switch (option) { case "load": if (!this.currentLoadedGame.Equals("")) { DocentQuitGame(this.currentLoadedGame); } this.currentLoadedGame = gameIdValue; DocentLoadGame(gameIdValue); break; case "start": DocentStartGame(gameIdValue, round, difficulty); break; case "pause": DocentPauseGame(gameIdValue); break; case "stop": DocentStopGame(gameIdValue); break; case "apply": DocentApplyAdvancedSettings(gameIdValue, mode1, mode2, mode3, param1, param2, param3); break; case "quit": DocentQuitGame(gameIdValue); break; } } else if (msgString.StartsWith(API_KEYWORD_INIT)) { UpdateDocentGamesList(); } } } } }
/** * Handles any client connection changes that occur during each frame update. * If the state listener is connected, it will call its update function. * While the Game Server Interface has status changes, it will attempt to reconnect until connection is successful. * When TLS is connected, this class's server object will instantiate with its current IP address. * While the Game Server Interface has queued presence events, each event will be marshaled based upon the client's identity. * If a client is not yet recognized, it is added to the client collection and a registration message containing the * game server IP is dispatched to the controller client. If the client already exists, the presence state received is * used to determine connectivity status. * * While the Game Server Interface has queued events, each event will be marshaled to the client object associated * with the sender and its message string parsed for either registration, initialization, or generic events, which * are then dispatched directly to the game class. * * Finally, if any client state changes have been made they are propogated to the clients. * * @see Esc.GameInterface * @see Esc.Server * @see Esc.StateListener */ public void Update() { // Go Full Screen after delay if (cumulativeTime > launchDelay && !gameFullScreen) { if (ServerConnection.developerMode) { GameInterface.goFullScreenDevMode(); WriteToLog("Set Game Full Screen Dev Mode"); } else { GameInterface.goFullScreen(); WriteToLog("Set Game Full Screen Production Mode"); } gameFullScreen = true; } else { cumulativeTime += Time.deltaTime; } if (this.stateListener != null) { if (this.stateListener.IsConnected()) { this.stateListener.Update(); } } if (this.willReconnect) { this.willReconnect = false; GameInterface.startServerInterface(); } // process status changes while (GameInterface.hasMoreStatusChanges()) { int stat; if (0 == GameInterface.getNextStatusChange(out stat)) { switch (stat) { case 0: // connected break; case 1: // TLS connected break; case 2: // disconnected if (null != OnDisconnected) { OnDisconnected(); } if (this.autoReconnect) { willReconnect = true; } // if (this.gameStarted){ // analytics.TrackGameDisconnected(); // } break; case 3: // roster loaded; this.server = new Server(KEYWORD_GAME_ENGINE); this.server.SetRemoteEndpoint("127.0.0.1"); if (null != OnConnected) { OnConnected(); } SendGameLoadedMessageToDocent(); //analytics.TrackGameLoad(GetClientRegisteredCount()); break; case 4: // error break; default: break; } } } // process presence events while (GameInterface.hasMorePresenceEvents()) { StringBuilder user = new StringBuilder(64); int presence; if (0 == GameInterface.getNextPresenceEvent(user, user.Capacity, out presence)) { uint index; string username = user.ToString(); if (KEYWORD_DOCENT != username && KEYWORD_GAME_LAUNCHER != username) { if (this.clientUsernameMap.ContainsKey(username)) { this.clientUsernameMap.TryGetValue(username, out index); if (index >= 0 && clients.Count > 0 && index < clients.Count) { this.clients [(int)index].SetStatus(presence); if (presence == 5) { DisconnectClient(this.clients [(int)index]); // if (this.gameStarted) // analytics.TrackControllerDisconnected(); } else if (presence == 0 && !this.gameStarted) { string registrationMessage = API_KEYWORD_REGISTERED + this.serverIpAddress + "," + index.ToString() + "," + this.gameId; GameInterface.dispatchEvent(username, registrationMessage); // LoadSave.savedData.Add (Time.time.ToString () + " : OUT :" + username + " " + registrationMessage + "\n"); WriteToLog(" 1 registering user: "******"," + index.ToString() + "," + this.gameId; GameInterface.dispatchEvent(username, registrationMessage); // LoadSave.savedData.Add (Time.time.ToString () + " : OUT :" + username + " " + registrationMessage + "\n"); WriteToLog(" 2 registering user: "******" : IN :" + username + " " + msgString + "\n"); WriteToLog(" " + username + " sent a message: " + msgString); if (username.Equals(KEYWORD_GAME_LAUNCHER)) { EscEvent evt = EscEvent.FromString(msgString); string requestedGameID = evt.attributes ["game"]; if (msgString.StartsWith(API_KEYWORD_START)) { if (requestedGameID.Equals(this.gameId)) { this.gameStarted = true; this.gameStartRound = Convert.ToInt32(evt.attributes ["round"]); this.gameDifficulty = Convert.ToInt32(evt.attributes ["difficulty"]); StartGame(); OnGameStart(requestedGameID); // track how many total controllers are registered //analytics.TrackGameLoad(GetClientRegisteredCount()); // track the round started //analytics.TrackRoundStart(this.gameStartRound.ToString()); // track how many total controllers are ready to play the game //analytics.TrackGameStart(GetClientReadyCount ()); } } else if (msgString.StartsWith(API_KEYWORD_PAUSE)) { if (requestedGameID.Equals(this.gameId)) { this.gamePaused = !this.gamePaused; PauseControllers(); OnGamePause(requestedGameID); // track game pause //analytics.TrackGamePause(GetClientReadyCount ()); } } else if (msgString.StartsWith(API_KEYWORD_STOP)) { if (requestedGameID.Equals(this.gameId)) { this.gameStarted = false; OnGameStop(requestedGameID); WriteToLog(msgString); // track the round ended //analytics.TrackRoundEnd(this.gameStartRound.ToString()); } } else if (msgString.StartsWith(API_KEYWORD_QUIT)) { if (requestedGameID.Equals(this.gameId)) { this.gameStarted = false; OnGameEnd(requestedGameID); Application.Quit(); WriteToLog(msgString); // track game end //analytics.TrackGameEnd(GetClientReadyCount ()); } } } else if (!username.Equals(KEYWORD_DOCENT)) { if (this.clientUsernameMap.ContainsKey(username)) { this.clientUsernameMap.TryGetValue(username, out index); if (index >= clients.Count) { WriteToLog(" " + username + " has an invalid index: " + index.ToString()); continue; } if (msgString.StartsWith(API_KEYWORD_REGISTERED)) { string ipAddress = msgString.Substring(API_KEYWORD_REGISTERED.Length); this.clients [(int)index].Register(ipAddress); if (null != OnClientRegistered) { OnClientRegistered(this.clients [(int)index]); } } else if (msgString.StartsWith(API_KEYWORD_INIT)) { this.clients [(int)index].SetReadiness(true); if (null != OnClientInitialized) { OnClientInitialized(this.clients [(int)index], EscEvent.FromString(msgString)); } } else { EscEvent evt = EscEvent.FromString(msgString); this.clients [(int)index].AppendEvent(evt); } } } else if (username.Equals(KEYWORD_DOCENT)) { if (msgString.StartsWith(API_KEYWORD_APPLY_PARAMS)) { // determine which command it is and parse it... EscEvent evt = EscEvent.FromString(msgString); int modeParam1 = 0; int modeParam2 = 0; int modeParam3 = 0; try { // WARNING: This won't work if mode3 was sent but mode 2 was not modeParam1 = Int32.Parse(evt.attributes ["mode1"]); modeParam2 = Int32.Parse(evt.attributes ["mode2"]); modeParam3 = Int32.Parse(evt.attributes ["mode3"]); } catch { WriteToLog(" error parsing docent parameters "); } // store parameters locally... this.gameStringParameter1 = evt.attributes ["param1"]; this.gameStringParameter2 = evt.attributes ["param2"]; this.gameStringParameter3 = evt.attributes ["param3"]; this.gameModeParameter1 = modeParam1; this.gameModeParameter2 = modeParam2; this.gameModeParameter3 = modeParam3; // notify listeners that a change was applied if (null != OnParametersUpdated) { OnParametersUpdated(); } } else if (msgString.StartsWith(KEYWORD_NEXT)) { // notify listeners that the next button was pressed if (null != OnNextScreen) { OnNextScreen(); } } else if (msgString.StartsWith(KEYWORD_CHECK_IF_LOADED)) { string options = API_KEYWORD_GAME_PREVIOUSLY_LOADED + "gameId=" + this.gameId + ",gameStarted=" + this.gameStarted; GameInterface.dispatchEvent(username, options); // LoadSave.savedData.Add (Time.time.ToString () + " : OUT :" + username + " " + options + "\n"); } } } } if (null != this.server && this.server.StateVarsAreStale()) { this.server.PropagateStateVars(); } }
/** * Appends EscEvent to the list of events * @param evt the EscEvent that is added to the list */ internal void AppendEvent(EscEvent evt) { this.events.Add(evt); }