/// <summary> /// Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders, /// what PlanetWars structures to create, etc. /// </summary> public static LobbyHostingContext GetDedicatedServerStartSetup(LobbyHostingContext context) { var ret = context; try { var mode = context.Mode; var commProfiles = new LuaTable(); var db = new ZkDataContext(); // calculate to whom to send extra comms var accountIDsWithExtraComms = new List <int>(); if (mode == AutohostMode.Planetwars || mode == AutohostMode.GameFFA || mode == AutohostMode.Teams) { var groupedByTeam = context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count()); var biggest = groupedByTeam.FirstOrDefault(); if (biggest != null) { foreach (var other in groupedByTeam.Skip(1)) { var cnt = biggest.Count() - other.Count(); if (cnt > 0) { foreach (var a in other.Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)) .OrderByDescending(x => x.GetRating(RatingCategory.Casual).Elo) .Take(cnt)) { accountIDsWithExtraComms.Add(a.AccountID); } } } } } // write Planetwars details to modoptions (for widget) Faction attacker = null; Faction defender = null; Planet planet = null; if (mode == AutohostMode.Planetwars) { planet = db.Galaxies.First(x => x.IsDefault).Planets.First(x => x.Resource.InternalName == context.Map); attacker = context.Players.Where(x => x.AllyID == 0 && !x.IsSpectator) .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)) .Where(x => x.Faction != null) .Select(x => x.Faction) .First(); defender = planet.Faction; if (attacker == defender) { defender = null; } ret.ModOptions["attackingFaction"] = attacker.Shortcut; ret.ModOptions["attackingFactionName"] = attacker.Name; ret.ModOptions["attackingFactionColor"] = attacker.Color; if (defender != null) { ret.ModOptions["defendingFaction"] = defender.Shortcut; ret.ModOptions["defendingFactionName"] = defender.Name; ret.ModOptions["defendingFactionColor"] = defender.Color; } else { ret.ModOptions["defendingFaction"] = "Mercenary"; ret.ModOptions["defendingFactionName"] = "Local militia"; ret.ModOptions["defendingFactionColor"] = "#CCCCCC"; } ret.ModOptions["planet"] = planet.Name; } // write player custom keys (level, elo, is muted, etc.) foreach (var p in context.Players) { var user = db.Accounts.Where(x => x.AccountID == p.LobbyID).Include(x => x.RelalationsByOwner).FirstOrDefault(); if (user != null) { var userParams = new Dictionary <string, string>(); ret.UserParameters[p.Name] = userParams; userParams["LobbyID"] = user.AccountID.ToString(); userParams["CountryCode"] = user.HideCountry ? "??" : user.Country; var userBanMuted = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanMute) != null; if (userBanMuted) { userParams["muted"] = "1"; } userParams["faction"] = user.Faction != null ? user.Faction.Shortcut : ""; userParams["clan"] = user.Clan != null ? user.Clan.Shortcut : ""; userParams["clanfull"] = user.Clan != null ? user.Clan.ClanName : ""; userParams["level"] = user.Level.ToString(); //userParams["mm_elo"] = Math.Round(user.EffectiveMmElo).ToString(); //userParams["casual_elo"] = Math.Round(user.EffectiveElo).ToString(); userParams["elo"] = Math.Round(user.GetBestRating().Elo).ToString(); userParams["icon"] = user.GetIconName(); userParams["avatar"] = user.Avatar; userParams["badges"] = string.Join(",", user.GetBadges()); userParams["admin"] = user.AdminLevel >= AdminLevel.Moderator ? "1" : "0"; userParams["room_boss"] = p.Name == context.FounderName ? "1" : "0"; if (p.PartyID.HasValue) { userParams["PartyID"] = p.PartyID.ToString(); } var userSpecChatBlocked = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanSpecChat) != null;; userParams["can_spec_chat"] = userSpecChatBlocked ? "0" : "1"; userParams["ignored"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Ignore).Select(x => x.Target.Name)); userParams["friends"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Friend).Select(x => x.Target.Name)); if (!p.IsSpectator) { // set valid PW structure attackers if (mode == AutohostMode.Planetwars) { userParams["pwRank"] = (user.AccountRolesByAccountID.Where( x => !x.RoleType.IsClanOnly && (x.RoleType.RestrictFactionID == null || x.RoleType.RestrictFactionID == user.FactionID)).OrderBy(x => x.RoleType.DisplayOrder).Select(x => (int?)x.RoleType.DisplayOrder).FirstOrDefault() ?? 999).ToString(); var allied = user.Faction != null && defender != null && user.Faction != defender && defender.HasTreatyRight(user.Faction, x => x.EffectPreventIngamePwStructureDestruction == true, planet); if (!allied && user.Faction != null && (user.Faction == attacker || user.Faction == defender)) { userParams["canAttackPwStructures"] = "1"; } userParams["pwInstructions"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(GetPwInstructions(planet, user, db, attacker))); } if (accountIDsWithExtraComms.Contains(user.AccountID)) { userParams["extracomm"] = "1"; } var commProfileIDs = new LuaTable(); var userCommandersBanned = Punishment.GetActivePunishment(user.AccountID, null, null, x => x.BanCommanders) != null; if (!userCommandersBanned) { // set up commander data foreach (var c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount) ) { try { var commProfile = new LuaTable(); if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"')) { c.Name = c.CommanderID.ToString(); } commProfiles.Add("c" + c.CommanderID, commProfile); commProfileIDs.Add("c" + c.CommanderID); // process decoration icons var decorations = new LuaTable(); foreach (var d in c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(x => x.SlotID).Select(x => x.Unlock)) { var iconData = db.CommanderDecorationIcons.FirstOrDefault(x => x.DecorationUnlockID == d.UnlockID); if (iconData != null) { string iconName = null, iconPosition = null; // FIXME: handle avatars and preset/custom icons if (iconData.IconType == (int)DecorationIconTypes.Faction) { iconName = user.Faction != null ? user.Faction.Shortcut : null; } else if (iconData.IconType == (int)DecorationIconTypes.Clan) { iconName = user.Clan != null ? user.Clan.Shortcut : null; } if (iconName != null) { iconPosition = CommanderDecoration.GetIconPosition(d); var entry = new LuaTable(); entry.Add("image", iconName); decorations.Add("icon_" + iconPosition.ToLower(), entry); } } else { decorations.Add(d.Code); } } commProfile["name"] = c.Name.Substring(0, Math.Min(25, c.Name.Length)); commProfile["chassis"] = c.Unlock.Code; commProfile["decorations"] = decorations; var modules = new LuaTable(); commProfile["modules"] = modules; for (var i = 1; i <= GlobalConst.NumCommanderLevels; i++) { var modulesForLevel = new LuaTable(); modules.Add(modulesForLevel); var modulesOrdered = c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i).ToList(); var slots = db.CommanderSlots.ToList().Where(x => x.MorphLevel == i && (x.ChassisID == null || (x.ChassisID == c.ChassisUnlockID))).ToList(); slots.Sort(delegate(CommanderSlot x, CommanderSlot y) { UnlockTypes type1 = x.UnlockType; UnlockTypes type2 = y.UnlockType; if (type1 == UnlockTypes.WeaponManualFire || type1 == UnlockTypes.WeaponBoth) { type1 = UnlockTypes.Weapon; } if (type2 == UnlockTypes.WeaponManualFire || type2 == UnlockTypes.WeaponBoth) { type2 = UnlockTypes.Weapon; } int result = type1.CompareTo(type2); if (result == 0) { return(x.CommanderSlotID.CompareTo(y.CommanderSlotID)); } else { return(result); } }); foreach (var slot in slots) { String value = String.Empty; var module = c.CommanderModules.FirstOrDefault(x => x.SlotID == slot.CommanderSlotID); if (module != null) { value = module.Unlock.Code; } modulesForLevel.Add(value); } } } catch (Exception ex) { Trace.TraceError(ex.ToString()); throw new ApplicationException( $"Error processing commander: {c.CommanderID} - {c.Name} of player {user.AccountID} - {user.Name}", ex); } } } else { userParams["jokecomm"] = "1"; } userParams["commanders"] = commProfileIDs.ToBase64String(); } } } ret.ModOptions["commanderTypes"] = commProfiles.ToBase64String(); // set PW structures if (mode == AutohostMode.Planetwars) { var owner = planet.Faction != null ? planet.Faction.Shortcut : ""; var pwStructures = new LuaTable(); foreach ( var s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName))) { pwStructures.Add(s.StructureType.IngameUnitName, new LuaTable { { "unitname", s.StructureType.IngameUnitName }, { "owner", s.Account?.Name }, { "canBeEvacuated", s.StructureType.IsIngameEvacuable }, { "canBeDestroyed", s.StructureType.IsIngameDestructible }, //{ "isDestroyed", s.IsDestroyed ? true : false }, { "name", $"{owner} {s.StructureType.Name} ({(s.Account != null ? s.Account.Name : "unowned")})" }, { "description", s.StructureType.Description } }); } ret.ModOptions["planetwarsStructures"] = pwStructures.ToBase64String(); } return(ret); } catch (Exception ex) { Trace.TraceError(ex.ToString()); throw; } }
static bool listOnlyThatLevelsModules = false; // may cause bugs /// <summary> /// Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders, what PlanetWars structures to create, etc. /// </summary> public static SpringBattleStartSetup GetSpringBattleStartSetup(BattleContext context) { try { AutohostMode mode = context.GetMode(); var ret = new SpringBattleStartSetup(); if (mode == AutohostMode.Planetwars) { ret.BalanceTeamsResult = Balancer.BalanceTeams(context, true, null, null); context.Players = ret.BalanceTeamsResult.Players; } var commanderTypes = new LuaTable(); var db = new ZkDataContext(); // calculate to whom to send extra comms var accountIDsWithExtraComms = new List <int>(); if (mode == AutohostMode.Planetwars || mode == AutohostMode.Generic || mode == AutohostMode.GameFFA || mode == AutohostMode.Teams) { IOrderedEnumerable <IGrouping <int, PlayerTeam> > groupedByTeam = context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count()); IGrouping <int, PlayerTeam> biggest = groupedByTeam.FirstOrDefault(); if (biggest != null) { foreach (var other in groupedByTeam.Skip(1)) { int cnt = biggest.Count() - other.Count(); if (cnt > 0) { foreach (Account a in other.Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)).OrderByDescending(x => x.Elo * x.EloWeight).Take( cnt)) { accountIDsWithExtraComms.Add(a.AccountID); } } } } } bool is1v1 = context.Players.Where(x => !x.IsSpectator).ToList().Count == 2 && context.Bots.Count == 0; // write Planetwars details to modoptions (for widget) Faction attacker = null; Faction defender = null; Planet planet = null; if (mode == AutohostMode.Planetwars) { planet = db.Galaxies.First(x => x.IsDefault).Planets.First(x => x.Resource.InternalName == context.Map); attacker = context.Players.Where(x => x.AllyID == 0 && !x.IsSpectator) .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)) .Where(x => x.Faction != null) .Select(x => x.Faction) .First(); defender = planet.Faction; if (attacker == defender) { defender = null; } ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "attackingFaction", Value = attacker.Shortcut }); if (defender != null) { ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "defendingFaction", Value = defender.Shortcut }); } ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "planet", Value = planet.Name }); } // write player custom keys (level, elo, is muted, etc.) foreach (PlayerTeam p in context.Players) { Account user = db.Accounts.Find(p.LobbyID); if (user != null) { var userParams = new List <SpringBattleStartSetup.ScriptKeyValuePair>(); ret.UserParameters.Add(new SpringBattleStartSetup.UserCustomParameters { LobbyID = p.LobbyID, Parameters = userParams }); bool userBanMuted = user.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanMute); if (userBanMuted) { userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "muted", Value = "1" }); } userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "faction", Value = user.Faction != null ? user.Faction.Shortcut : "" }); userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "clan", Value = user.Clan != null ? user.Clan.Shortcut : "" }); userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "level", Value = user.Level.ToString() }); double elo = mode == AutohostMode.Planetwars ? user.EffectivePwElo : (is1v1 ? user.Effective1v1Elo : user.EffectiveElo); userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "elo", Value = Math.Round(elo).ToString() }); // elo for ingame is just ordering for auto /take userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "avatar", Value = user.Avatar }); userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "admin", Value = (user.IsZeroKAdmin ? "1" : "0") }); if (!p.IsSpectator) { // set valid PW structure attackers if (mode == AutohostMode.Planetwars) { bool allied = user.Faction != null && defender != null && user.Faction != defender && defender.HasTreatyRight(user.Faction, x => x.EffectPreventIngamePwStructureDestruction == true, planet); if (!allied && user.Faction != null && (user.Faction == attacker || user.Faction == defender)) { userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "canAttackPwStructures", Value = "1" }); } } var pu = new LuaTable(); bool userUnlocksBanned = user.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanUnlocks); bool userCommandersBanned = user.PunishmentsByAccountID.Any(x => !x.IsExpired && x.BanCommanders); if (!userUnlocksBanned) { if (mode != AutohostMode.Planetwars || user.Faction == null) { foreach (Unlock unlock in user.AccountUnlocks.Select(x => x.Unlock)) { pu.Add(unlock.Code); } } else { foreach (Unlock unlock in user.AccountUnlocks.Select(x => x.Unlock).Union(user.Faction.GetFactionUnlocks().Select(x => x.Unlock)).Where(x => x.UnlockType == UnlockTypes.Unit)) { pu.Add(unlock.Code); } } } userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "unlocks", Value = pu.ToBase64String() }); if (accountIDsWithExtraComms.Contains(user.AccountID)) { userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "extracomm", Value = "1" }); } var pc = new LuaTable(); if (!userCommandersBanned) { // set up commander data foreach (Commander c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount)) { try { if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"')) { c.Name = c.CommanderID.ToString(); } LuaTable morphTable = new LuaTable(); pc["[\"" + c.Name + "\"]"] = morphTable; // process decoration icons LuaTable decorations = new LuaTable(); foreach (Unlock d in c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy( x => x.SlotID).Select(x => x.Unlock)) { CommanderDecorationIcon iconData = db.CommanderDecorationIcons.FirstOrDefault(x => x.DecorationUnlockID == d.UnlockID); if (iconData != null) { string iconName = null, iconPosition = null; // FIXME: handle avatars and preset/custom icons if (iconData.IconType == (int)DecorationIconTypes.Faction) { iconName = user.Faction != null ? user.Faction.Shortcut : null; } else if (iconData.IconType == (int)DecorationIconTypes.Clan) { iconName = user.Clan != null ? user.Clan.Shortcut : null; } if (iconName != null) { iconPosition = CommanderDecoration.GetIconPosition(d); LuaTable entry = new LuaTable(); entry.Add("image", iconName); decorations.Add("icon_" + iconPosition.ToLower(), entry); } } else { decorations.Add(d.Code); } } string prevKey = null; for (int i = 0; i <= GlobalConst.NumCommanderLevels; i++) { string key = string.Format("c{0}_{1}_{2}", user.AccountID, c.ProfileNumber, i); morphTable.Add(key); // TODO: maybe don't specify morph series in player data, only starting unit var comdef = new LuaTable(); commanderTypes[key] = comdef; comdef["chassis"] = c.Unlock.Code + i; var modules = new LuaTable(); comdef["modules"] = modules; comdef["decorations"] = decorations; comdef["name"] = c.Name.Substring(0, Math.Min(25, c.Name.Length)) + " level " + i; //if (i < GlobalConst.NumCommanderLevels) //{ // comdef["next"] = string.Format("c{0}_{1}_{2}", user.AccountID, c.ProfileNumber, i+1); //} //comdef["owner"] = user.Name; if (i > 0) { comdef["cost"] = c.GetTotalMorphLevelCost(i); if (listOnlyThatLevelsModules) { if (prevKey != null) { comdef["prev"] = prevKey; } prevKey = key; foreach (Unlock m in c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i && x.Unlock != null).OrderBy( x => x.Unlock.UnlockType).ThenBy(x => x.SlotID).Select(x => x.Unlock)) { modules.Add(m.Code); } } else { foreach (Unlock m in c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel <= i && x.Unlock != null).OrderBy( x => x.Unlock.UnlockType).ThenBy(x => x.SlotID).Select(x => x.Unlock)) { modules.Add(m.Code); } } } } } catch (Exception ex) { Trace.TraceError(ex.ToString()); throw new ApplicationException( string.Format("Error processing commander: {0} - {1} of player {2} - {3}", c.CommanderID, c.Name, user.AccountID, user.Name), ex); } } } else { userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "jokecomm", Value = "1" }); } userParams.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "commanders", Value = pc.ToBase64String() }); } } } ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "commanderTypes", Value = commanderTypes.ToBase64String() }); // set PW structures if (mode == AutohostMode.Planetwars) { string owner = planet.Faction != null ? planet.Faction.Shortcut : ""; var pwStructures = new LuaTable(); foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName))) { pwStructures.Add("s" + s.StructureTypeID, new LuaTable { { "unitname", s.StructureType.IngameUnitName }, //{ "isDestroyed", s.IsDestroyed ? true : false }, { "name", string.Format("{0} {1} ({2})", owner, s.StructureType.Name, s.Account != null ? s.Account.Name:"unowned") }, { "description", s.StructureType.Description } }); } ret.ModOptions.Add(new SpringBattleStartSetup.ScriptKeyValuePair { Key = "planetwarsStructures", Value = pwStructures.ToBase64String() }); } return(ret); } catch (Exception ex) { Trace.TraceError(ex.ToString()); throw; } }
public ActionResult CommanderProfile(int profileNumber, string name, int?chassis, string deleteCommander) { if (profileNumber < 1 || profileNumber > GlobalConst.CommanderProfileCount) { return(Content("WTF! get lost")); } var db = new ZkDataContext(); using (var scope = new TransactionScope()) { var unlocks = GetUserUnlockCountsListIncludingFree(db); Commander comm = db.Commanders.SingleOrDefault(x => x.ProfileNumber == profileNumber && x.AccountID == Global.AccountID); if (comm != null) { if (!string.IsNullOrEmpty(deleteCommander)) // delete commander { db.Commanders.DeleteOnSubmit(comm); db.SaveChanges(); scope.Complete(); return(GetCommanderProfileView(profileNumber)); } } else { comm = new Commander() { AccountID = Global.AccountID, ProfileNumber = profileNumber }; db.Commanders.InsertOnSubmit(comm); } if (comm.Unlock == null) { var chassisUnlock = unlocks.FirstOrDefault(x => x.Unlock.UnlockID == chassis); if ((chassis == null || chassisUnlock == null)) { return(GetCommanderProfileView(profileNumber)); } else { comm.ChassisUnlockID = chassis.Value; comm.Unlock = chassisUnlock.Unlock; } } if (!string.IsNullOrEmpty(name)) { if (name.Length > GlobalConst.MaxCommanderNameLength) { name = name.Substring(0, GlobalConst.MaxCommanderNameLength); } name = Regex.Replace(name, @"[^\u0020-\u007E]", string.Empty); // remove unicode stuff comm.Name = name; } // process modules foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x))) { var m = Regex.Match(key, "m([0-9]+)"); if (m.Success) { var slotId = int.Parse(m.Groups[1].Value); int unlockId; int.TryParse(Request.Form[key], out unlockId); if (unlockId > 0) { CommanderSlot slot = db.CommanderSlots.SingleOrDefault(x => x.CommanderSlotID == slotId); if (slot == null) { return(Content("WTF get lost!")); } Unlock unlock = db.Unlocks.SingleOrDefault(x => x.UnlockID == unlockId); if (unlock == null) { return(Content("WTF get lost!")); } if (!unlocks.Any(x => x.Unlock.UnlockID == unlock.UnlockID)) { return(Content("WTF get lost!")); } if (slot.MorphLevel < unlock.MorphLevel || !IsUnlockValidForSlot(unlock, slot)) { return(Content(string.Format("WTF cannot use {0} in slot {1}", unlock.Name, slot.CommanderSlotID))); } if (!string.IsNullOrEmpty(unlock.LimitForChassis)) { var validChassis = unlock.LimitForChassis.Split(','); if (!validChassis.Contains(comm.Unlock.Code)) { return(Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name))); } } if (!IsPrerequisiteUnlockPresent(comm, unlock)) { return(Content(string.Format("{0} missing prerequisite module", unlock.Name))); } var comSlot = comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId); if (comSlot == null) { comSlot = new CommanderModule() { SlotID = slotId }; comm.CommanderModules.Add(comSlot); } comSlot.ModuleUnlockID = unlockId; } else { var oldModule = comm.CommanderModules.FirstOrDefault(x => x.SlotID == slotId); if (oldModule != null) { comm.CommanderModules.Remove(oldModule); } } } } // process decorations foreach (var key in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x))) { var d = Regex.Match(key, "d([0-9]+)"); if (d.Success) { var slotId = int.Parse(d.Groups[1].Value); int unlockId; int.TryParse(Request.Form[key], out unlockId); if (unlockId > 0) { CommanderDecorationSlot decSlot = db.CommanderDecorationSlots.SingleOrDefault(x => x.CommanderDecorationSlotID == slotId); if (decSlot == null) { return(Content("WTF get lost!")); } Unlock unlock = db.Unlocks.SingleOrDefault(x => x.UnlockID == unlockId && x.UnlockType == UnlockTypes.Decoration); if (unlock == null) { return(Content("WTF get lost!")); } if (!unlocks.Any(x => x.Unlock.UnlockID == unlock.UnlockID)) { return(Content("WTF get lost!")); } if (!string.IsNullOrEmpty(unlock.LimitForChassis)) { var validChassis = unlock.LimitForChassis.Split(','); if (!validChassis.Contains(comm.Unlock.Code)) { return(Content(string.Format("{0} cannot be used in commander {1}", unlock.Name, comm.Unlock.Name))); } } var comSlot = comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == slotId); if (comSlot == null) { comSlot = new CommanderDecoration() { SlotID = slotId }; comm.CommanderDecorations.Add(comSlot); } comSlot.DecorationUnlockID = unlockId; } else { var oldDecoration = comm.CommanderDecorations.FirstOrDefault(x => x.SlotID == slotId); if (oldDecoration != null) { comm.CommanderDecorations.Remove(oldDecoration); } } } } // remove a module/decoration if ordered to foreach (var toDel in Request.Form.AllKeys.Where(x => !string.IsNullOrEmpty(x))) { var m = Regex.Match(toDel, "deleteSlot([0-9]+)"); if (m.Success) { var slotId = int.Parse(m.Groups[1].Value); comm.CommanderModules.Remove(comm.CommanderModules.SingleOrDefault(x => x.SlotID == slotId)); } var d = Regex.Match(toDel, "deleteDecorationSlot([0-9]+)"); if (d.Success) { var decSlotId = int.Parse(d.Groups[1].Value); comm.CommanderDecorations.Remove(comm.CommanderDecorations.SingleOrDefault(x => x.SlotID == decSlotId)); } } // cleanup invalid modules? db.SaveChanges(); foreach (var unlock in comm.CommanderModules.GroupBy(x => x.Unlock)) { if (unlock.Key == null) { continue; } var owned = unlocks.Where(x => x.Unlock.UnlockID == unlock.Key.UnlockID).Sum(x => (int?)x.Count) ?? 0; if (owned < unlock.Count()) { var toRemove = unlock.Count() - owned; foreach (var m in unlock.OrderByDescending(x => x.SlotID)) { db.CommanderModules.DeleteOnSubmit(m); //comm.CommanderModules.Remove(m); toRemove--; if (toRemove <= 0) { break; } } } } db.SaveChanges(); scope.Complete(); } return(GetCommanderProfileView(profileNumber)); }
/// <summary> /// Sets up all the things that Springie needs to know for the battle: how to balance, who to get extra commanders, /// what PlanetWars structures to create, etc. /// </summary> public static LobbyHostingContext GetDedicatedServerStartSetup(LobbyHostingContext context) { var ret = context; try { var mode = context.Mode; var commProfiles = new LuaTable(); var db = new ZkDataContext(); // calculate to whom to send extra comms var accountIDsWithExtraComms = new Dictionary <int, int>(); if (mode == AutohostMode.Planetwars || mode == AutohostMode.GameFFA || mode == AutohostMode.Teams) { var groupedByTeam = context.Players.Where(x => !x.IsSpectator).GroupBy(x => x.AllyID).OrderByDescending(x => x.Count()); var biggest = groupedByTeam.FirstOrDefault(); if (biggest != null) { foreach (var other in groupedByTeam.Skip(1)) { var cnt = biggest.Count() - other.Count(); if (cnt > 0) { // example case: 3 players on this team, 8 players on largest team // 5 bonus comms to dole out to this team // per_player = 1 (integer result of 5/3) // remainder: 2, so now cnt = 2 // iterate over all players in this team // first player: cnt == 2, >0 so we give him a second extra comm // second player: cnt == 1, >0 so same deal // from now on cnt <= 0 so the last player only gets the one extra comm int per_player = cnt / other.Count(); cnt = cnt % other.Count(); foreach (var a in other .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)) .OrderByDescending(x => x.GetRating(RatingCategory.Casual).Elo)) { accountIDsWithExtraComms.Add(a.AccountID, per_player + (cnt > 0 ? 1 : 0)); cnt--; } } } } } // write Planetwars details to modoptions (for widget) Faction attacker = null; Faction defender = null; Planet planet = null; if (mode == AutohostMode.Planetwars) { var galaxy = db.Galaxies.First(x => x.IsDefault); planet = galaxy.Planets.First(x => x.Resource.InternalName == context.Map); attacker = context.Players.Where(x => x.AllyID == 0 && !x.IsSpectator) .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)) .Where(x => x.Faction != null) .Select(x => x.Faction) .First(); defender = planet.Faction; if (attacker == defender) { defender = null; } ret.ModOptions["attackingFaction"] = attacker.Shortcut; ret.ModOptions["attackingFactionName"] = attacker.Name; ret.ModOptions["attackingFactionColor"] = attacker.Color; if (defender != null) { ret.ModOptions["defendingFaction"] = defender.Shortcut; ret.ModOptions["defendingFactionName"] = defender.Name; ret.ModOptions["defendingFactionColor"] = defender.Color; } else { ret.ModOptions["defendingFaction"] = "Mercenary"; ret.ModOptions["defendingFactionName"] = "Local militia"; ret.ModOptions["defendingFactionColor"] = "#CCCCCC"; } ret.ModOptions["planet"] = planet.Name; ret.ModOptions["pw_galaxyTurn"] = galaxy.Turn.ToString(); ret.ModOptions["pw_baseIP"] = GlobalConst.BaseInfluencePerBattle.ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_dropshipIP"] = planet.GetEffectiveShipIpBonus(attacker).ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_defenseIP"] = planet.GetEffectiveIpDefense().ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_attackerIP"] = (planet.PlanetFactions.FirstOrDefault(x => x.FactionID == attacker.FactionID)?.Influence ?? 0).ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_maxIP"] = GlobalConst.PlanetWarsMaximumIP.ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_neededIP"] = GlobalConst.InfluenceToCapturePlanet.ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_attackerWinLoseCC"] = GlobalConst.PlanetWarsAttackerWinLoseCcMultiplier.ToString(CultureInfo.InvariantCulture); ret.ModOptions["pw_defenderWinKillCC"] = GlobalConst.PlanetWarsDefenderWinKillCcMultiplier.ToString(CultureInfo.InvariantCulture); } // write player custom keys (level, elo, is muted, etc.) foreach (var p in context.Players) { var user = db.Accounts.Where(x => x.AccountID == p.LobbyID).Include(x => x.RelalationsByOwner).FirstOrDefault(); if (user != null) { var userParams = new Dictionary <string, string>(); ret.UserParameters[p.Name] = userParams; userParams["LobbyID"] = user.AccountID.ToString(); userParams["CountryCode"] = user.HideCountry ? "??" : user.Country; var userBanMuted = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanMute) != null; if (userBanMuted) { userParams["muted"] = "1"; } userParams["faction"] = user.Faction != null ? user.Faction.Shortcut : ""; userParams["clan"] = user.Clan != null ? user.Clan.Shortcut : ""; userParams["clanfull"] = user.Clan != null ? user.Clan.ClanName : ""; userParams["level"] = user.Level.ToString(); //userParams["mm_elo"] = Math.Round(user.EffectiveMmElo).ToString(); //userParams["casual_elo"] = Math.Round(user.EffectiveElo).ToString(); userParams["elo"] = Math.Round(user.GetRating(context.ApplicableRating).Elo).ToString(); userParams["elo_order"] = context.Players.Where(x => !x.IsSpectator) .Select(x => db.Accounts.First(y => y.AccountID == x.LobbyID)) .Where(x => x.GetRating(context.ApplicableRating).Elo > user.GetRating(context.ApplicableRating).Elo) .Count() .ToString(); userParams["icon"] = user.GetIconName(); userParams["avatar"] = user.Avatar; userParams["badges"] = string.Join(",", user.GetBadges()); userParams["admin"] = user.AdminLevel >= AdminLevel.Moderator ? "1" : "0"; userParams["room_boss"] = p.Name == context.FounderName ? "1" : "0"; if (p.PartyID.HasValue) { userParams["PartyID"] = p.PartyID.ToString(); } var userSpecChatBlocked = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanSpecChat) != null;; userParams["can_spec_chat"] = userSpecChatBlocked ? "0" : "1"; userParams["ignored"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Ignore).Select(x => x.Target.Name)); userParams["friends"] = string.Join(",", user.RelalationsByOwner.Where(x => x.Relation == Relation.Friend).Select(x => x.Target.Name)); if (!p.IsSpectator) { // set valid PW structure attackers if (mode == AutohostMode.Planetwars) { userParams["pwRank"] = (user.AccountRolesByAccountID.Where( x => !x.RoleType.IsClanOnly && (x.RoleType.RestrictFactionID == null || x.RoleType.RestrictFactionID == user.FactionID)).OrderBy(x => x.RoleType.DisplayOrder).Select(x => (int?)x.RoleType.DisplayOrder).FirstOrDefault() ?? 999).ToString(); var allied = user.Faction != null && defender != null && user.Faction != defender && defender.HasTreatyRight(user.Faction, x => x.EffectPreventIngamePwStructureDestruction == true, planet); if (!allied && user.Faction != null && (user.Faction == attacker || user.Faction == defender)) { userParams["canAttackPwStructures"] = "1"; } userParams["pwInstructions"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(GetPwInstructions(planet, user, db, attacker))); } if (accountIDsWithExtraComms.ContainsKey(user.AccountID)) { userParams["extracomm"] = accountIDsWithExtraComms[user.AccountID].ToString(); } var commProfileIDs = new LuaTable(); var userCommandersBanned = Punishment.GetActivePunishment(user.AccountID, null, null, null, x => x.BanCommanders) != null; if (!userCommandersBanned) { // set up commander data foreach (var c in user.Commanders.Where(x => x.Unlock != null && x.ProfileNumber <= GlobalConst.CommanderProfileCount) ) { try { var commProfile = new LuaTable(); if (string.IsNullOrEmpty(c.Name) || c.Name.Any(x => x == '"')) { c.Name = c.CommanderID.ToString(); } commProfiles.Add("c" + c.CommanderID, commProfile); commProfileIDs.Add("c" + c.CommanderID); // process decoration icons var decorations = new LuaTable(); foreach (var d in c.CommanderDecorations.Where(x => x.Unlock != null).OrderBy(x => x.SlotID).Select(x => x.Unlock)) { var iconData = db.CommanderDecorationIcons.FirstOrDefault(x => x.DecorationUnlockID == d.UnlockID); if (iconData != null) { string iconName = null, iconPosition = null; // FIXME: handle avatars and preset/custom icons if (iconData.IconType == (int)DecorationIconTypes.Faction) { iconName = user.Faction != null ? user.Faction.Shortcut : null; } else if (iconData.IconType == (int)DecorationIconTypes.Clan) { iconName = user.Clan != null ? user.Clan.Shortcut : null; } if (iconName != null) { iconPosition = CommanderDecoration.GetIconPosition(d); var entry = new LuaTable(); entry.Add("image", iconName); decorations.Add("icon_" + iconPosition.ToLower(), entry); } } else { decorations.Add(d.Code); } } commProfile["name"] = LuaTable.SanitizeString(c.Name.Substring(0, Math.Min(25, c.Name.Length))) ?? "dummy"; commProfile["chassis"] = c.Unlock.Code; commProfile["decorations"] = decorations; var modules = new LuaTable(); commProfile["modules"] = modules; for (var i = 1; i <= GlobalConst.NumCommanderLevels; i++) { var modulesForLevel = new LuaTable(); modules.Add(modulesForLevel); //var modulesOrdered = c.CommanderModules.Where(x => x.CommanderSlot.MorphLevel == i).ToList(); var slots = db.CommanderSlots.ToList().Where(x => x.MorphLevel == i && (x.ChassisID == null || (x.ChassisID == c.ChassisUnlockID))).ToList(); slots.Sort(delegate(CommanderSlot x, CommanderSlot y) { UnlockTypes type1 = x.UnlockType; UnlockTypes type2 = y.UnlockType; if (type1 == UnlockTypes.WeaponManualFire || type1 == UnlockTypes.WeaponBoth) { type1 = UnlockTypes.Weapon; } if (type2 == UnlockTypes.WeaponManualFire || type2 == UnlockTypes.WeaponBoth) { type2 = UnlockTypes.Weapon; } int result = type1.CompareTo(type2); if (result == 0) { return(x.CommanderSlotID.CompareTo(y.CommanderSlotID)); } else { return(result); } }); foreach (var slot in slots) { String value = String.Empty; var module = c.CommanderModules.FirstOrDefault(x => x.SlotID == slot.CommanderSlotID); if (module != null) { value = module.Unlock.Code; } modulesForLevel.Add(value); } } } catch (Exception ex) { Trace.TraceError(ex.ToString()); throw new ApplicationException( $"Error processing commander: {c.CommanderID} - {c.Name} of player {user.AccountID} - {user.Name}", ex); } } } else { userParams["jokecomm"] = "1"; } userParams["commanders"] = commProfileIDs.ToBase64String(); } } } ret.ModOptions["commanderTypes"] = commProfiles.ToBase64String(); /* General-purpose identifier. * Prefer the more specific ones below when possible */ ret.ModOptions["serverType"] = "ZKLS"; /* Access to commands normally accessible only by the host. * Lua calls prepend the / on their own, but not the autohost, * so /say doesn't need it, but the cheat command does */ ret.ModOptions["cheatCommandPrefix"] = "say !hostsay /"; /* The server is listening for SPRINGIE strings (the game can skip those otherwise). * See https://github.com/ZeroK-RTS/Zero-K-Infrastructure/blob/master/Shared/LobbyClient/DedicatedServer.cs#L317 */ ret.ModOptions["sendSpringieData"] = "1"; // set PW structures if (mode == AutohostMode.Planetwars) { var owner = planet.Faction != null ? planet.Faction.Shortcut : ""; var pwStructures = new LuaTable(); foreach ( var s in planet.PlanetStructures.Where(x => x.StructureType != null && !string.IsNullOrEmpty(x.StructureType.IngameUnitName))) { pwStructures.Add(s.StructureType.IngameUnitName, new LuaTable { { "unitname", s.StructureType.IngameUnitName }, { "owner", s.Account?.Name }, { "canBeEvacuated", s.StructureType.IsIngameEvacuable }, { "canBeDestroyed", s.StructureType.IsIngameDestructible }, { "isInactive", !s.IsActive }, { "name", $"{owner} {s.StructureType.Name} ({(s.Account != null ? s.Account.Name : "unowned")})" }, { "description", s.StructureType.Description } }); } ret.ModOptions["planetwarsStructures"] = pwStructures.ToBase64String(); } return(ret); } catch (Exception ex) { Trace.TraceError(ex.ToString()); throw; } }