public GameDataPacket(IPEndPoint destination, GameData gameData) : base(PacketType.GAMEDATA, destination) { AddContent(gameData.GetByteArray()); FinalizeData(); return; }
/// <summary> /// Perform a transion between states. /// </summary> /// <param name="transEvent">An event that is occuring when a packet arrives.</param> /// <param name="packet">The packet received over the network.</param> public void DoTransition(GameServerTransition transEvent, GameData packet) { Tuple<GameServerState, TransitionAction> transition = null; try { transition = TransitionTable[new Tuple<GameServerState,GameServerTransition>(CurrentState,transEvent)]; transition.Item2(packet); CurrentState = transition.Item1; } catch (Exception error) { Debug.WriteLine("You managed to break the GameServerStateMachine. Congratulations, asshole: {0}", new Object[] {error.Message}); Debug.WriteLine("Violating Transition: {0} - {1} - {2}",new Object[] {CurrentState,transEvent,packet}); throw error; } return; }
/// <summary> /// Handles a Game Start Request /// </summary> /// <param name="gameData">The game data related to character locking.</param> protected override void OnGameStart(GameData gameData) { // Set player as ready Game.GetPlayer(gameData.PlayerID).PlayerReady = true; for (int i = 0; i < Game.players.Length; ++i) { Player player = Game.GetPlayer(i); if (player != null && !player.PlayerReady) { return; } } // If everyone has sent the start game request: Game.Network.BroadCastGameData(new GameData(GameData.GameDataType.GameStart)); Game.StartGame(); return; }
/// <summary> /// A Player has joined, set them up in the system. /// </summary> /// <param name="gameData">The game data related to the character joining the session.</param> protected override void OnPlayerConnect(GameData gameData) { GameData response; Player player = Game.ConnectionIDToPlayer(gameData.ConnectionInfo); switch ((GameData.ConnectionDetails)gameData.EventDetail) { case GameData.ConnectionDetails.IdReqest: if (player == null) // If this is a new player, assign them a new ID, otherwise just resend the old id { player = new Player(gameData.ConnectionInfo, Game); } response = new GameData(GameData.GameDataType.Connect, player.PlayerID, (int)GameData.ConnectionDetails.IdReqest); //TODO: Ask Ben Cassel, why is this broadcast? Game.Network.BroadCastGameData(response); for (int i = 0; i < Game.players.Length; ++i) { if (Game.players[i] != null) { response = new GameData(GameData.GameDataType.Connect, Game.players[i].PlayerID, (int)GameData.ConnectionDetails.Connected); Game.Network.BroadCastGameData(response); } } break; case GameData.ConnectionDetails.Disconnected: case GameData.ConnectionDetails.Dropped: if (player != null) // This is a known player based on their connection, so we can drop them { Game.UnregisterPlayer(player); response = new GameData(GameData.GameDataType.Connect,player.PlayerID,(int)GameData.ConnectionDetails.Disconnected); Game.Network.BroadCastGameData(response); } break; default: throw new ArgumentException(); } return; }
/// <summary> /// Update hanlder from the network layer. This is only invoked until control passes back to the game server. /// </summary> /// <param name="gameData">Game data being used to update the state of the game.</param> public void UpdateLobbyState(GameData gameData) { switch (gameData.Type) { case GameData.GameDataType.Connect: OnPlayerConnect(gameData); break; case GameData.GameDataType.SelectCharacter: OnPlayerSelectCharacter(gameData); break; case GameData.GameDataType.LockCharacter: OnPlayerLockCharacter(gameData); break; case GameData.GameDataType.GameStart: OnGameStart(gameData); break; default: throw new ArgumentException(); } return; }
/// <summary> /// Run logic for when a player locks or unlocks a character. /// </summary> /// <param name="gameData">The game data related to the player's actions.</param> protected abstract void OnPlayerLockCharacter(GameData gameData);
/// <summary> /// Run logic for a player connecting to or disconnecting from the game. /// </summary> /// <param name="gameData">The game data related to the player's actions.</param> protected abstract void OnPlayerConnect(GameData gameData);
/// <summary> /// Handles a Game Start Request /// </summary> /// <param name="gameData">The game data related to character locking.</param> protected abstract void OnGameStart(GameData gameData);
/// <summary> /// Send a unit of game data to a particular client. /// </summary> /// <param name="gameData">The unit of game data to send.</param> /// <param name="connectionID">The ID of the client to send the game data to.</param> public void SendGameData(GameData gameData, ConnectionID connectionID) { networkWorker.SendPacket(new GameDataPacket(connectionID.IPEndPoint, gameData)); return; }
/// <summary> /// After choosing the level and number of players, start the game. /// </summary> /// <param name="levelID">The ID of the level to initialize.</param> /// <param name="myPlayerID">The ID of the player character.</param> public void SetupGameState(int levelID, int myPlayerID) { Level level = new Level(GameState.root, LevelPack.levels[levelID]); SpawnPointEntity sp = level.spawnPoints[myPlayerID]; TestMan tm = new TestMan(sp, true); players[myPlayerID].EntityID = tm.id; LocalPlayer.EntityID = players[myPlayerID].EntityID; //hack? EntityData entityData = new EntityData(EntityData.EntityType.TestMan, tm.id, tm.transform); GameData gameData = new GameData(GameData.GameDataType.NewEntity, myPlayerID, 0, null, entityData); Network.SendGameData(gameData); return; }
/// <summary> /// Update an entity based on a transform. /// </summary> /// <param name="entity">The entity to update.</param> public virtual void OnTransformChange(Entity entity) { // Generate a transform change packet, put it on stack TransformData transformData = new TransformData(entity.id, entity.transform); // TODO: This likely doesn't work. This neeeds to be fixed (the player ID and event detail might need changing, or we may simply need a new constructor). GameData gameData = new GameData(GameData.GameDataType.Movement, LocalPlayer.PlayerID, 0, transformData); lock (gameStatesToSend) { gameStatesToSend.Add(gameData); } return; }
/// <summary> /// A player has changed their character selection. /// </summary> /// <param name="gameData">The game data related to character selection.</param> protected override void OnPlayerSelectCharacter(GameData gameData) { Player player = Game.ConnectionIDToPlayer(gameData.ConnectionInfo); player.CharacterSelection = gameData.EventDetail; Game.Network.BroadCastGameData(new GameData(GameData.GameDataType.SelectCharacter, player.PlayerID, gameData.EventDetail)); return; }
/// <summary> /// Hanldes the character lock request /// </summary> /// <param name="gameData">The game data related to character locking.</param> protected override void OnPlayerLockCharacter(GameData gameData) { Player player = Game.ConnectionIDToPlayer(gameData.ConnectionInfo); player.CharacterLocked = true; Game.Network.BroadCastGameData(new GameData(GameData.GameDataType.LockCharacter, player.PlayerID)); return; }
/// <summary> /// Handles reception of game data updates from the client. /// </summary> /// <param name="packet">A packet that contains game data information.</param> protected override void OnGameData(NetworkPacket packet) { GameData gameData = new GameData(packet.DataArray); gameData.ConnectionInfo = connections[packet.Destination]; gameDataUpdater(gameData); return; }
/// <summary> /// Run logic for a player choosing between different characters. /// </summary> /// <param name="gameData">The game data related to the player's actions.</param> protected abstract void OnPlayerSelectCharacter(GameData gameData);
/// <summary> /// Send out state change information /// </summary> /// <param name="entity">The entity to update.</param> public virtual void OnEntityStateChange(Entity entity) { EntityStateData stateData; // Invoke class-specific constructors, to avoid sending extra information if (entity is MobileEntity) { stateData = new EntityStateData((MobileEntity)entity); } else { stateData = new EntityStateData(entity); } GameData gameData = new GameData(GameData.GameDataType.EntityStateChange, LocalPlayer.PlayerID, 0); gameData.EventDetail = entity.id; gameData.EntityStateData = stateData; lock (gameStatesToSend) { gameStatesToSend.Add(gameData); } return; }
/// <summary> /// Handles a Game Start Request /// </summary> /// <param name="gameData">The game data related to character locking.</param> protected override void OnGameStart(GameData gameData) { Game.SetupGameState(0, Game.LocalPlayer.PlayerID); Game.StartGame(); newGameUpdater.Invoke(Game); return; }
/// <summary> /// Add incoming data to the game states. /// </summary> /// <param name="gameData">Received game data that should inform us about changing state, requests, etc.</param> protected virtual void AddGameState(GameData gameData) { lock (gameStatesToCommit) { gameStatesToCommit.Add(gameData); } return; }
/// <summary> /// A Player has joined, set them up in the system. /// </summary> /// <param name="gameData">The game data related to the character joining the session.</param> protected override void OnPlayerConnect(GameData gameData) { // TODO: Add responses to some of these events if necessary switch ((GameData.ConnectionDetails)gameData.EventDetail) { case GameData.ConnectionDetails.IdReqest: if (Game.LocalPlayer == null) { Game.LocalPlayer = new Player(null, Game, gameData.PlayerID); Entity.next_id = gameData.PlayerID * (int.MaxValue / GameBase.MAX_PLAYERS); } break; case GameData.ConnectionDetails.Connected: // Register a new player on a client new Player(null, Game, gameData.PlayerID); break; case GameData.ConnectionDetails.Disconnected: // Drop a connected player from the client case GameData.ConnectionDetails.Dropped: Game.UnregisterPlayer(Game.GetPlayer(gameData.PlayerID)); break; default: throw new ArgumentException(); } return; }
/// <summary> /// Update the state over the game based on incoming game data. /// </summary> /// <param name="gameData">The received game data.</param> protected override void AddGameState(GameData gameData) { lock (gameStatesToCommit) { for (int i = 0; i < players.Length; i++) // Forward the received information to other machines (but not the one received from) { Player player = GetPlayer(i); if (i == gameData.PlayerID || player == null) { continue; } Network.SendGameData(gameData, PlayerToConnectionID(players[i])); gameStatesToCommit.Add(gameData); } } return; }
/// <summary> /// A player has changed their character selection. /// </summary> /// <param name="gameData">The game data related to character selection.</param> protected override void OnPlayerSelectCharacter(GameData gameData) { throw new NotImplementedException(); }
/// <summary> /// Send a unit of game data to the server. /// </summary> /// <param name="gameData">The game data to send to the server.</param> public void SendGameData(GameData gameData) { networkWorker.SendPacket(new GameDataPacket(serverEndPoint, gameData)); return; }
/// <summary> /// Broadcast a unit of game data to all users. /// </summary> /// <param name="gameData">The unit of game data to broadcast.</param> public void BroadCastGameData(GameData gameData) { foreach (ConnectionID connection in connections.Values) { SendGameData(gameData, connection); } return; }