/// <summary> /// Handles the zone login request packet /// </summary> static public void Handle_CS_PlayerLogin(CS_PlayerLogin <Zone> pkt, Zone zone) { //Make a note Log.write(TLog.Inane, "Player login request for '{0}' on '{1}'", pkt.alias, zone); SC_PlayerLogin <Zone> plog = new SC_PlayerLogin <Zone>(); plog.player = pkt.player; if (String.IsNullOrWhiteSpace(pkt.alias)) { plog.bSuccess = false; plog.loginMessage = "Please enter an alias."; zone._client.send(plog); return; } //Are they using the launcher? if (String.IsNullOrWhiteSpace(pkt.ticketid)) { //They're trying to trick us, jim! plog.bSuccess = false; plog.loginMessage = "Please use the Infantry launcher to run the game."; zone._client.send(plog); return; } if (pkt.ticketid.Contains(':')) { //They're using the old, outdated launcher plog.bSuccess = false; plog.loginMessage = "Please use the updated launcher from the website."; zone._client.send(plog); return; } using (InfantryDataContext db = zone._server.getContext()) { Data.DB.player player = null; Data.DB.account account = db.accounts.SingleOrDefault(acct => acct.ticket.Equals(pkt.ticketid)); if (account == null) { //They're trying to trick us, jim! plog.bSuccess = false; plog.loginMessage = "Your session id has expired. Please re-login."; zone._client.send(plog); return; } //Is there already a player online under this account? if (!DBServer.bAllowMulticlienting && zone._server._zones.Any(z => z.hasAccountPlayer(account.id))) { plog.bSuccess = false; plog.loginMessage = "Account is currently in use."; zone._client.send(plog); return; } //Check for IP and UID bans Logic_Bans.Ban banned = Logic_Bans.checkBan(pkt, db, account, zone._zone.id); if (banned.type == Logic_Bans.Ban.BanType.GlobalBan) { //We don't respond to globally banned player requests plog.bSuccess = false; plog.loginMessage = "Banned."; Log.write(TLog.Warning, "Failed login: "******" Alias: " + pkt.alias + " Reason: " + banned.type.ToString()); zone._client.send(plog); return; } if (banned.type == Logic_Bans.Ban.BanType.IPBan) { //Their IP has been banned, make something up! plog.bSuccess = false; plog.loginMessage = "You have been temporarily suspended until " + banned.expiration.ToString("f", CultureInfo.CreateSpecificCulture("en-US")); Log.write(TLog.Warning, "Failed login: "******" Alias: " + pkt.alias + " Reason: " + banned.type.ToString()); zone._client.send(plog); return; } if (banned.type == Logic.Logic_Bans.Ban.BanType.ZoneBan) { //They've been blocked from entering the zone, tell them how long they've got left on their ban plog.bSuccess = false; plog.loginMessage = "You have been temporarily suspended from this zone until " + banned.expiration.ToString("f", CultureInfo.CreateSpecificCulture("en-US")); Log.write(TLog.Warning, "Failed login: "******" Alias: " + pkt.alias + " Reason: " + banned.type.ToString()); zone._client.send(plog); return; } if (banned.type == Logic.Logic_Bans.Ban.BanType.AccountBan) { //They've been blocked from entering any zone, tell them when to come back plog.bSuccess = false; plog.loginMessage = "Your account has been temporarily suspended until " + banned.expiration.ToString("f", CultureInfo.CreateSpecificCulture("en-US")); Log.write(TLog.Warning, "Failed login: "******" Alias: " + pkt.alias + " Reason: " + banned.type.ToString()); zone._client.send(plog); return; } //They made it! //We have the account associated! plog.permission = (PlayerPermission)account.permission; if (account.permission > (int)PlayerPermission.Sysop) { plog.permission = PlayerPermission.Sysop; } //Attempt to find the related alias Data.DB.alias alias = db.alias.SingleOrDefault(a => a.name.Equals(pkt.alias)); Data.DB.stats stats = null; //Is there already a player online under this alias? if (alias != null && zone._server._zones.Any(z => z.hasAliasPlayer(alias.id))) { plog.bSuccess = false; plog.loginMessage = "Alias is currently in use."; zone._client.send(plog); return; } if (alias == null && !pkt.bCreateAlias) { //Prompt him to create a new alias if he has room int maxAliases = 30; if (account.alias.Count < maxAliases) { //He has space! Prompt him to make a new alias plog.bSuccess = false; plog.bNewAlias = true; zone._client.send(plog); return; } else { plog.bSuccess = false; plog.loginMessage = "Your account has reached the maximum number of " + maxAliases.ToString() + " aliases allowed."; zone._client.send(plog); return; } } else if (alias == null && pkt.bCreateAlias) { //We want to create a new alias! alias = new InfServer.Data.DB.alias(); alias.name = pkt.alias; alias.creation = DateTime.Now; alias.account1 = account; alias.IPAddress = pkt.ipaddress; alias.lastAccess = DateTime.Now; alias.timeplayed = 0; db.alias.InsertOnSubmit(alias); Log.write(TLog.Normal, "Creating new alias '{0}' on account '{1}'", pkt.alias, account.name); } else if (alias != null) { //We can't recreate an existing alias or login to one that isn't ours.. if (pkt.bCreateAlias || alias.account1 != account) { plog.bSuccess = false; plog.loginMessage = "The specified alias already exists."; zone._client.send(plog); return; } } //Do we have a player row for this zone? player = db.players.SingleOrDefault( plyr => plyr.alias1 == alias && plyr.zone1 == zone._zone); if (player == null) { //We need to create another! player = new InfServer.Data.DB.player(); player.squad1 = null; player.zone = zone._zone.id; player.alias1 = alias; player.lastAccess = DateTime.Now; player.permission = 0; //Create a blank stats row stats = new InfServer.Data.DB.stats(); stats.zone = zone._zone.id; player.stats1 = stats; db.stats.InsertOnSubmit(stats); db.players.InsertOnSubmit(player); //It's a first-time login, so no need to load stats plog.bFirstTimeSetup = true; } else { //Load the player details and stats! plog.banner = player.banner; plog.permission = (PlayerPermission)Math.Max(player.permission, (int)plog.permission); if (player.permission > account.permission) { //He's a dev here, set the bool plog.developer = true; } //Check for admin Data.DB.alias aliasMatch = null; foreach (string str in Logic_Admins.ServerAdmins) { if ((aliasMatch = db.alias.SingleOrDefault(a => string.Compare(a.name, str, true) == 0)) != null) { if (account.id == aliasMatch.account && account.permission >= 5) { plog.admin = true; break; } } } //If he isn't part of the admin list, he doesn't get powers if (!plog.admin && account.permission >= 5) { account.permission = 0; } plog.squad = (player.squad1 == null) ? "" : player.squad1.name; if (player.squad1 != null) { plog.squadID = player.squad1.id; } stats = player.stats1; plog.stats.zonestat1 = stats.zonestat1; plog.stats.zonestat2 = stats.zonestat2; plog.stats.zonestat3 = stats.zonestat3; plog.stats.zonestat4 = stats.zonestat4; plog.stats.zonestat5 = stats.zonestat5; plog.stats.zonestat6 = stats.zonestat6; plog.stats.zonestat7 = stats.zonestat7; plog.stats.zonestat8 = stats.zonestat8; plog.stats.zonestat9 = stats.zonestat9; plog.stats.zonestat10 = stats.zonestat10; plog.stats.zonestat11 = stats.zonestat11; plog.stats.zonestat12 = stats.zonestat12; plog.stats.kills = stats.kills; plog.stats.deaths = stats.deaths; plog.stats.killPoints = stats.killPoints; plog.stats.deathPoints = stats.deathPoints; plog.stats.assistPoints = stats.assistPoints; plog.stats.bonusPoints = stats.bonusPoints; plog.stats.vehicleKills = stats.vehicleKills; plog.stats.vehicleDeaths = stats.vehicleDeaths; plog.stats.playSeconds = stats.playSeconds; plog.stats.cash = stats.cash; plog.stats.inventory = new List <PlayerStats.InventoryStat>(); plog.stats.experience = stats.experience; plog.stats.experienceTotal = stats.experienceTotal; plog.stats.skills = new List <PlayerStats.SkillStat>(); //Convert the binary inventory/skill data if (player.inventory != null) { DBHelpers.binToInventory(plog.stats.inventory, player.inventory); } if (player.skills != null) { DBHelpers.binToSkills(plog.stats.skills, player.skills); } } //Rename him plog.alias = alias.name; //Try and submit any new rows before we try and use them try { db.SubmitChanges(); } catch (Exception e) { plog.bSuccess = false; plog.loginMessage = "Unable to create new player / alias, please try again."; Log.write(TLog.Exception, "Exception adding player or alias to DB: {0}", e); zone._client.send(plog); return; } //Add them if (zone.newPlayer(pkt.player.id, alias.name, player)) { plog.bSuccess = true; Log.write("Player '{0}' logged into zone '{1}'", alias.name, zone._zone.name); //Modify his alias IP address and access times alias.IPAddress = pkt.ipaddress.Trim(); alias.lastAccess = DateTime.Now; //Change it db.SubmitChanges(); } else { plog.bSuccess = false; plog.loginMessage = "Unknown login failure."; Log.write("Failed adding player '{0}' from '{1}'", alias.name, zone._zone.name); } //Give them an answer zone._client.sendReliable(plog); } }
/// <summary> /// Handles the login request packet sent by the client /// </summary> static public void Handle_CS_Login(CS_Login pkt, Client <Player> client) { //Let's escalate our client's status to player! ZoneServer server = (client._handler as ZoneServer); // check for excessive joins to zone from same IP if (pkt.bCreateAlias != true && server._connections.ContainsKey(client._ipe.Address)) { Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Please wait 10 seconds before logging in again."); Log.write(TLog.Warning, "Possible throttler removed: {0}", client._ipe.ToString()); return; } else if (!server._connections.ContainsKey(client._ipe.Address)) { server._connections.Add(client._ipe.Address, DateTime.Now.AddSeconds(10)); } //Check their client version and UIDs //TODO: find out what the UIDs are and what an invalid UID might look like, and reject spoofed ones if (pkt.Version != Helpers._serverVersion || pkt.UID1 <= 10000 || pkt.UID2 <= 10000 || pkt.UID3 <= 10000) { Log.write(TLog.Warning, "Suspicious login packet from {0} : Version ({1}) UID1({2}) UID2({3}) UID3({4})", pkt.Username, pkt.Version, pkt.UID1, pkt.UID2, pkt.UID3); } String alias = pkt.Username; //Check alias for illegal characters if (String.IsNullOrWhiteSpace(alias)) { Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Alias cannot be blank."); return; } try { //Temporary till we find the login bug if (!char.IsLetterOrDigit(alias, 0) || char.IsWhiteSpace(alias, 0) || char.IsWhiteSpace(alias, alias.Length - 1) || alias != Logic_Text.RemoveIllegalCharacters(alias)) { //Boot him.. Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Alias contains illegal characters, must start with a letter or number and cannot end with a space."); return; } } catch (ArgumentOutOfRangeException) { Log.write(TLog.Warning, "Player login name is {0}", alias); Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Alias contains illegal characters, must start with a letter or number and cannot end with a space."); return; } if (alias.Length > 64) { //Change this if alias.name in the db is changed.. currently at varchar(64) Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Alias length is too long."); return; } //Are we in permission mode? if (server._config["server/permitMode"].boolValue && !Logic_Permit.checkPermit(alias)) { Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Zone is in permission only mode."); return; } if (server._clients.Values.Count(x => x._ipe.Address.ToString() == client._ipe.Address.ToString()) > 3) { Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Too many connections from same IP."); Log.write(TLog.Error, "Too many concurrent connections from IP Address {0}", client._ipe.Address); return; } Player newPlayer = server.newPlayer(client, alias); //If it failed for some reason, present a failure message if (newPlayer == null) { Helpers.Login_Response(client, SC_Login.Login_Result.Failed, "Login Failure, Zone is full."); Log.write(TLog.Error, "New player is null possibly due to zone being full."); return; } newPlayer._UID1 = pkt.UID1; newPlayer._UID2 = pkt.UID2; newPlayer._UID3 = pkt.UID3; //Are we in standalone mode? if (server.IsStandalone) { //Always first time setup in standalone mode newPlayer.assignFirstTimeStats(false); //Success! Let him in. Helpers.Login_Response(client, SC_Login.Login_Result.Success, "This server is currently in stand-alone mode. Your character's scores and stats will not be saved."); } else { //Defer the request to the database server CS_PlayerLogin <Data.Database> plogin = new CS_PlayerLogin <Data.Database>(); plogin.bCreateAlias = pkt.bCreateAlias; plogin.player = newPlayer.toInstance(); plogin.alias = alias; plogin.ticketid = pkt.TicketID; plogin.UID1 = pkt.UID1; plogin.UID2 = pkt.UID2; plogin.UID3 = pkt.UID3; plogin.NICInfo = pkt.NICInfo; plogin.ipaddress = pkt._client._ipe.Address.ToString().Trim(); server._db.send(plogin); } }