public ActionResult RemovePunishment(int punishmentID) { var db = new ZkDataContext(); var todel = db.Punishments.First(x => x.PunishmentID == punishmentID); db.Punishments.DeleteOnSubmit(todel); db.SubmitAndMergeChanges(); if (todel.BanLobby) { Account acc = todel.AccountByAccountID; Global.Nightwatch.Tas.AdminUnban(acc.Name); if (todel.BanIP != null) { Global.Nightwatch.Tas.AdminUnban(todel.BanIP); } var otherPenalty = Punishment.GetActivePunishment(acc.AccountID, null, null, x => x.BanLobby, db); if (otherPenalty != null) { var time = otherPenalty.BanExpires - DateTime.Now; double days = time.Value.TotalDays; Global.Nightwatch.Tas.AdminBan(acc.Name, days / 24, otherPenalty.Reason); if (otherPenalty.BanIP != null) { Global.Nightwatch.Tas.AdminBanIP(otherPenalty.BanIP, days / 24, otherPenalty.Reason); } } } return(RedirectToAction("Detail", "Users", new { id = todel.AccountID })); }
public static void UpdateUserFromAccount(User user, Account acc) { user.Name = acc.Name; user.DisplayName = acc.SteamName; user.Avatar = acc.Avatar; user.Level = acc.Level; user.EffectiveMmElo = (int)Math.Round(acc.GetRating(RatingCategory.MatchMaking).Elo); user.EffectiveElo = (int)Math.Round(acc.GetRating(RatingCategory.Casual).Elo); user.RawMmElo = (int)Math.Round(acc.GetRating(RatingCategory.MatchMaking).RealElo); user.SteamID = acc.SteamID?.ToString(); user.IsAdmin = acc.AdminLevel >= AdminLevel.Moderator; user.IsBot = acc.IsBot; user.Country = acc.Country; user.Faction = acc.Faction != null ? acc.Faction.Shortcut : null; user.Clan = acc.Clan != null ? acc.Clan.Shortcut : null; user.AccountID = acc.AccountID; user.Badges = acc.GetBadges().Select(x => x.ToString()).ToList(); user.Icon = acc.GetIconName(); if (user.Badges.Count == 0) { user.Badges = null; // slight optimization for data transfer } Interlocked.Increment(ref user.SyncVersion); user.BanMute = Punishment.GetActivePunishment(acc.AccountID, user.IpAddress, 0, x => x.BanMute) != null; user.BanSpecChat = Punishment.GetActivePunishment(acc.AccountID, user.IpAddress, 0, x => x.BanSpecChat) != null; }
void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) { if (DateTime.UtcNow.Subtract(lastPollCheck).TotalMinutes > 15) { PollController.AutoClosePolls(); lastPollCheck = DateTime.UtcNow; } Account acc = null; if (Request[GlobalConst.ASmallCakeCookieName] != null) { var testAcc = Account.AccountByName(new ZkDataContext(), Request[GlobalConst.ASmallCakeLoginCookieName]); if (testAcc != null) { if (AuthTools.ValidateSiteAuthToken(testAcc.Name, testAcc.Password, Request[GlobalConst.ASmallCakeCookieName])) { acc = testAcc; } } } if (acc == null) { if (Request[GlobalConst.LoginCookieName] != null) { acc = AuthServiceClient.VerifyAccountHashed(Request[GlobalConst.LoginCookieName], Request[GlobalConst.PasswordHashCookieName]); } } if (acc != null) { var ip = GetUserIP(); using (var db = new ZkDataContext()) { var penalty = Punishment.GetActivePunishment(acc.AccountID, ip, null, x => x.BanSite, db); if (penalty != null) { Response.Write(string.Format("You are banned! (IP match to account {0})\n", penalty.AccountByAccountID.Name)); Response.Write(string.Format("Ban expires: {0} UTC\n", penalty.BanExpires)); Response.Write(string.Format("Reason: {0}\n", penalty.Reason)); Response.End(); } else { HttpContext.Current.User = acc; // todo replace with safer permanent cookie Response.SetCookie(new HttpCookie(GlobalConst.LoginCookieName, acc.Name) { Expires = DateTime.Now.AddMonths(12) }); Response.SetCookie(new HttpCookie(GlobalConst.PasswordHashCookieName, acc.Password) { Expires = DateTime.Now.AddMonths(12) }); } } } }
private void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) { if (DateTime.UtcNow.Subtract(lastPollCheck).TotalMinutes > 60) { PollController.AutoClosePolls(); // this is silly here, should be a seaprate timer/thread lastPollCheck = DateTime.UtcNow; } Account acc = null; if (FormsAuthentication.IsEnabled && User.Identity.IsAuthenticated) { acc = Account.AccountByName(new ZkDataContext(), User.Identity.Name); } else if (Request[GlobalConst.SessionTokenVariable] != null) { int id = 0; if (Global.Server?.SessionTokens.TryRemove(Request[GlobalConst.SessionTokenVariable], out id) == true) { acc = new ZkDataContext().Accounts.Find(id); } } if (acc != null) { var ip = Request.UserHostAddress; var lastLogin = acc.AccountUserIDs.OrderByDescending(x => x.LastLogin).FirstOrDefault(); var userID = lastLogin?.UserID; var installID = lastLogin?.InstallID; var penalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, installID, x => x.BanSite); if (penalty != null) { Response.Write(string.Format("You are banned! (IP match to account {0})\n", penalty.AccountByAccountID.Name)); Response.Write(string.Format("Ban expires: {0} UTC\n", penalty.BanExpires)); Response.Write(string.Format("Reason: {0}\n", penalty.Reason)); Response.End(); } else { HttpContext.Current.User = acc; FormsAuthentication.SetAuthCookie(acc.Name, true); } } // remove cake from URL var removeCake = Regex.Replace(Request.Url.ToString(), $"([?|&])({GlobalConst.SessionTokenVariable}=[^&?]+[?|&]*)", m => m.Groups[1].Value); if (removeCake != Request.Url.ToString()) { Response.Redirect(removeCake, true); } }
public ActionResult VotePost(int forumPostID, int delta) { var db = new ZkDataContext(); var myAcc = Global.Account; var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum); if (penalty != null) { return(Content(string.Format("You cannot vote while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason))); } if (myAcc.Level < GlobalConst.MinLevelForForumVote) { return(Content(string.Format("You cannot vote until you are level {0} or higher", GlobalConst.MinLevelForForumVote))); } if ((Global.Account.ForumTotalUpvotes - Global.Account.ForumTotalDownvotes) < GlobalConst.MinNetKarmaToVote) { return(Content("Your net karma is too low to vote")); } if (delta > 1) { delta = 1; } else if (delta < -1) { delta = -1; } var post = db.ForumPosts.First(x => x.ForumPostID == forumPostID); var author = post.Account; if (author.AccountID == Global.AccountID) { return(Content("Cannot vote for your own posts")); } if (myAcc.VotesAvailable <= 0) { return(Content("Out of votes")); } var existingVote = db.AccountForumVotes.SingleOrDefault(x => x.ForumPostID == forumPostID && x.AccountID == Global.AccountID); if (existingVote != null) // clear existing vote { var oldDelta = existingVote.Vote; // reverse vote effects if (oldDelta > 0) { author.ForumTotalUpvotes = author.ForumTotalUpvotes - oldDelta; post.Upvotes = post.Upvotes - oldDelta; } else if (oldDelta < 0) { author.ForumTotalDownvotes = author.ForumTotalDownvotes + oldDelta; post.Downvotes = post.Downvotes + oldDelta; } db.AccountForumVotes.DeleteOnSubmit(existingVote); } if (delta > 0) { author.ForumTotalUpvotes = author.ForumTotalUpvotes + delta; post.Upvotes = post.Upvotes + delta; } else if (delta < 0) { author.ForumTotalDownvotes = author.ForumTotalDownvotes - delta; post.Downvotes = post.Downvotes - delta; } if (delta != 0) { var voteEntry = new AccountForumVote { AccountID = Global.AccountID, ForumPostID = forumPostID, Vote = delta }; db.AccountForumVotes.InsertOnSubmit(voteEntry); myAcc.VotesAvailable--; } db.SaveChanges(); return(RedirectToAction("Thread", new { id = post.ForumThreadID, postID = forumPostID })); }
public ActionResult SubmitPost( int?threadID, int?categoryID, int?resourceID, int?missionID, int?springBattleID, int?clanID, int?planetID, string text, string title, string wikiKey, int?forumPostID, bool?isMinorEdit) { if (threadID == null && missionID == null && resourceID == null && springBattleID == null && clanID == null && planetID == null && forumPostID == null && string.IsNullOrWhiteSpace(title)) { return(Content("Cannot post new thread with blank title")); } if (string.IsNullOrWhiteSpace(text)) { return(Content("Please type some text :)")); } var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum); if (penalty != null) { return (Content( string.Format("You cannot post while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason))); } var db = new ZkDataContext(); using (var scope = new TransactionScope()) { var thread = db.ForumThreads.SingleOrDefault(x => x.ForumThreadID == threadID); var category = thread?.ForumCategory; if (category == null && categoryID != null) { category = db.ForumCategories.FirstOrDefault(x => x.ForumCategoryID == categoryID); } string currentTitle = null; // update title if (thread != null && !string.IsNullOrEmpty(title)) { currentTitle = thread.Title; thread.Title = title; thread.WikiKey = wikiKey; } if (thread != null && planetID != null) { var planet = db.Planets.Single(x => x.PlanetID == planetID); thread.Title = "Planet " + planet.Name; } if (thread != null && clanID != null) { var clan = db.Clans.Single(x => x.ClanID == clanID); thread.Title = "Clan " + clan.ClanName; } if (thread != null && missionID != null) { var mission = db.Missions.Single(x => x.MissionID == missionID); thread.Title = "Mission " + mission.Name; } if (thread != null && resourceID != null) { var map = db.Resources.Single(x => x.ResourceID == resourceID); thread.Title = "Map " + map.InternalName; } if (threadID == null && category != null) // new thread { if (category.IsLocked) { return(Content("Thread is locked")); } if (category.ForumMode == ForumMode.Wiki) { if (string.IsNullOrEmpty(wikiKey) || !Account.IsValidLobbyName(wikiKey)) { return(Content("You need to set a valid wiki key")); } if (db.ForumThreads.Any(y => y.WikiKey == wikiKey)) { return(Content("This wiki key already exists")); } } if (string.IsNullOrEmpty(title)) { return(Content("Title cannot be empty")); } thread = new ForumThread(); thread.CreatedAccountID = Global.AccountID; thread.Title = title; thread.WikiKey = wikiKey; thread.ForumCategoryID = category.ForumCategoryID; db.ForumThreads.InsertOnSubmit(thread); } if (thread == null && resourceID != null) // non existing thread, we posted new post on map { var res = db.Resources.Single(x => x.ResourceID == resourceID); if (res.ForumThread != null) { return(Content("Double post")); } thread = new ForumThread { Title = "Map " + res.InternalName, CreatedAccountID = Global.AccountID, LastPostAccountID = Global.AccountID }; thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Maps); res.ForumThread = thread; db.ForumThreads.InsertOnSubmit(thread); } if (thread == null && springBattleID != null) // non existing thread, we posted new post on battle { var bat = db.SpringBattles.Single(x => x.SpringBattleID == springBattleID); if (bat.ForumThread != null) { return(Content("Double post")); } thread = new ForumThread { Title = bat.FullTitle, CreatedAccountID = Global.AccountID, LastPostAccountID = Global.AccountID }; thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.SpringBattles); bat.ForumThread = thread; db.ForumThreads.InsertOnSubmit(thread); } if (thread == null && clanID != null) { var clan = db.Clans.Single(x => x.ClanID == clanID); if (clan.ForumThread != null) { return(Content("Double post")); } thread = new ForumThread { Title = "Clan " + clan.ClanName, CreatedAccountID = Global.AccountID, LastPostAccountID = Global.AccountID }; thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Clans); clan.ForumThread = thread; thread.Clan = clan; db.ForumThreads.InsertOnSubmit(thread); } if (thread == null && planetID != null) { var planet = db.Planets.Single(x => x.PlanetID == planetID); if (planet.ForumThread != null) { return(Content("Double post")); } thread = new ForumThread { Title = "Planet " + planet.Name, CreatedAccountID = Global.AccountID, LastPostAccountID = Global.AccountID }; thread.ForumCategory = db.ForumCategories.FirstOrDefault(x => x.ForumMode == ForumMode.Planets); planet.ForumThread = thread; db.ForumThreads.InsertOnSubmit(thread); } if (thread == null) { return(Content("Thread not found")); } if (thread.IsLocked && Global.Account.AdminLevel < AdminLevel.Moderator) { return(Content("Thread is locked")); } if (thread.RestrictedClanID != null && thread.RestrictedClanID != Global.Account.ClanID) { return(Content("Cannot post in this clan")); } var lastPost = thread.ForumPosts.OrderByDescending(x => x.ForumPostID).FirstOrDefault(); int?gotoPostId = null; //double post preventer if (lastPost == null || lastPost.AuthorAccountID != Global.AccountID || lastPost.Text != text || (!string.IsNullOrEmpty(title) && title != currentTitle)) { if (forumPostID != null) { var post = thread.ForumPosts.Single(x => x.ForumPostID == forumPostID); if (!post.CanEdit(Global.Account)) { throw new ApplicationException("Not authorized to edit the post"); } post.ForumPostEdits.Add( new ForumPostEdit { EditorAccountID = Global.AccountID, EditTime = DateTime.UtcNow, OriginalText = post.Text, NewText = text }); post.Text = text; } else { var p = new ForumPost { AuthorAccountID = Global.AccountID, Text = text, Created = DateTime.UtcNow }; thread.ForumPosts.Add(p); db.SaveChanges(); gotoPostId = p.ForumPostID; } if (isMinorEdit != true) { thread.LastPost = DateTime.UtcNow; thread.LastPostAccountID = Global.AccountID; } thread.PostCount = thread.ForumPosts.Count(); thread.UpdateLastRead(Global.AccountID, true, thread.LastPost); db.SaveChanges(); } scope.Complete(); if (missionID.HasValue) { return(RedirectToAction("Detail", "Missions", new { id = missionID })); } if (resourceID.HasValue) { return(RedirectToAction("Detail", "Maps", new { id = resourceID })); } if (springBattleID.HasValue) { return(RedirectToAction("Detail", "Battles", new { id = springBattleID })); } if (clanID.HasValue) { return(RedirectToAction("Detail", "Clans", new { id = clanID })); } if (planetID.HasValue) { return(RedirectToAction("Planet", "Planetwars", new { id = planetID })); } if (forumPostID.HasValue) { return(RedirectToAction("Thread", "Forum", new { id = thread.ForumThreadID, postID = forumPostID })); } return(RedirectToAction("Thread", "Forum", new { id = thread.ForumThreadID, postID = gotoPostId })); } }
public ActionResult NewPost(int?categoryID, int?threadID, int?forumPostID, string wikiKey) { var res = new NewPostResult(); var db = new ZkDataContext(); var penalty = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanForum); if (penalty != null) { return (Content( string.Format("You cannot post while banned from forum!\nExpires: {0} UTC\nReason: {1}", penalty.BanExpires, penalty.Reason))); } if (threadID.HasValue && threadID > 0) { var clan = db.Clans.FirstOrDefault(x => x.ForumThreadID == threadID); if (clan != null && Global.ClanID != clan.ClanID) { return(Content(string.Format("You are not a member of {0}, you cannot post in their clan thread", clan.ClanName))); } var t = db.ForumThreads.Single(x => x.ForumThreadID == threadID.Value); res.CurrentThread = t; res.LastPosts = res.CurrentThread.ForumPosts.OrderByDescending(x => x.ForumPostID).Take(20); if (!categoryID.HasValue) { categoryID = t.ForumCategoryID; } } if (!categoryID.HasValue) { categoryID = db.ForumCategories.Where(x => !x.IsLocked && x.ForumMode == ForumMode.General).OrderBy(x => x.SortOrder).First().ForumCategoryID; // post in general by default } var category = db.ForumCategories.FirstOrDefault(x => x.ForumCategoryID == categoryID); res.Path = category?.GetPath() ?? new List <ForumCategory>(); res.CurrentCategory = category; if (forumPostID != null) { var post = db.ForumPosts.Single(x => x.ForumPostID == forumPostID); if (!post.CanEdit(Global.Account)) { return(Content("You cannot edit this post")); } res.EditedPost = post; } if (threadID != null) { var thread = res.CurrentThread; res.CanSetTopic = (thread.ForumPosts.Count > 0 && thread.ForumPosts.First().ForumPostID == forumPostID && (category.ForumMode == ForumMode.General || category.ForumMode == ForumMode.Wiki || category.ForumMode == ForumMode.Archive)); } else { res.CanSetTopic = true; } res.WikiKey = wikiKey; return(View(res)); }
public async Task <LoginCheckerResponse> DoLogin(Login login, string ip) { await semaphore.WaitAsync(); try { var userID = login.UserID; var lobbyVersion = login.LobbyVersion; using (var db = new ZkDataContext()) { if (!VerifyIp(ip)) { return(new LoginCheckerResponse(LoginResponse.Code.BannedTooManyConnectionAttempts)); } SteamWebApi.PlayerInfo info = null; if (!string.IsNullOrEmpty(login.SteamAuthToken)) { info = await server.SteamWebApi.VerifyAndGetAccountInformation(login.SteamAuthToken); if (info == null) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.InvalidSteamToken)); } } Account accBySteamID = null; Account accByLogin = null; if (info != null) { accBySteamID = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.SteamID == info.steamid); } if (!string.IsNullOrEmpty(login.Name)) { var loginToUpper = login.Name.ToUpper(); accByLogin = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name) ?? db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name.ToUpper() == loginToUpper); } if (accBySteamID == null) { if (accByLogin == null) { LogIpFailure(ip); if (!string.IsNullOrEmpty(login.Name)) { return(new LoginCheckerResponse(LoginResponse.Code.InvalidName)); } else { return(new LoginCheckerResponse(LoginResponse.Code.SteamNotLinkedAndLoginMissing)); } } if (string.IsNullOrEmpty(login.PasswordHash) || !accByLogin.VerifyPassword(login.PasswordHash)) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.InvalidPassword)); } } var acc = accBySteamID ?? accByLogin; var ret = new LoginCheckerResponse(LoginResponse.Code.Ok); ret.LoginResponse.Name = acc.Name; var user = ret.User; acc.Country = ResolveCountry(ip); if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country)) { acc.Country = "??"; } acc.LobbyVersion = lobbyVersion; acc.LastLogin = DateTime.UtcNow; if (info != null) { if (db.Accounts.Any(x => x.SteamID == info.steamid && x.Name != acc.Name)) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.SteamLinkedToDifferentAccount)); } acc.SteamID = info.steamid; acc.SteamName = info.personaname; } user.LobbyVersion = login.LobbyVersion; user.IpAddress = ip; UpdateUserFromAccount(user, acc); LogIP(db, acc, ip); LogUserID(db, acc, userID); db.SaveChanges(); ret.LoginResponse.SessionToken = Guid.NewGuid().ToString(); // create session token var banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby); if (banPenalty != null) { return (BlockLogin( $"Banned until {banPenalty.BanExpires} (match to {banPenalty.AccountByAccountID.Name}), reason: {banPenalty.Reason}", acc, ip, userID)); } if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled) { if (HasVpn(ip, acc, db)) { return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID)); } } return(ret); } } finally { semaphore.Release(); } }
public async Task <RegisterResponse> DoRegister(Register register, string ip) { if (!Account.IsValidLobbyName(register.Name)) { return(new RegisterResponse(RegisterResponse.Code.NameHasInvalidCharacters)); } if (server.ConnectedUsers.ContainsKey(register.Name)) { return(new RegisterResponse(RegisterResponse.Code.AlreadyConnected)); } if (string.IsNullOrEmpty(register.PasswordHash) && string.IsNullOrEmpty(register.SteamAuthToken)) { return(new RegisterResponse(RegisterResponse.Code.MissingBothPasswordAndToken)); } if (!VerifyIp(ip)) { return(new RegisterResponse(RegisterResponse.Code.BannedTooManyAttempts)); } var banPenalty = Punishment.GetActivePunishment(null, ip, register.UserID, x => x.BanLobby); if (banPenalty != null) { return new RegisterResponse(RegisterResponse.Code.Banned) { BanReason = banPenalty.Reason } } ; SteamWebApi.PlayerInfo info = null; if (!string.IsNullOrEmpty(register.SteamAuthToken)) { info = await server.SteamWebApi.VerifyAndGetAccountInformation(register.SteamAuthToken); if (info == null) { return(new RegisterResponse(RegisterResponse.Code.InvalidSteamToken)); } } using (var db = new ZkDataContext()) { var registerName = register.Name.ToUpper(); var existingByName = db.Accounts.FirstOrDefault(x => x.Name.ToUpper() == registerName); if (existingByName != null) { if (info != null && existingByName.SteamID == info.steamid) { return(new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisSteamToken)); } if (info == null && !string.IsNullOrEmpty(register.PasswordHash) && existingByName.VerifyPassword(register.PasswordHash)) { return(new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisPassword)); } return(new RegisterResponse(RegisterResponse.Code.NameAlreadyTaken)); } var acc = new Account() { Name = register.Name }; acc.SetPasswordHashed(register.PasswordHash); acc.SetName(register.Name); acc.SetAvatar(); acc.Email = register.Email; if (info != null) { var existingBySteam = db.Accounts.FirstOrDefault(x => x.SteamID == info.steamid); if (existingBySteam != null) { return(new RegisterResponse(RegisterResponse.Code.SteamAlreadyRegistered)); } acc.SteamID = info.steamid; acc.SteamName = info.personaname; } else if (string.IsNullOrEmpty(register.PasswordHash)) { return(new RegisterResponse(RegisterResponse.Code.InvalidPassword)); } LogIP(db, acc, ip); LogUserID(db, acc, register.UserID); db.Accounts.Add(acc); db.SaveChanges(); } return(new RegisterResponse(RegisterResponse.Code.Ok)); }
/// <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; } }
public LoginResponse Login(User user, Login login, Client client) { string ip = client.RemoteEndpointIP; long userID = login.UserID; string lobbyVersion = login.LobbyVersion; using (var db = new ZkDataContext()) { Account acc = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name); if (acc == null) { return new LoginResponse { ResultCode = LoginResponse.Code.InvalidName } } ; if (!acc.VerifyPassword(login.PasswordHash)) { return new LoginResponse { ResultCode = LoginResponse.Code.InvalidPassword } } ; if (state.Clients.ContainsKey(login.Name)) { return new LoginResponse { ResultCode = LoginResponse.Code.AlreadyConnected } } ; acc.Country = ResolveCountry(ip); acc.LobbyVersion = lobbyVersion; acc.LastLogin = DateTime.UtcNow; user.ClientType = login.ClientType; user.LobbyVersion = login.LobbyVersion; UpdateUserFromAccount(user, acc); LogIP(db, acc, ip); LogUserID(db, acc, userID); db.SaveChanges(); var banMute = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanMute, db); if (banMute != null) { user.BanMute = true; } Punishment banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby, db); if (banPenalty != null) { return (BlockLogin( string.Format("Banned until {0} (match to {1}), reason: {2}", banPenalty.BanExpires, banPenalty.AccountByAccountID.Name, banPenalty.Reason), acc, ip, userID)); } Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490); if (accAnteep != null) { if (accAnteep.AccountUserIDs.Any(y => y.UserID == userID)) { Talk(String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", acc.Name, userID, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } if (userID > 0 && userID < 1000) { Talk(String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", acc.Name, userID, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } if (accAnteep.AccountIPs.Any(y => y.IP == ip)) { Talk(String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", acc.Name, ip, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } } if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled) { // check user IP against http://dnsbl.tornevall.org // does not catch all smurfs // mostly false positives, do not use string reversedIP = string.Join(".", ip.Split('.').Reverse().ToArray()); try { IPAddress[] resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList; if (resolved.Length > 0) { Talk(String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", acc.Name, ip, resolved.Length, string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl))); } } catch (SocketException sockEx) { // not in database, do nothing } } try { if (!acc.HasVpnException) { for (int i = 0; i <= 1; i++) { var whois = new Whois(); Dictionary <string, string> data = whois.QueryByIp(ip, i == 1); if (!data.ContainsKey("netname")) { data["netname"] = "UNKNOWN NETNAME"; } if (!data.ContainsKey("org-name")) { data["org-name"] = "UNKNOWN ORG"; } if (!data.ContainsKey("abuse-mailbox")) { data["abuse-mailbox"] = "no mailbox"; } if (!data.ContainsKey("notify")) { data["notify"] = "no notify address"; } if (!data.ContainsKey("role")) { data["role"] = "UNKNOWN ROLE"; } if (!data.ContainsKey("descr")) { data["descr"] = "no description"; } if (!data.ContainsKey("remarks")) { data["remarks"] = "no remarks"; } List <string> blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList(); List <string> blockedHosts = db.BlockedHosts.Select(x => x.HostName).ToList(); /*if (acc.Country == "MY") * { * client.Say(SayPlace.User, "KingRaptor", String.Format("USER {0}\nnetname: {1}\norgname: {2}\ndescr: {3}\nabuse-mailbox: {4}", * acc.Name, data["netname"], data["org-name"], data["descr"], data["abuse-mailbox"]), false); * }*/ bool blockedHost = blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) || (blockedHosts.Any(x => data["notify"].Contains(x))); foreach (string company in blockedCompanies) { if (data["netname"].ToLower().Contains(company) || data["org-name"].ToLower().Contains(company) || data["descr"].ToLower().Contains(company) || data["role"].ToLower().Contains(company) || data["remarks"].ToLower().Contains(company)) { blockedHost = true; break; } } string hostname = Dns.GetHostEntry(ip).HostName; if (blockedHosts.Any(hostname.Contains)) { blockedHost = true; } if (blockedHost) { return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID)); } } } } catch (SocketException sockEx) {} catch (Exception ex) { Trace.TraceError("VPN check error: {0}", ex); } if (state.Clients.TryAdd(login.Name, client)) { return new LoginResponse { ResultCode = LoginResponse.Code.Ok } } ; else { return new LoginResponse() { ResultCode = LoginResponse.Code.AlreadyConnected } }; } } string ResolveCountry(string ip) { if (IsLanIP(ip)) { return("CZ"); } else { try { return(geoIP.Country(ip).Country.IsoCode); } catch (Exception ex) { Trace.TraceWarning("{0} Unable to resolve country", this); return("??"); } } } LoginResponse BlockLogin(string reason, Account acc, string ip, long user_id) { Talk(string.Format("Login denied for {0} IP:{1} ID:{2} reason: {3}", acc.Name, ip, user_id, reason)); return(new LoginResponse { Reason = reason, ResultCode = LoginResponse.Code.Banned }); }
public async Task<RegisterResponse> DoRegister(Register register, string ip) { if (!Account.IsValidLobbyName(register.Name)) return new RegisterResponse(RegisterResponse.Code.NameHasInvalidCharacters); if (server.ConnectedUsers.ContainsKey(register.Name)) return new RegisterResponse(RegisterResponse.Code.AlreadyConnected); if (string.IsNullOrEmpty(register.PasswordHash) && string.IsNullOrEmpty(register.SteamAuthToken)) return new RegisterResponse(RegisterResponse.Code.MissingBothPasswordAndToken); if (!VerifyIp(ip)) return new RegisterResponse(RegisterResponse.Code.BannedTooManyAttempts); var banPenalty = Punishment.GetActivePunishment(null, ip, register.UserID, register.InstallID, x => x.BanLobby); if (banPenalty != null) return new RegisterResponse(RegisterResponse.Code.Banned) {BanReason = banPenalty.Reason}; SteamWebApi.PlayerInfo info = null; if (!string.IsNullOrEmpty(register.SteamAuthToken)) { info = await server.SteamWebApi.VerifyAndGetAccountInformation(register.SteamAuthToken); if (info == null) return new RegisterResponse(RegisterResponse.Code.InvalidSteamToken); } using (var db = new ZkDataContext()) { var registerName = register.Name.ToUpper(); var existingByName = db.Accounts.FirstOrDefault(x => x.Name.ToUpper() == registerName); if (existingByName != null) { if (info != null && existingByName.SteamID == info.steamid) return new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisSteamToken); if (info == null && !string.IsNullOrEmpty(register.PasswordHash) && existingByName.VerifyPassword(register.PasswordHash)) return new RegisterResponse(RegisterResponse.Code.AlreadyRegisteredWithThisPassword); return new RegisterResponse(RegisterResponse.Code.NameAlreadyTaken); } var acc = new Account() { Name = register.Name }; acc.SetPasswordHashed(register.PasswordHash); acc.SetName(register.Name); acc.SetAvatar(); acc.Email = register.Email; if (info != null) { var existingBySteam = db.Accounts.FirstOrDefault(x => x.SteamID == info.steamid); if (existingBySteam != null) return new RegisterResponse(RegisterResponse.Code.SteamAlreadyRegistered); acc.SteamID = info.steamid; acc.SteamName = info.personaname; } else if (string.IsNullOrEmpty(register.PasswordHash)) { return new RegisterResponse(RegisterResponse.Code.InvalidPassword); } LogIP(db, acc, ip); LogUserID(db, acc, register.UserID, register.InstallID); db.Accounts.Add(acc); db.SaveChanges(); var smurfs = acc.GetSmurfs().Where(a => a.PunishmentsByAccountID.Any(x => x.BanExpires > DateTime.UtcNow)); if (smurfs.Any()) { await server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("Smurf Alert! {0} might be a smurf of {1}. Check https://zero-k.info/Users/AdminUserDetail/{2}", acc.Name, smurfs.OrderByDescending(x => x.Level).First().Name, acc.AccountID)); } } return new RegisterResponse(RegisterResponse.Code.Ok); }
public async Task <ActionResult> ChatMessages(ChatModel model) { model = model ?? new ChatModel(); var db = new ZkDataContext(); bool isMuted = Punishment.GetActivePunishment(Global.AccountID, Request.UserHostAddress, 0, null, x => x.BanMute) != null; var minTime = DateTime.UtcNow.AddDays(-30); if (!string.IsNullOrEmpty(model.Channel)) { // only show allowed channels if (!Global.Server.ChannelManager.CanJoin(Global.Account, model.Channel)) { return(PartialView("LobbyChatMessages", model)); } if (!String.IsNullOrEmpty(model.Message) && !isMuted) { await Global.Server.GhostSay(new Say() { IsEmote = false, Place = SayPlace.Channel, Ring = false, Source = SaySource.Zk, Target = model.Channel, Text = model.Message, Time = DateTime.UtcNow, User = Global.Account.Name, }); } string channelName = model.Channel; model.Data = db.LobbyChatHistories .SqlQuery("SELECT TOP 30 * FROM [dbo].[LobbyChatHistories] WHERE [Target] = {0} AND [SayPlace] = {1} AND [Time] > {2} ORDER BY [Time] DESC", channelName, SayPlace.Channel, minTime) .ToList().OrderBy(x => x.Time).AsQueryable(); //Note if using Take(), it will be slow for uncommon channels like zktourney when ordering by Time and slow for common channels like zk if ordering by ID } else if (!string.IsNullOrEmpty(model.User)) { if (!String.IsNullOrEmpty(model.Message) && !isMuted) { await Global.Server.GhostSay(new Say() { IsEmote = false, Place = SayPlace.User, Ring = false, Source = SaySource.Zk, Target = model.User, Text = model.Message, Time = DateTime.UtcNow, User = Global.Account.Name, }); } string otherName = model.User; string myName = Global.Account.Name; //Users can abuse rename to gain access to other users PMs, it's a feature model.Data = db.LobbyChatHistories .Where(x => (x.User == otherName && x.Target == myName || x.User == myName && x.Target == otherName) && x.SayPlace == SayPlace.User && x.Time > minTime) .OrderByDescending(x => x.Time).Take(30) .ToList().OrderBy(x => x.Time).AsQueryable(); } else { string myName = Global.Account.Name; var ignoredIds = db.AccountRelations.Where(x => (x.Relation == Relation.Ignore) && (x.OwnerAccountID == Global.AccountID)).Select(x => x.TargetAccountID).ToList(); var ignoredNames = db.Accounts.Where(x => ignoredIds.Contains(x.AccountID)).Select(x => x.Name).ToHashSet(); model.Data = db.LobbyChatHistories .Where(x => x.Target == myName && x.SayPlace == SayPlace.User && x.Time > minTime) .OrderByDescending(x => x.Time).Take(30) .ToList() .Where(x => !ignoredNames.Contains(x.User)) .OrderBy(x => x.Time) .AsQueryable(); } model.Message = ""; return(PartialView("LobbyChatMessages", model)); }
/// <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; } }
public async Task <LoginCheckerResponse> DoLogin(Login login, string ip, List <ulong> dlc) { var limit = MiscVar.ZklsMaxUsers; if (limit > 0 && server.ConnectedUsers.Count >= limit) { return(new LoginCheckerResponse(LoginResponse.Code.ServerFull)); } await semaphore.WaitAsync(); try { var userID = login.UserID; var installID = login.InstallID; var lobbyVersion = login.LobbyVersion; using (var db = new ZkDataContext()) { if (!VerifyIp(ip)) { return(new LoginCheckerResponse(LoginResponse.Code.BannedTooManyConnectionAttempts)); } SteamWebApi.PlayerInfo info = null; if (!string.IsNullOrEmpty(login.SteamAuthToken)) { info = await server.SteamWebApi.VerifyAndGetAccountInformation(login.SteamAuthToken); if (info == null) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.InvalidSteamToken)); } } Account accBySteamID = null; Account accByLogin = null; if (info != null) { accBySteamID = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.SteamID == info.steamid); } if (!string.IsNullOrEmpty(login.Name)) { accByLogin = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name) ?? db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name.Equals(login.Name, StringComparison.CurrentCultureIgnoreCase)); } if (accBySteamID == null) { if (accByLogin == null) { LogIpFailure(ip); if (!string.IsNullOrEmpty(login.Name)) { return(new LoginCheckerResponse(LoginResponse.Code.InvalidName)); } else { return(new LoginCheckerResponse(LoginResponse.Code.SteamNotLinkedAndLoginMissing)); } } if (string.IsNullOrEmpty(login.PasswordHash) || !accByLogin.VerifyPassword(login.PasswordHash)) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.InvalidPassword)); } } var acc = accBySteamID ?? accByLogin; var ret = new LoginCheckerResponse(LoginResponse.Code.Ok); ret.LoginResponse.Name = acc.Name; var user = ret.User; acc.Country = ResolveCountry(ip); if ((acc.Country == null) || string.IsNullOrEmpty(acc.Country)) { acc.Country = "??"; } acc.LobbyVersion = lobbyVersion; acc.LastLogin = DateTime.UtcNow; if (info != null) { if (db.Accounts.Any(x => x.SteamID == info.steamid && x.Name != acc.Name)) { LogIpFailure(ip); return(new LoginCheckerResponse(LoginResponse.Code.SteamLinkedToDifferentAccount)); } acc.SteamID = info.steamid; acc.SteamName = info.personaname; } user.LobbyVersion = login.LobbyVersion; user.IpAddress = ip; acc.VerifyAndAddDlc(dlc); UpdateUserFromAccount(user, acc); LogIP(db, acc, ip); LogUserID(db, acc, userID, installID); if (String.IsNullOrEmpty(installID) && !acc.HasVpnException) { await server.GhostChanSay(GlobalConst.ModeratorChannel, string.Format("{0} just logged in with an unsupported lobby https://zero-k.info/Users/AdminUserDetail/{1}", acc.Name, acc.AccountID)); } db.SaveChanges(); ret.LoginResponse.SessionToken = Guid.NewGuid().ToString(); // create session token var banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, installID, x => x.BanLobby); if (banPenalty != null) { return (BlockLogin( $"Banned until {banPenalty.BanExpires} (match to {banPenalty.AccountByAccountID.Name}), reason: {banPenalty.Reason}", acc, ip, userID, installID)); } if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled) { if (HasVpn(ip, acc, db)) { return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID, installID)); } } return(ret); } } finally { semaphore.Release(); } }
public AuthService(TasClient client) { this.client = client; /* * this.client.Input += (s, e) => * { * Console.WriteLine(e.Command +" "+ Utils.Glue(e.Args)); * }; * this.client.Output += (s, e) => * { * Console.WriteLine(e.Data.Key + " " +Utils.Glue(e.Data.Value.Select(x=>x.ToString()).ToArray())); * };*/ this.client.LoginAccepted += (s, e) => { requests.Clear(); client.JoinChannel(ModeratorChannel); client.JoinChannel(Top20Channel); using (var db = new ZkDataContext()) foreach (var fac in db.Factions.Where(x => !x.IsDeleted)) { client.JoinChannel(fac.Shortcut); } }; this.client.TestLoginAccepted += (s, e) => { RequestInfo entry; if (requests.TryGetValue(client.MessageID, out entry)) { entry.CorrectName = e.ServerParams[0]; entry.LobbyID = Convert.ToInt32(e.ServerParams[1]); if (client.ExistingUsers.ContainsKey(entry.CorrectName)) { entry.User = client.ExistingUsers[entry.CorrectName]; } entry.WaitHandle.Set(); } requests.TryRemove(client.MessageID, out entry); }; this.client.UserAdded += (s, e) => { using (var db = new ZkDataContext()) { var acc = Account.AccountByLobbyID(db, e.Data.LobbyID); if (acc != null) { this.client.Extensions.PublishAccountData(acc); if (acc.SpringieLevel > 2 || acc.IsZeroKAdmin) { client.ForceJoinChannel(e.Data.Name, ModeratorChannel); } if (topPlayers.IsTop20(e.Data.LobbyID)) { client.ForceJoinChannel(e.Data.Name, Top20Channel); } if (acc.Clan != null) { client.ForceJoinChannel(e.Data.Name, acc.Clan.GetClanChannel(), acc.Clan.Password); } if (acc.Faction != null && acc.Level >= GlobalConst.FactionChannelMinLevel && acc.CanPlayerPlanetWars()) { client.ForceJoinChannel(e.Data.Name, acc.Faction.Shortcut); } } client.RequestUserIP(e.Data.Name); client.RequestUserID(e.Data.Name); } }; this.client.UserIDRecieved += (sender, args) => { Task.Factory.StartNew(() => { try { using (var db = new ZkDataContext()) { var acc = Account.AccountByName(db, args.Name); var penalty = Punishment.GetActivePunishment(acc != null ? acc.AccountID : 0, null, args.ID, x => x.BanLobby, db); if (penalty != null) { client.AdminKickFromLobby(args.Name, string.Format("Banned until {0} (ID match to {1}), reason: {2}", penalty.BanExpires, penalty.AccountByAccountID.Name, penalty.Reason)); } ; if (acc != null && args.ID != 0) { var entry = acc.AccountUserIDS.FirstOrDefault(x => x.UserID == args.ID); if (entry == null) { entry = new AccountUserID { AccountID = acc.AccountID, UserID = args.ID, FirstLogin = DateTime.UtcNow }; db.AccountUserIDS.InsertOnSubmit(entry); } entry.LoginCount++; entry.LastLogin = DateTime.UtcNow; } Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490); bool isAnteepSmurf = accAnteep.AccountUserIDS.Any(x => x.UserID == args.ID); if (isAnteepSmurf) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", args.Name, args.ID, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); } if (args.ID != 0 && args.ID < 1000) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", args.Name, args.ID, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); } db.SubmitChanges(); } } catch (Exception ex) { Trace.TraceError("Error getting user ID: {0}", ex); } }); }; this.client.UserIPRecieved += (sender, args) => { Task.Factory.StartNew(() => { try { Account acc = null; using (var db = new ZkDataContext()) { acc = Account.AccountByName(db, args.Name); var penalty = Punishment.GetActivePunishment(acc != null ? acc.AccountID : 0, args.IP, null, x => x.BanLobby, db); if (penalty != null) { client.AdminKickFromLobby(args.Name, string.Format("Banned until {0} (IP match to {1}), reason: {2}", penalty.BanExpires, penalty.AccountByAccountID.Name, penalty.Reason)); } if (acc != null) { var entry = acc.AccountIPS.FirstOrDefault(x => x.IP == args.IP); if (entry == null) { entry = new AccountIP { AccountID = acc.AccountID, IP = args.IP, FirstLogin = DateTime.UtcNow }; db.AccountIPS.InsertOnSubmit(entry); } entry.LoginCount++; entry.LastLogin = DateTime.UtcNow; } db.SubmitChanges(); } try { if (acc == null || !acc.HasVpnException) { if (GlobalConst.VpnCheckEnabled) { // check user IP against http://dnsbl.tornevall.org // does not catch all smurfs // mostly false positives, do not use var reversedIP = string.Join(".", args.IP.Split('.').Reverse().ToArray()); try { var resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList; if (resolved.Length > 0) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", args.Name, args.IP, resolved.Length, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); //client.AdminKickFromLobby(args.Name, // "Connection using proxy or VPN is not allowed! (You can ask for exception). See http://dnsbl.tornevall.org/removal.php to get your IP removed from the blacklist."); } } catch (System.Net.Sockets.SocketException sockEx) { // not in database, do nothing } } using (var db = new ZkDataContext()) { Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490); bool isAnteepSmurf = accAnteep.AccountIPS.Any(x => x.IP == args.IP); if (isAnteepSmurf) { client.Say(TasClient.SayPlace.Channel, ModeratorChannel, String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", args.Name, args.IP, acc != null ? "http://zero-k.info/Users/Detail/" + acc.AccountID : ""), false); } } using (ZkDataContext db = new ZkDataContext()) { for (int i = 0; i <= 1; i++) { var whois = new Whois(); var data = whois.QueryByIp(args.IP, i == 1); if (!data.ContainsKey("netname")) { data["netname"] = "UNKNOWN NETNAME"; } if (!data.ContainsKey("org-name")) { data["org-name"] = "UNKNOWN ORG"; } if (!data.ContainsKey("abuse-mailbox")) { data["abuse-mailbox"] = "no mailbox"; } if (!data.ContainsKey("notify")) { data["notify"] = "no notify address"; } if (!data.ContainsKey("role")) { data["role"] = "UNKNOWN ROLE"; } if (!data.ContainsKey("descr")) { data["descr"] = "no description"; } if (!data.ContainsKey("remarks")) { data["remarks"] = "no remarks"; } var blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList(); var blockedHosts = db.BlockedHosts.Select(x => x.HostName).ToList(); /*if (acc.Country == "MY") * { * client.Say(TasClient.SayPlace.User, "KingRaptor", String.Format("USER {0}\nnetname: {1}\norgname: {2}\ndescr: {3}\nabuse-mailbox: {4}", * acc.Name, data["netname"], data["org-name"], data["descr"], data["abuse-mailbox"]), false); * }*/ if (blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) || (blockedHosts.Any(x => data["notify"].Contains(x)))) { client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)"); } foreach (string company in blockedCompanies) { if (data["netname"].ToLower().Contains(company) || data["org-name"].ToLower().Contains(company) || data["descr"].ToLower().Contains(company) || data["role"].ToLower().Contains(company) || data["remarks"].ToLower().Contains(company)) { client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)"); break; } } var hostname = Dns.GetHostEntry(args.IP).HostName; if (blockedHosts.Any(hostname.Contains)) { client.AdminKickFromLobby(args.Name, "Connection using proxy or VPN is not allowed! (You can ask for exception)"); } } } } } catch (System.Net.Sockets.SocketException sockEx) { // do nothing } catch (Exception ex) { Trace.TraceError("VPN check error: {0}", ex); client.Say(TasClient.SayPlace.Channel, ModeratorChannel, ex.ToString(), false); } } catch (Exception ex) { Trace.TraceError("Error getting user IP: {0}", ex); //client.Say(TasClient.SayPlace.User, "KingRaptor", ex.ToString(), false); } }); }; this.client.UserStatusChanged += (s, e) => { var user = client.ExistingUsers[e.ServerParams[0]]; Task.Factory.StartNew(() => { try { using (var db = new ZkDataContext()) UpdateUser(user.LobbyID, user.Name, user, null, db); } catch (Exception ex) { Trace.TraceError(ex.ToString()); } }, TaskCreationOptions.LongRunning); }; this.client.BattleUserJoined += (s, e) => { var battle = client.ExistingBattles[e.BattleID]; var founder = battle.Founder; if (founder.IsSpringieManaged) { try { var user = client.ExistingUsers[e.UserName]; /* obsolete; all major lobbies have multiengine support * if (!user.IsZkLobbyUser && !user.IsNotaLobby && battle.EngineVersion != client.ServerSpringVersion && * battle.EngineVersion != client.ServerSpringVersion + ".0") { * client.Say(TasClient.SayPlace.User, * user.Name, * string.Format( * "ALERT! YOU WILL DESYNC!! You NEED SPRING ENGINE {0} to play here. Simply join the game with Zero-K lobby ( http://zero-k.info/Wiki/Download ) OR get the engine from http://springrts.com/dl/buildbot/default/ OR build it on your Linux: http://springrts.com/wiki/Building_Spring_on_Linux ", * battle.EngineVersion), * false); * } */ using (var db = new ZkDataContext()) { var acc = Account.AccountByLobbyID(db, user.LobbyID); var name = founder.Name.TrimNumbers(); var aconf = db.AutohostConfigs.FirstOrDefault(x => x.Login == name); if (acc != null && user != null && aconf != null && (acc.LastLobbyVersionCheck == null || DateTime.UtcNow.Subtract(acc.LastLobbyVersionCheck.Value).TotalDays > 3) && aconf.AutohostMode != 0) { client.RequestLobbyVersion(user.Name); } /* * if (acc != null) * { * int numIDs = acc.AccountUserIDS != null ? acc.AccountUserIDS.Count : 0; * if (numIDs == 0) client.Say(TasClient.SayPlace.User, "KingRaptor", string.Format("USER {0} joined battle {1}; has {2} userIDs; lobby version {3}", acc.Name, founder.Name, numIDs, acc.LobbyVersion), false); * } * else * client.Say(TasClient.SayPlace.User, "KingRaptor", string.Format("USER {0} joined battle {1}", e.UserName + " (NO ACCOUNT)", founder.Name), false); * * if (acc != null) * { * if (!acc.AccountUserIDS.Any()) * { * string reason = string.Format("Sorry you are using unsupported lobby ({0}), please upgrade or use Zero-K Lobby, Weblobby or SpringLobby", acc.LobbyVersion); * client.Say(TasClient.SayPlace.User, user.Name, reason, false); * client.Say(TasClient.SayPlace.User, founder.Name, string.Format("!kick {0} {1}", acc.LobbyVersion, reason), false); * } * }*/ } } catch (Exception ex) { //client.Say(TasClient.SayPlace.User, "KingRaptor", ex.ToString(), false); Trace.TraceError("Error procesisng battle user joined: {0}", ex); } } }; this.client.TestLoginDenied += (s, e) => { RequestInfo entry; if (requests.TryGetValue(client.MessageID, out entry)) { entry.WaitHandle.Set(); } requests.TryRemove(client.MessageID, out entry); }; this.client.UserLobbyVersionRecieved += (s, e) => { using (var db = new ZkDataContext()) { var acc = Account.AccountByName(db, e.Name); if (acc != null) { acc.LobbyVersion = e.LobbyVersion; acc.LastLobbyVersionCheck = DateTime.UtcNow; db.SubmitAndMergeChanges(); if (!acc.LobbyVersion.StartsWith("ZK")) { // FIXME abma broke this (LobbyVersion is now some huge-ass integer instead) //client.Say(TasClient.SayPlace.User, // e.Name, // string.Format( // "WARNING: You are connected using {0} which is not fully compatible with this host. Please use Zero-K lobby. Download it from http://zero-k.info NOTE: to play all Spring games with Zero-K lobby, untick \"Official games\" on its multiplayer tab. Thank you!", // e.LobbyVersion), // false); } } } }; this.client.BattleFound += (s, e) => { if (e.Data.Founder.IsZkLobbyUser && !e.Data.Founder.IsBot) { client.SetBotMode(e.Data.Founder.Name, true); } }; this.client.ChannelUserAdded += (sender, args) => { try { var channel = args.ServerParams[0]; var user = args.ServerParams[1]; if (channel == ModeratorChannel) { var u = client.ExistingUsers[user]; if (u.SpringieLevel <= 2 && !u.IsZeroKAdmin) { client.ForceLeaveChannel(user, ModeratorChannel); } } else if (channel == Top20Channel) { var u = client.ExistingUsers[user]; if (!topPlayers.IsTop20(u.LobbyID) && u.Name != client.UserName) { client.ForceLeaveChannel(user, Top20Channel); } } else { using (var db = new ZkDataContext()) { var fac = db.Factions.FirstOrDefault(x => x.Shortcut == channel); if (fac != null) { // faction channel var u = client.ExistingUsers[user]; var acc = Account.AccountByLobbyID(db, u.LobbyID); if (acc == null || acc.FactionID != fac.FactionID || acc.Level < GlobalConst.FactionChannelMinLevel) { client.ForceLeaveChannel(user, channel); } } } } } catch (Exception ex) { Trace.TraceError("Error procesisng channel user added: {0}", ex); } }; this.client.ChannelUserRemoved += (sender, args) => { try { var channel = args.ServerParams[0]; var user = args.ServerParams[1]; if (channel == ModeratorChannel) { var u = client.ExistingUsers[user]; if (u.SpringieLevel > 2 || u.IsZeroKAdmin) { client.ForceJoinChannel(user, ModeratorChannel); } } } catch (Exception ex) { Trace.TraceError("Error procesisng channel user added: {0}", ex); } }; }