/* * Copyright (c) 2013 Jayce Rettob * * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License. * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/3.0/. */ using System.Collections; using com.jbrettob.core; using com.jbrettob.data; using com.jbrettob.data.enums; using com.jbrettob.data.events; using com.jbrettob.game; using com.jbrettob.player; using com.jbrettob.ui; using PlayerIOClient; using UnityEngine; namespace com.jbrettob.game { /// /// Main server, which controls all the incomming messages and handles them. /// public class GameServer:CoreObject { private float _oldStateTime = 0; private uint _getScoreTimer = 0; // private FPSGraph _fpsGraph; private SpawnManager _spawnManager; private CarrierLightArtefact _lightBulb; private Callback _switchToPlayerCameraCallback; /// /// Initializes a new instance of the class. /// /// /// Debug. /// public GameServer(bool debug) { this.debug = debug; } public void setSwitchToPlayerCameraCallback(Callback callback) { _switchToPlayerCameraCallback = callback; } /// /// Every incomming message from the server goes through here and is being handled by their own function. /// /// /// . /// public void onGetMessage(Message message) { NetworkDebugger.ReceiveMessage(); switch (message.Type) { // TODO: add version check, to prevent using an older version to play on the server case GameEvent.PLAYER_JOINED: playerJoined(message); break; case GameEvent.PLAYER_INFO: playerInfo(message); break; case GameEvent.PLAYER_UPDATE: // calculate time offset // Time.time is in seconds * 1000 = ms float newTime = Time.time * 1000; float diff = newTime - _oldStateTime; DataManager.getInstance().playerIOAPI.setDeltaTime(diff); _oldStateTime = newTime; gamePing(diff); playerUpdate(message, diff); if (_getScoreTimer >= 31) { NetworkDebugger.SendMessage(); DataManager.getInstance().playerIOAPI.connection.Send(GameEvent.GET_SCORE); _getScoreTimer = 0; } else { _getScoreTimer++; } break; case GameEvent.PLAYER_LEAVED: playerLeaved(message); break; case GameEvent.SPAWN_LIGHT_BULB: spawnLightBulb(message); break; case GameEvent.LIGHT_BULB_DESTROY: lightBulbDestroy(message); break; case PlayerEvent.RESPAWN: playerRespawn(message); break; case GameEvent.GAME_PLAYING: gamePlaying(message); break; case GameEvent.GAME_FINISHED: gameFinished(message); break; case GameEvent.PLAYER_RESET: playerReset(message); break; case PlayerEvent.DEAD: playerDead(message); break; // TODO: create a local audio system case AudioEvent.PLAYER_AUDIO_CARRIER_DIE: case AudioEvent.PLAYER_AUDIO_CARRIER_LAND: case AudioEvent.PLAYER_AUDIO_CARRIER_RESPAWN: case AudioEvent.PLAYER_AUDIO_FLOCK_ATTACK: case AudioEvent.PLAYER_AUDIO_FLOCK_DIE: case AudioEvent.PLAYER_AUDIO_FLOCK_JUMP: case AudioEvent.PLAYER_AUDIO_FLOCK_LAND: case AudioEvent.PLAYER_AUDIO_FLOCK_RESPAWN: case AudioEvent.PLAYER_AUDIO_FLOCK_RUN: case AudioEvent.PLAYER_AUDIO_FLOCK_GASP: case AudioEvent.PLAYER_AUDIO_FLOCK_STATUED: case AudioEvent.PLAYER_AUDIO_FLOCK_FOOTSTEPS: { playerAudio(message); break; } case GameEvent.SPAWN_CARRIER_LIGHT: { spawnCarrierLight(message); break; } case GameEvent.GET_SCORE: { getScores(message); break; } default: logDebug("onGetMessage() message: " + message); break; } } /// /// Set the time difference in ms. /// /// /// Diff. /// private void gamePing(float diff) { if (_fpsGraph == null) { _fpsGraph = Object.FindObjectOfType(typeof(FPSGraph)) as FPSGraph; } if (_fpsGraph != null) { _fpsGraph.gamePing(diff); } } /// /// When played joined the room. /// /// /// . /// private void playerJoined(Message message) { if (debug) logDebug("playerJoined() message: " + message); // add joined player Transform go = GameObject.Instantiate(DataManager.getInstance().gameManager.playerPrefab, new Vector3(message.GetFloat(2), message.GetFloat(3), message.GetFloat(4)), Quaternion.identity) as Transform; Player player = go.GetComponent(); player.setPlayerData(message.GetInt(0), message.GetString(1)); player.y = 2; player.setState( message.GetFloat(2), message.GetFloat(3), message.GetFloat(4), message.GetFloat(5), message.GetFloat(6), message.GetFloat(7), message.GetFloat(8), message.GetFloat(9), message.GetFloat(10), message.GetFloat(11), message.GetBoolean(12), // hasLight message.GetBoolean(13), // isMoving message.GetBoolean(14), // isDead message.GetBoolean(15), // isRunning message.GetBoolean(16) // dashed ); DataManager.getInstance().players.Add(player); } /// /// When player receives info from the room. /// /// /// . /// private void playerInfo(Message message) { if (debug) logDebug("playerInfo() message: " + message); Player player = getPlayerById(message.GetInt(0)); if (!Application.isWebPlayer) player.setFMOD(); DataManager.getInstance().userModel.setPlayer(player); if (_switchToPlayerCameraCallback != null) { _switchToPlayerCameraCallback(player); } DataManager.getInstance().gameState = GameDataNames.GAME_STATES_GAME_PLAYING; player.audioGameStart.playAudio(); } /// /// When player respawns from the server. /// /// /// . /// private void playerRespawn(Message message) { if (debug) logDebug("playerRespawn() message: " + message); if (_spawnManager == null) { _spawnManager = Object.FindObjectOfType(typeof(SpawnManager)) as SpawnManager;; } Transform spawnpoint = _spawnManager.spawnpoints[Random.Range(1, _spawnManager.spawnpoints.Length)].transform; Vector3 spawnpos = spawnpoint.position; Player player = getPlayerById(message.GetInt(0)); player.x = spawnpos.x; player.y = spawnpos.y; player.z = spawnpos.z; if (debug) logDebug("playerRespawn() should spawn at: " + spawnpoint.rotation.eulerAngles.x + "," + spawnpoint.rotation.eulerAngles.y + "," + spawnpoint.rotation.eulerAngles.z); player.transform.rotation = Quaternion.Euler( new Vector3( 0, spawnpoint.rotation.eulerAngles.y, 0 ) ); player.playerCamera.localRotation = Quaternion.Euler( new Vector3(spawnpoint.rotation.eulerAngles.x, 0, 0) ); player.setState( spawnpos.x, spawnpos.y, spawnpos.z, spawnpoint.rotation.eulerAngles.x, spawnpoint.rotation.eulerAngles.y, 0, 0, 0, 0, 0, false, // hasLight false, // isMoving false, // isDead false, // isRunning false // dashed ); player.reset(); DataManager.getInstance().playerIOAPI.sendMessage(GameEvent.PLAYER_UPDATE, true); } /// /// When player updates from the server. /// /// /// from PlayerIO looks like this: /// 00 server deltaTime /// 01 player.Id /// 02 player.x /// 03 player.y /// 04 player.z /// 05 player.rotationX /// 06 player.rotationY /// 07 player.rotationZ /// 08 player.accelerationX /// 09 player.accelerationY /// 10 player.cameraRotation /// 11 player.playerRotation /// 12 player.hasLight /// 13 player.isMoving /// 14 player.isDead /// 15 player.isRunning /// 16 player.dashed /// /// /// Diff. /// private void playerUpdate(Message message, float diff) { if (debug) logDebug("playerUpdate() message: " + message); if (_oldStateTime == 0) { _oldStateTime = Time.time; return; } uint row = 0; for (uint i = 0; i < (message.Count - 1) / 15; i++) { row = i * 16; Player player = getPlayerById(message.GetInt(row + 1)); player.setState( message.GetFloat(row + 2), message.GetFloat(row + 3), message.GetFloat(row + 4), message.GetFloat(row + 5), message.GetFloat(row + 6), message.GetFloat(row + 7), message.GetFloat(row + 8), message.GetFloat(row + 9), message.GetFloat(row + 10), message.GetFloat(row + 11), message.GetBoolean(row + 12), message.GetBoolean(row + 13), message.GetBoolean(row + 14), message.GetBoolean(row + 15), message.GetBoolean(row + 16) ); } } /// /// When played leaves the room. /// /// /// from PlayerIO looks like this: /// 00 player.Id /// private void playerLeaved(Message message) { if (debug) logDebug("playerLeaved() message: " + message); Player player = getPlayerById(message.GetInt(0)); DataManager.getInstance().players.Remove(player); GameObject.Destroy(player.gameObject); } /// /// When the client should spawn a light artefact /// /// /// from PlayerIO looks like this: /// 00 spawnpos.x /// 01 spawnpos.y /// 02 spawnpos.z /// But these values aren't being used anymore! /// private void spawnLightBulb(Message message) { if (debug) logDebug("spawnLightBulb() message: " + message); lightBulbDestroy(null); if (_spawnManager == null) { _spawnManager = Object.FindObjectOfType(typeof(SpawnManager)) as SpawnManager; } Vector3 spawnPos = _spawnManager.spawnpoints[0].position; Transform to = GameObject.Instantiate(DataManager.getInstance().gameManager.carrierLightArtefactPrefab, new Vector3(spawnPos.x, spawnPos.y, spawnPos.z), Quaternion.identity) as Transform; to.name = "CarrierLightArtefact"; DataManager.getInstance().userModel.setLightBulb(to.GetComponent()); } /// /// When the client should destroy the light artefact /// /// /// from PlayerIO looks like this: /// private void lightBulbDestroy(Message message) { if (debug) logDebug("lightBulbDestroy()"); if (_lightBulb == null) { _lightBulb = Object.FindObjectOfType(typeof(CarrierLightArtefact)) as CarrierLightArtefact; } if (_lightBulb != null) { GameObject.Destroy(_lightBulb.gameObject); } } /// /// Returns the Player class based on the id that's been given /// /// /// /// private Player getPlayerById(int id) { Player player = null; foreach (Player playerItem in DataManager.getInstance().players) { if (playerItem.id == id) { player = playerItem; break; } } if (player == null) { logError("can not find player with the id: " + id); return null; } return player; } /// /// When the client should go into play mode from the server /// /// /// from PlayerIO looks like this: /// private void gamePlaying(Message message) { if (debug) logDebug("gamePlaying() message: " + message); if( GameObject.Find("EndGameAudioListener") != null ) { // Disconnect from server if (DataManager.getInstance().playerIOAPI.connection != null) { DataManager.getInstance().playerIOAPI.connection.Disconnect(); DataManager.getInstance().playerIOAPI.setConnection(null); } if (DataManager.getInstance().playerIOAPI.client != null) { DataManager.getInstance().playerIOAPI.setClient(null); } Application.LoadLevel(WorldNames.GAME_LOBBY); } else { DataManager.getInstance().gameState = GameDataNames.GAME_STATES_GAME_PLAYING; DataManager.getInstance().scoreAPI.reset(); DataManager.getInstance().gameManager.endGameAudio.Stop(); if(DataManager.getInstance().gameManager.endScreen) DataManager.getInstance().gameManager.endScreen.Hide(); if(DataManager.getInstance().gameManager.hudNotifications) DataManager.getInstance().gameManager.hudNotifications.Hide(); } } /// /// When the client should go into finished mode from the server /// /// /// from PlayerIO looks like this: /// 00 player.Id of our own player /// 01 player.Username of the player who won /// private void gameFinished(Message message) { if (debug) logDebug("gameFinished() message: " + message); if (debug) logDebug("Player " + message.GetString(1) + " has won the game! The game will restart in 15 seconds..."); Debug.Log("GAME FINISHED"); GameObject obj = new GameObject(); obj.AddComponent(typeof(AudioListener)); obj.name = "EndGameAudioListener"; NetworkDebugger.SendMessage(); DataManager.getInstance().playerIOAPI.connection.Send(GameEvent.GET_SCORE); DataManager.getInstance().gameState = GameDataNames.GAME_STATES_GAME_FINISHED; DataManager.getInstance().gameManager.endScreen.Show(message.GetString(1) + " has won the game!"); Player player = getPlayerById(message.GetInt(0)); if (player != null && player == DataManager.getInstance().userModel.player) { DataManager.getInstance().gameManager.endGameAudio.PlayWin(); } else { DataManager.getInstance().gameManager.endGameAudio.PlayLose(); } GameObject.Destroy( player.gameObject ); GameObject.Destroy( GameObject.Find("AudioHolder") ); //player.GetComponent().enabled = false; } /// /// When the client should go reset the player /// /// /// from PlayerIO looks like this: /// 00 player.Id of our own player /// private void playerReset(Message message) { if (debug) logDebug("playerReset() message: " + message); Player player = getPlayerById(message.GetInt(0)); if (player != null) { player.reset(); } } /// /// When the client should set the player to dead state. /// /// /// from PlayerIO looks like this: /// 00 player.Id of our own player /// 01 player.Id of the attacket /// public void playerDead(Message message) { if (debug) logDebug("playerDead() message: " + message); if (debug) logDebug("You have been killed by " + message.GetString(1) + " (-20% lightpoints)!"); Player player = getPlayerById(message.GetInt(0)); if (player != null) { if (!player.hasLight) { int oldScore = DataManager.getInstance().scoreAPI.getScore; int decreaseScore = Mathf.RoundToInt(-oldScore * GameDataNames.LOSE_SCORE_IN_PERCENTAGE); DataManager.getInstance().scoreAPI.addScore(decreaseScore); DataManager.getInstance().gameManager.hudNotifications.Show("You have been killed by " + message.GetString(1) + " \n(-"+Mathf.Abs(decreaseScore)+" lightpoints)!", 10f); DataManager.getInstance().playerIOAPI.connection.Send(GameEvent.PLAYER_SCORE, DataManager.getInstance().scoreAPI.getScore); } else { DataManager.getInstance().gameManager.hudNotifications.Show("You have been killed by " + message.GetString(1), 10f); } } } /// /// When the client should spawn an CarrierLight explosion /// /// /// from PlayerIO looks like this: /// 00 player.Id of the player who gained the light /// public void spawnCarrierLight(Message message) { if (debug) logDebug("spawnCarrierLight() message: " + message); Player player = getPlayerById(message.GetInt(0)); if (player != null) { DataManager.getInstance().gameManager.spawnCarrierKillParticlesAtPosition(player.transform.position, player.id); if (DataManager.getInstance().userModel.player == player && player.audioCarrierDie != null) player.audioCarrierDie.playAudio(); } } /// /// When the client request the player's scores /// /// /// from PlayerIO looks like this: /// 00 player.username /// 01 player.deaths /// 02 player.kills /// 03 player.score /// repeat this with the amount of players are in-game. /// private void getScores(Message message) { if (debug) logDebug("getScores() message: " + message); ArrayList data = new ArrayList(); for (uint i = 0; i < message.Count / 4; i++) { if (debug) logDebug( "getScores() " + message.GetString(i * 4) + ": " + message.GetInt( (i * 4) + 1) + "/" + message.GetInt( (i * 4) + 2) + " score: " + message.GetInt( (i * 4) + 3) ); ArrayList obj = new ArrayList(); obj.Add( message.GetString(i * 4) ); obj.Add( message.GetInt( (i * 4) + 1) ); obj.Add( message.GetInt( (i * 4) + 2) ); obj.Add( message.GetInt( (i * 4) + 3) ); data.Add(obj); } DataManager.getInstance().gameManager.scoreboardWindow.setContent(data); } /// /// When the client should play an audio event, that's being called via the server. /// /// /// from PlayerIO looks like this: /// 00 player.id /// 01 audio.id /// 02 audio.max volume /// 03 audio.min volume /// 04 audio.max pitch /// 05 audio.min pitch /// private void playerAudio(Message message) { if (debug) logDebug("playerAudio() message: " + message); Player player = getPlayerById(message.GetInt(0)); if (player != null) { switch (message.Type) { case AudioEvent.PLAYER_AUDIO_CARRIER_DIE: player.audioCarrierDie.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_CARRIER_LAND: player.audioCarrierLand.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_CARRIER_RESPAWN: player.audioCarrierRespawn.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_ATTACK: player.audioFlockAttack.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_DIE: player.audioFlockDie.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_JUMP: player.audioFlockJump.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_LAND: player.audioFlockLand.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_RESPAWN: break; case AudioEvent.PLAYER_AUDIO_FLOCK_GASP: player.audioFlockGasp.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_RUN: player.audioFlockRun.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_STATUED: player.audioFlockStatued.playAudioMessageFromServer(message); break; case AudioEvent.PLAYER_AUDIO_FLOCK_FOOTSTEPS: player.audioFlockFootsteps.playAudioMessageFromServer(message); break; } } } } }