static void CheckPaidStatusCallback([NotNull] SchedulerTask task) { PlayerInfo info = (PlayerInfo)task.UserState; if (info == null) { throw new NullReferenceException("task.UserState"); } info.AccountType = Player.CheckPaidStatus(info.Name); }
static void CheckPaidStatusCallback(SchedulerTask task) { PlayerInfo info = (PlayerInfo)task.UserState; info.AccountType = Player.CheckPaidStatus(info.Name); }
bool LoginSequence() { byte opcode = reader.ReadByte(); if( opcode != (byte)OpCode.Handshake ) { if( opcode == 2 ) { // This may be someone connecting with an SMP client int strLen = IPAddress.NetworkToHostOrder( reader.ReadInt16() ); if( strLen >= 2 && strLen <= 16 ) { string smpPlayerName = Encoding.UTF8.GetString( reader.ReadBytes( strLen ) ); Logger.Log( "Session.LoginSequence: Player \"{0}\" tried connecting with SMP/Beta client from {1}. " + "fCraft does not support SMP/Beta.", LogType.Warning, smpPlayerName, IP ); // send SMP KICK packet writer.Write( (byte)255 ); byte[] stringData = Encoding.UTF8.GetBytes( NoSmpMessage ); writer.Write( (short)stringData.Length ); writer.Write( stringData ); bytesSent += (1 + stringData.Length); writer.Flush(); } else { // Not SMP client (invalid player name length) Logger.Log( "Session.LoginSequence: Unexpected opcode in the first packet from {0}: {1}.", LogType.Error, IP, opcode ); KickNow( "Unexpected handshake message - possible protocol mismatch!", LeaveReason.ProtocolViolation ); } return false; } else { Logger.Log( "Session.LoginSequence: Unexpected opcode in the first packet from {0}: {1}.", LogType.Error, IP, opcode ); KickNow( "Unexpected handshake message - possible protocol mismatch!", LeaveReason.ProtocolViolation ); return false; } } // Check protocol version int clientProtocolVersion = reader.ReadByte(); if( clientProtocolVersion != Config.ProtocolVersion ) { Logger.Log( "Session.LoginSequence: Wrong protocol version: {0}.", LogType.Error, clientProtocolVersion ); KickNow( "Incompatible protocol version!", LeaveReason.ProtocolViolation ); return false; } string playerName = ReadString(); string verificationCode = ReadString(); reader.ReadByte(); // unused bytesReceived += 131; // Check name for nonstandard characters if( !Player.IsValidName( playerName ) ) { Logger.Log( "Session.LoginSequence: Unacceptible player name: {0} ({1})", LogType.SuspiciousActivity, playerName, IP ); KickNow( "Invalid characters in player name!", LeaveReason.ProtocolViolation ); return false; } // Verify name Player = new Player( null, playerName, this, WorldManager.MainWorld.Map.Spawn ); bool showVerifyNamesWarning = false; if( !Server.VerifyName( Player.Name, verificationCode, Server.Salt ) ) { NameVerificationMode nameVerificationMode = ConfigKey.VerifyNames.GetEnum<NameVerificationMode>(); string standardMessage = String.Format( "Session.LoginSequence: Could not verify player name for {0} ({1}).", Player.Name, IP ); if( IP.Equals( IPAddress.Loopback ) && nameVerificationMode == NameVerificationMode.Always ) { Logger.Log( "{0} Player was identified as connecting from localhost and allowed in.", LogType.SuspiciousActivity, standardMessage ); } else if( IP.IsLAN() && ConfigKey.AllowUnverifiedLAN.GetBool() ) { Logger.Log( "{0} Player was identified as connecting from LAN and allowed in.", LogType.SuspiciousActivity, standardMessage ); } else if( Player.Info.TimesVisited > 1 && Player.Info.LastIP.Equals( IP ) ) { switch( nameVerificationMode ) { case NameVerificationMode.Always: Player.Info.ProcessFailedLogin( this ); Logger.Log( "{0} IP matched previous records for that name. " + "Player was kicked anyway because VerifyNames is set to Always.", LogType.SuspiciousActivity, standardMessage ); KickNow( "Could not verify player name!", LeaveReason.UnverifiedName ); return false; case NameVerificationMode.Balanced: case NameVerificationMode.Never: Logger.Log( "{0} IP matched previous records for that name. Player was allowed in.", LogType.SuspiciousActivity, standardMessage ); break; } } else { switch( nameVerificationMode ) { case NameVerificationMode.Always: case NameVerificationMode.Balanced: Player.Info.ProcessFailedLogin( this ); Logger.Log( "{0} IP did not match. Player was kicked.", LogType.SuspiciousActivity, standardMessage ); KickNow( "Could not verify player name!", LeaveReason.UnverifiedName ); return false; case NameVerificationMode.Never: Logger.Log( "{0} IP did not match. " + "Player was allowed in anyway because VerifyNames is set to Never.", LogType.SuspiciousActivity, standardMessage ); Player.Message( "&WYour name could not be verified." ); showVerifyNamesWarning = true; break; } } } // Check if player is banned if( Player.Info.Banned ) { Player.Info.ProcessFailedLogin( this ); Logger.Log( "Banned player {0} tried to log in from {1}", LogType.SuspiciousActivity, Player.Name, IP ); if( ConfigKey.ShowBannedConnectionMessages.GetBool() ) { Server.SendToAllWhoCan( "&SBanned player {0}&S tried to log in from {1}", null, Permission.ViewPlayerIPs, Player.GetClassyName(), IP ); Server.SendToAllWhoCant( "&SBanned player {0}&S tried to log in.", null, Permission.ViewPlayerIPs, Player.GetClassyName() ); } string bannedMessage = String.Format( "Banned {0} ago by {1}: {2}", Player.Info.TimeSinceBan.ToMiniString(), Player.Info.BannedBy, Player.Info.BanReason ); KickNow( bannedMessage, LeaveReason.LoginFailed ); return false; } // Check if player's IP is banned IPBanInfo ipBanInfo = IPBanList.Get( IP ); if( ipBanInfo != null ) { Player.Info.ProcessFailedLogin( this ); ipBanInfo.ProcessAttempt( Player ); if( ConfigKey.ShowBannedConnectionMessages.GetBool() ) { Server.SendToAll( "{0}&S tried to log in from a banned IP.", Player.GetClassyName() ); } Logger.Log( "{0} tried to log in from a banned IP.", LogType.SuspiciousActivity, Player.Name ); string bannedMessage = String.Format( "IP-banned {0} ago by {1}: {2}", DateTime.UtcNow.Subtract( ipBanInfo.BanDate ).ToMiniString(), ipBanInfo.BannedBy, ipBanInfo.BanReason ); KickNow( bannedMessage, LeaveReason.LoginFailed ); return false; } // Check if max number of connections is reached for IP if( !Server.RegisterSessionAndCheckConnectionCount( this ) ) { Player.Info.ProcessFailedLogin( this ); Logger.Log( "Session.LoginSequence: Denied player {0}: maximum number of connections was reached for {1}", LogType.SuspiciousActivity, playerName, IP ); KickNow( String.Format( "Max connection count reached for {0}", IP ), LeaveReason.LoginFailed ); return false; } // Check if player is paid (if required) if( ConfigKey.PaidPlayersOnly.GetBool() ) { SendNow( PacketWriter.MakeHandshake( Player, ConfigKey.ServerName.GetString(), "Please wait; Checking paid status..." ) ); writer.Flush(); if( !Player.CheckPaidStatus( Player.Name ) ) { Logger.Log( "Player {0} was kicked because their account is not paid, and PaidOnly setting is enabled.", LogType.SystemActivity, Player.Name ); KickNow( "Paid players allowed only.", LeaveReason.LoginFailed ); return false; } } // Any additional security checks should be done right here if( Server.RaisePlayerConnectingEvent( Player ) ) return false; // ----==== beyond this point, player is considered connecting (allowed to join) ====---- // Register player for future block updates if( !Server.RegisterPlayerAndCheckIfFull( this ) ) { Logger.Log( "Player {0} was kicked because server is full.", LogType.SystemActivity, Player.Name ); string kickMessage = String.Format( "Sorry, server is full ({0}/{1})", Server.PlayerList.Length, ConfigKey.MaxPlayers.GetInt() ); KickNow( kickMessage, LeaveReason.ServerFull ); return false; } Player.Info.ProcessLogin( Player ); // ----==== Beyond this point, player is considered connected (authenticated and registered) ====---- World startingWorld = Server.RaisePlayerConnectedEvent( Player, WorldManager.MainWorld ); // Send server information SendNow( PacketWriter.MakeHandshake( Player, ConfigKey.ServerName.GetString(), ConfigKey.MOTD.GetString() ) ); // AutoRank if( ConfigKey.AutoRankEnabled.GetBool() ) { Rank newRank = AutoRankManager.Check( Player.Info ); if( newRank != null ) { ModerationCommands.DoChangeRank( Player.Console, Player.Info, newRank, "~AutoRank", false, true ); } } bool firstTime = (Player.Info.TimesVisited == 1); if( !JoinWorldNow( startingWorld, true, true ) ) { Logger.Log( "Failed to load main world ({0}) for connecting player {1} (from {2})", LogType.Error, startingWorld.Name, Player.Name, IP ); KickNow( "Unable to join the main world.", LeaveReason.WorldFull ); return false; } // ==== Beyond this point, player is considered ready (has a world) ==== if( showVerifyNamesWarning ) { Server.SendToAllExcept( "&WName and IP of {0}&W are unverified!", Player, Player.GetClassyName() ); } // Check if other banned players logged in from this IP PlayerInfo[] bannedPlayerNames = PlayerDB.FindPlayers( IP, 25 ).Where( playerFromSameIP => playerFromSameIP.Banned ).ToArray(); if( bannedPlayerNames.Length > 0 ) { string logString = String.Format( "&WPlayer {0}&W logged in from an IP previously used by banned players: {1}", Player.GetClassyName(), bannedPlayerNames.JoinToClassyString() ); Server.SendToAll( logString ); Logger.Log( logString, LogType.SuspiciousActivity ); } // Announce join if( ConfigKey.ShowConnectionMessages.GetBool() ) { Server.SendToAllExcept( Server.MakePlayerConnectedMessage( Player, firstTime, Player.World ), Player ); } // check if player is still muted if( Player.Info.MutedUntil > DateTime.UtcNow ) { int secondsLeft = (int)Player.Info.MutedUntil.Subtract( DateTime.UtcNow ).TotalSeconds; Player.Message( "&WYou were previously muted by {0}, {1} seconds left.", Player.Info.MutedBy, secondsLeft ); Server.SendToAllExcept( "&WPlayer {0}&W was previously muted by {1}&W, {2} seconds left.", Player, Player.GetClassyName(), Player.Info.MutedBy, secondsLeft ); } // check if player is still frozen if( Player.Info.IsFrozen ) { if( Player.Info.FrozenOn != DateTime.MinValue ) { Player.Message( "&WYou were previously frozen {0} ago by {1}", Player.Info.TimeSinceFrozen.ToMiniString(), Player.Info.FrozenBy ); Server.SendToAllExcept( "&WPlayer {0}&W was previously frozen {1} ago by {2}.", Player, Player.GetClassyName(), Player.Info.TimeSinceFrozen.ToMiniString(), Player.Info.FrozenBy ); } else { Player.Message( "&WYou were previously frozen by {0}", Player.Info.FrozenBy ); Server.SendToAllExcept( "&WPlayer {0}&W was previously frozen by {1}.", Player, Player.GetClassyName(), Player.Info.FrozenBy ); } } // Welcome message if( File.Exists( Paths.GreetingFileName ) ) { string[] greetingText = File.ReadAllLines( Paths.GreetingFileName ); foreach( string greetingLine in greetingText ) { StringBuilder sb = new StringBuilder( greetingLine ); sb.Replace( "{SERVER_NAME}", ConfigKey.ServerName.GetString() ); sb.Replace( "{RANK}", Player.Info.Rank.GetClassyName() ); sb.Replace( "{PLAYER_NAME}", Player.GetClassyName() ); sb.Replace( "{TIME}", DateTime.Now.ToShortTimeString() ); // localized sb.Replace( "{WORLD}", Player.World.GetClassyName() ); sb.Replace( "{PLAYERS}", Server.CountVisiblePlayers( Player ).ToString() ); sb.Replace( "{WORLDS}", WorldManager.WorldList.Length.ToString() ); sb.Replace( "{MOTD}", ConfigKey.MOTD.GetString() ); Player.Message( sb.ToString() ); } } else { if( firstTime ) { Player.Message( "Welcome to {0}", ConfigKey.ServerName.GetString() ); } else { Player.Message( "Welcome back to {0}", ConfigKey.ServerName.GetString() ); } Player.Message( "Your rank is {0}&S. Type &H/help&S for help.", Player.Info.Rank.GetClassyName() ); } // A reminder for first-time users if( PlayerDB.CountTotalPlayers() == 1 && Player.Info.Rank != RankManager.HighestRank ) { Player.Message( "Type &H/rank {0} {1}&S in console to promote yourself", Player.Name, RankManager.HighestRank.Name ); } Server.RaisePlayerReadyEvent( Player ); IsReady = true; return true; }