/// <summary> /// Adds a IShip to a team appropriately /// handles linking team to IShip as well /// Sends notice to clients of team addition /// Creates new team if teamID is not in use /// </summary> /// <returns>Returns true if successful</returns> public async Task <bool> AddPlayerToTeamAsync(Player p, int teamID) { var teamModel = await _databaseManager.GetTeamAsync(teamID); Team team; if (teamModel == null) { team = new Team(); team.Id = _teamIDSupplier.PopFreeID(); await _databaseManager.SaveAsync(team); } else { team = new Team(teamModel); } if (team.PlayerIDs.Contains(p.Id)) { return(false); } team.PlayerIDs.Add(p.Id); p.AddTeam(team); await _databaseManager.SaveAsync(team); if (p.CurrentAreaID == null || p.GetArea().GetOnlinePlayers().Count == 0 || p.GetArea() is Limbo) { return(true); } var area = p.GetArea(); if (area.NumOnlinePlayers < 2)//If p is the only player in the area, no need to send a message { return(true); } MessageAddRemoveShipsTeam data = new MessageAddRemoveShipsTeam(); if (p.ActiveShipId != null) { data.IDs.Add((int)p.ActiveShipId); } else { return(true); } data.TeamID = team.Id; area.BroadcastMessage(new NetworkMessageContainer(data, MessageTypes.AddRemoveShipsTeam)); return(true); }
/// <summary> /// /// Creates a new team, fills with ships provided in list /// Sends addTeam Command to all passed ships /// </summary> /// <param name="players"></param> /// <returns></returns> public int CreateNewTeam(List <Player> players) { var areas = new HashSet <IArea>(); //Keeps track of all areas which need to recieve new team information int teamID = _teamIDSupplier.PopFreeID(); Team tempTeam = new Team(); tempTeam.Id = teamID; NetOutgoingMessage msg; foreach (Player p in players) { tempTeam.PlayerIDs.Add(p.Id); p.AddTeam(tempTeam); areas.Add(p.GetArea()); //Hashtables automatically make sure each area is only added once } //make sure the sent message only contains information about the team in the appropriate system _databaseManager.SaveAsync(tempTeam); foreach (var a in areas) { if (a.NumOnlinePlayers == 0) { continue; } MessageAddRemoveShipsTeam msgData = new MessageAddRemoveShipsTeam(); msgData.TeamID = tempTeam.Id; msgData.AddOrRemove = true; foreach (var s in a.GetShips()) { if (s.Value.PlayerID != null && tempTeam.PlayerIDs.Contains((int)s.Value.PlayerID)) { msgData.IDs.Add(s.Value.Id); } } a.BroadcastMessage(new NetworkMessageContainer(msgData, MessageTypes.AddRemoveShipsTeam)); } return(tempTeam.Id); }
void _teamRemove_Handler(object sender, NetworkMessageContainer messageData) { PlayerRemoveTeam t = messageData.MessageData as PlayerRemoveTeam; var areas = new HashSet <IArea>(); foreach (int i in t.PlayerIDs) { if (_objects.ContainsKey(i)) { _objects[i].RemoveTeam(t.TeamIDToRemove); areas.Add(_objects[i].GetArea()); } } //Send removeships message to areas in which this team exists foreach (var a in areas) { var data = new MessageAddRemoveShipsTeam { AddOrRemove = false, TeamID = t.TeamIDToRemove }; foreach (var s in a.GetShips()) { if (t.PlayerIDs.Contains(s.Value.Id)) { data.IDs.Add(s.Value.Id); } } var message = new NetworkMessageContainer(data, MessageTypes.AddRemoveShipsTeam); a.BroadcastMessage(message); } }
/// <summary> /// Checks messages which should only be handled if the state is active. Returns true if a message is processed. /// </summary> /// <param name="?"></param> /// <returns>Returns true if a message is processed.</returns> bool _checkActiveMessages(MessagePackSerializableObject msg, MessageTypes messageType) { // All message cases must return true to signify that a message has been processed. switch (messageType) { #region Change ship location case (MessageTypes.ChangeShipLocation): { var data = msg as MessageChangeShipLocation; Ship s = _clientShipManager.GetShip(data.ShipID); if (s == null) { ConsoleManager.WriteLine("Warning: ShipID not found while processing ChangeShipLocation message.", ConsoleMessageType.Warning); break; } s.Position = new Vector2(data.PosX, data.PosY); s.LinearVelocity = new Vector2(data.VelX, data.VelY); s.Rotation = data.Rotation; return(true); } #endregion #region Receieve Position Update case (MessageTypes.PositionUpdateData): { var data = msg as MessagePositionUpdateData; if (data == null) { return(true); } data.UpdateDataObjects .Where(p => p.TargetType == PositionUpdateTargetType.Ship) .ForEach(UpdateShipPosition); return(true); } #endregion #region Add/Remove Ships to/from Team case (MessageTypes.AddRemoveShipsTeam): { MessageAddRemoveShipsTeam data = msg as MessageAddRemoveShipsTeam; _targetingService.DisableTargetSetting(); if (data.AddOrRemove) { foreach (var ID in data.IDs) { _teamManager.AddTeamToObject(ID, data.TeamID); } } else { foreach (var ID in data.IDs) { _teamManager.RemoveTeamFromObject(ID, data.TeamID); } } _targetingService.EnableTargetSetting(); return(true); } #endregion #region Receive New Ship // New connection, got a player ID case (MessageTypes.ReceiveNewShips): { var data = msg as MessageReceiveNewShips; foreach (var sd in data.Ships) { var s = MessageReader.InstantiateShip(sd, _physicsManager.World, _clientShipManager, false); if (s.Pilot.PilotType == PilotType.Player) { _numPlayerPilots++; if (_numPlayerPilots == 1 && IncreaseUpdateInterval != null) //Added the first player pilot { IncreaseUpdateInterval(this, MessageHandlerID.Value); } } } return(true); } #endregion #region NumOnlinePlayersChanged (Redis only) case MessageTypes.Redis_NumOnlinePlayersChanged: { var data = msg as MessageEmptyMessage; if (data.Data != null) { _numPlayerPilots = (int)data.Data; if (_numPlayerPilots >= 1 && IncreaseUpdateInterval != null) //Added the first player pilot { IncreaseUpdateInterval(this, MessageHandlerID.Value); } else if (_numPlayerPilots == 0 && DecreaseUpdateInterval != null) { DecreaseUpdateInterval(this, MessageHandlerID.Value); } } return(true); } #endregion #region Receive New Structure case MessageTypes.ReceiveNewStructure: { var data = msg as MessageReceiveNewStructure; StructureData sd = data.StructureData; InstantiateStructure(sd); return(true); } #endregion #region ReceiveFloatyAreaObjects case MessageTypes.ReceiveFloatyAreaObjects: { var data = msg as MessageReceiveFloatyAreaObjects; _floatyAreaObjectManager.InstantiateFloatyAreaObjects(data); break; } #endregion #region KillOrRemoveObjectsFromArea case MessageTypes.RemoveKillRevive: { MessageRemoveKillRevive data = msg as MessageRemoveKillRevive; switch (data.ObjectType) { case RemovableObjectTypes.FloatyAreaObject: { _floatyAreaObjectManager.RemoveFloatyAreaObjects(data); break; } case RemovableObjectTypes.Ship: { List <Ship> ships = new List <Ship>(); foreach (var ID in data.ObjectIDs) { Ship s = _clientShipManager.GetShip(ID); if (s == null) { ConsoleManager.WriteLine("Error: ShipID not found in MainNetworkingManager while processing MessageTypes.RemoveKillRevive", ConsoleMessageType.Error); } else { ships.Add(s); } } switch (data.ActionType) { case ActionType.Kill: { foreach (Ship s in ships) { s.Kill(); if (s != _clientShipManager.PlayerShip) { Debugging.DisposeStack.Push(this.ToString()); s.Body.Enabled = false; } _targetingService.DeRegisterObject(s); } break; } case ActionType.Revive: { float healthMultiplier = data.HealthMultiplier == null ? 1 : (float)data.HealthMultiplier; float shieldsMultiplier = data.ShieldMultiplier == null ? 1 : (float)data.ShieldMultiplier; foreach (Ship s in ships) { s.Revive((int)(s.MaxHealth * healthMultiplier), (int)(s.MaxShields * shieldsMultiplier)); _targetingService.RegisterObject(s); } break; } case ActionType.Remove: { foreach (Ship s in ships) { _clientShipManager.RemoveShip(s.Id); if (s.Pilot.PilotType == PilotType.Player) { _numPlayerPilots--; if (_numPlayerPilots == 0 && DecreaseUpdateInterval != null) //Last player pilot has been removed { DecreaseUpdateInterval(this, MessageHandlerID.Value); } } } break; } } break; } case RemovableObjectTypes.Structure: { switch (data.ActionType) { case ActionType.Kill: { foreach (var ID in data.ObjectIDs) { KillStructure(ID); } break; } case ActionType.Revive: { ConsoleManager.WriteLine("Error: Revive not implemented for structures.", ConsoleMessageType.Error); break; } case ActionType.Remove: { foreach (var ID in data.ObjectIDs) { RemoveStructure(ID); } break; } } break; } } return(true); } #endregion #region ObjectFired case MessageTypes.ObjectFired: { var data = msg as MessageObjectFired; ObjectFired(data); return(true); } #endregion #region COMMAND Change Ship Type case (MessageTypes.ChangeShipType): { var data = msg as ShipData; //This might not work...yolo MessageReader.InstantiateShip(data, _physicsManager.World, _clientShipManager, true); return(true); } #endregion #region Fire Denial case (MessageTypes.FireRequestResponse): { var data = msg as MessageFireRequestResponse; switch (data.FiringObjectType) { case FiringObjectTypes.Ship: { ShipFireResponse(data); break; } case FiringObjectTypes.Structure: { StructureFireResponse(data); break; } } return(true); } #endregion #region SelectorCommandMessage case MessageTypes.SelectorMessageType: { MessageSelectorCommand data = msg as MessageSelectorCommand; _selectionManager.RelayNetworkCommand(data); return(true); } #endregion #region Set Health case (MessageTypes.SetHealth): { var setHealthData = msg as MessageSetHealth; foreach (var d in setHealthData.HealthData) { Ship s = _clientShipManager.GetShip(d.ShipID); if (s == null) { ConsoleManager.WriteLine("Warning: ShipID not found while processing SetHealth message.", ConsoleMessageType.Warning); break; } if (!s.IsAlive) { s.Revive((int)d.Health, (int)d.Shields); } s.CurrentHealth = d.Health; s.Shields.CurrentShields = d.Shields; s.SetCurrentEnergy(d.Energy); for (int i = 0; i < d.DebuffTypesToAdd.Count; i++) { s.Debuffs.AddDebuff(d.DebuffTypesToAdd[i], d.DebuffCountsToAdd[i], TimeKeeper.MsSinceInitialization); } } return(true); } #endregion #region AddCargoToShip case MessageTypes.AddCargoToShip: { var data = msg as MessageAddCargoToShip; Ship s = _clientShipManager.GetShip(data.ShipID); if (s == null) { ConsoleManager.WriteLine("Warning: ShipID not found while processing AddStatefulCargoToShip message.", ConsoleMessageType.Warning); break; } foreach (var cargoData in data.StatefulCargoData) { var cargo = MessageReader.InstantiateStatefulCargo(cargoData); s.Cargo.AddStatefulCargo(cargo, true); if (cargo.CargoType == StatefulCargoTypes.Module) { s.AddModule((Module)cargo); } } foreach (var cargoData in data.StatelessCargoData) { s.Cargo.AddStatelessCargo(cargoData.CargoType, cargoData.Quantity, true); } break; } #endregion #region RemoveCargoFromPlayerShip case MessageTypes.RemoveCargoFromShip: { var data = msg as MessageRemoveCargoFromShip; Ship s = _clientShipManager.GetShip(data.ShipID); if (s == null) { ConsoleManager.WriteLine("Warning: ShipID not found while processing RemoveStatefulCargoFromShip message.", ConsoleMessageType.Warning); break; } foreach (var cargoID in data.StatefulCargoIDs) { var removedCargo = s.Cargo.RemoveStatefulCargo(cargoID); if (removedCargo == null) { ConsoleManager.WriteLine("Error: cargo not found while processing message " + MessageTypes.RemoveCargoFromShip + " for ID " + s.Id, ConsoleMessageType.Error); } else if (removedCargo.CargoType == StatefulCargoTypes.Module) { s.RemoveModule(removedCargo.Id); } foreach (var cargoData in data.StatelessCargoData) { s.Cargo.RemoveStatelessCargo(cargoData.CargoType, cargoData.Quantity); } } break; } #endregion } return(false);//No message processed }
/// <summary> /// Dissolves the team with the given team number /// I kind of half assed this function, needs testing /// </summary> /// <param name="teamNumber"></param> /// <returns></returns> public void dissolveTeam(Team team) { var areas = new HashSet <IArea>(); //Keeps track of all areas which need to recieve notification HashSet <int> playerIDs = team.PlayerIDs; HashSet <int> nonlocalPlayerIDs = new HashSet <int>(); foreach (int i in team.PlayerIDs) { Player p = _playerLocator.GetPlayerAsync(i).Result; if (p == null) { nonlocalPlayerIDs.Add(i); } else { p.RemoveTeam(team.Id); areas.Add(p.GetArea()); } } if (nonlocalPlayerIDs.Count != 0) { NetworkMessageContainer msgc = new NetworkMessageContainer(); msgc.MessageData = new PlayerRemoveTeam(nonlocalPlayerIDs, team.Id); _redisServer.PublishObject(MessageTypes.Redis_PlayerRemoveTeam, msgc); } //Send removeships message to areas in which this team exists foreach (var a in areas) { if (a.NumOnlinePlayers == 0) { continue; } var data = new MessageAddRemoveShipsTeam(); data.AddOrRemove = false; data.TeamID = team.Id; foreach (var s in a.GetShips()) { if (team.PlayerIDs.Contains(s.Value.Id)) { data.IDs.Add(s.Value.Id); } } a.BroadcastMessage(new NetworkMessageContainer(data, MessageTypes.AddRemoveShipsTeam)); } _databaseManager.DeleteTeam(team.Id); _teamIDSupplier.PushFreeID(team.Id); }