2013-07-18 09:27:19 +02:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Net.Sockets ;
using System.Threading ;
using System.IO ;
using System.Net ;
namespace MinecraftClient
{
/// <summary>
/// The main client class, used to connect to a Minecraft server.
/// It allows message sending and text receiving.
/// </summary>
class McTcpClient
{
public static int AttemptsLeft = 0 ;
string host ;
int port ;
string username ;
string text ;
Thread t_updater ;
Thread t_sender ;
TcpClient client ;
MinecraftCom handler ;
/// <summary>
/// Starts the main chat client, wich will login to the server using the MinecraftCom class.
/// </summary>
/// <param name="username">The chosen username of a premium Minecraft Account</param>
/// <param name="sessionID">A valid sessionID obtained with MinecraftCom.GetLogin()</param>
/// <param name="server_port">The server IP (serveradress or serveradress:port)</param>
2014-01-09 23:28:41 +01:00
public McTcpClient ( string username , string uuid , string sessionID , string server_port , MinecraftCom handler )
2013-07-18 09:27:19 +02:00
{
2014-01-09 23:28:41 +01:00
StartClient ( username , uuid , sessionID , server_port , false , handler , "" ) ;
2013-07-18 09:27:19 +02:00
}
/// <summary>
/// Starts the main chat client in single command sending mode, wich will login to the server using the MinecraftCom class, send the command and close.
/// </summary>
/// <param name="username">The chosen username of a premium Minecraft Account</param>
/// <param name="sessionID">A valid sessionID obtained with MinecraftCom.GetLogin()</param>
/// <param name="server_port">The server IP (serveradress or serveradress:port)</param>
/// <param name="command">The text or command to send.</param>
2014-01-09 23:28:41 +01:00
public McTcpClient ( string username , string uuid , string sessionID , string server_port , MinecraftCom handler , string command )
2013-07-18 09:27:19 +02:00
{
2014-01-09 23:28:41 +01:00
StartClient ( username , uuid , sessionID , server_port , true , handler , command ) ;
2013-07-18 09:27:19 +02:00
}
/// <summary>
/// Starts the main chat client, wich will login to the server using the MinecraftCom class.
/// </summary>
/// <param name="user">The chosen username of a premium Minecraft Account</param>
/// <param name="sessionID">A valid sessionID obtained with MinecraftCom.GetLogin()</param>
/// <param name="server_port">The server IP (serveradress or serveradress:port)/param>
/// <param name="singlecommand">If set to true, the client will send a single command and then disconnect from the server</param>
/// <param name="command">The text or command to send. Will only be sent if singlecommand is set to true.</param>
2014-01-09 23:28:41 +01:00
private void StartClient ( string user , string uuid , string sessionID , string server_port , bool singlecommand , MinecraftCom handler , string command )
2013-07-18 09:27:19 +02:00
{
this . handler = handler ;
username = user ;
string [ ] sip = server_port . Split ( ':' ) ;
host = sip [ 0 ] ;
if ( sip . Length = = 1 )
{
port = 25565 ;
}
else
{
try
{
port = Convert . ToInt32 ( sip [ 1 ] ) ;
}
catch ( FormatException ) { port = 25565 ; }
}
try
{
2014-01-08 23:58:49 +01:00
Console . WriteLine ( "Logging in..." ) ;
2013-07-18 09:27:19 +02:00
client = new TcpClient ( host , port ) ;
client . ReceiveBufferSize = 1024 * 1024 ;
handler . setClient ( client ) ;
2014-01-09 23:28:41 +01:00
if ( handler . Login ( user , uuid , sessionID , host , port ) )
2013-07-18 09:27:19 +02:00
{
2014-01-08 23:58:49 +01:00
//Single command sending
if ( singlecommand )
2013-07-18 09:27:19 +02:00
{
2014-01-08 23:58:49 +01:00
handler . SendChatMessage ( command ) ;
Console . Write ( "Command " ) ;
Console . ForegroundColor = ConsoleColor . DarkGray ;
Console . Write ( command ) ;
Console . ForegroundColor = ConsoleColor . Gray ;
Console . WriteLine ( " sent." ) ;
Thread . Sleep ( 5000 ) ;
handler . Disconnect ( "disconnect.quitting" ) ;
Thread . Sleep ( 1000 ) ;
2013-07-18 09:27:19 +02:00
}
else
{
2014-03-11 08:14:58 -06:00
Console . WriteLine ( "Server was successfully joined.\nType '/quit' to leave the server." ) ;
2014-01-08 23:58:49 +01:00
//Command sending thread, allowing user input
t_sender = new Thread ( new ThreadStart ( StartTalk ) ) ;
t_sender . Name = "CommandSender" ;
t_sender . Start ( ) ;
//Data receiving thread, allowing text receiving
t_updater = new Thread ( new ThreadStart ( Updater ) ) ;
t_updater . Name = "PacketHandler" ;
t_updater . Start ( ) ;
2013-07-18 09:27:19 +02:00
}
}
else
{
2014-01-08 23:58:49 +01:00
Console . WriteLine ( "Login failed." ) ;
2013-07-18 09:27:19 +02:00
if ( ! singlecommand ) { Program . ReadLineReconnect ( ) ; }
}
}
catch ( SocketException )
{
Console . WriteLine ( "Failed to connect to this IP." ) ;
if ( AttemptsLeft > 0 )
{
ChatBot . LogToConsole ( "Waiting 5 seconds (" + AttemptsLeft + " attempts left)..." ) ;
Thread . Sleep ( 5000 ) ; AttemptsLeft - - ; Program . Restart ( ) ;
}
2013-07-20 11:01:49 +10:00
else if ( ! singlecommand ) { Console . ReadLine ( ) ; }
2013-07-18 09:27:19 +02:00
}
}
/// <summary>
/// Allows the user to send chat messages, commands, and to leave the server.
/// Will be automatically called on a separate Thread by StartClient()
/// </summary>
private void StartTalk ( )
{
try
{
2014-01-12 13:38:52 +01:00
//Needed if the player is dead
handler . SendRespawnPacket ( ) ;
2013-07-18 09:27:19 +02:00
while ( client . Client . Connected )
{
text = ConsoleIO . ReadLine ( ) ;
2013-08-18 18:26:20 +02:00
if ( ConsoleIO . basicIO & & text . Length > 0 & & text [ 0 ] = = ( char ) 0x00 )
2013-07-18 09:27:19 +02:00
{
2013-08-18 18:26:20 +02:00
//Process a request from the GUI
string [ ] command = text . Substring ( 1 ) . Split ( ( char ) 0x00 ) ;
switch ( command [ 0 ] . ToLower ( ) )
2013-07-18 09:27:19 +02:00
{
2013-08-18 18:26:20 +02:00
case "autocomplete" :
if ( command . Length > 1 ) { ConsoleIO . WriteLine ( ( char ) 0x00 + "autocomplete" + ( char ) 0x00 + handler . AutoComplete ( command [ 1 ] ) ) ; }
else Console . WriteLine ( ( char ) 0x00 + "autocomplete" + ( char ) 0x00 ) ;
break ;
}
}
else
{
2014-01-12 13:38:52 +01:00
text = text . Trim ( ) ;
if ( text . ToLower ( ) = = "/quit" | | text . ToLower ( ) = = "/reco" )
{
break ;
}
else if ( text . ToLower ( ) = = "/respawn" )
{
handler . SendRespawnPacket ( ) ;
ConsoleIO . WriteLine ( "You have respawned." ) ;
}
else if ( text . ToLower ( ) . StartsWith ( "/script " ) )
{
handler . BotLoad ( new Bots . Scripting ( text . Substring ( 8 ) ) ) ;
}
else if ( text ! = "" )
2013-08-18 18:26:20 +02:00
{
//Message is too long
if ( text . Length > 100 )
2013-07-18 09:27:19 +02:00
{
2013-08-18 18:26:20 +02:00
if ( text [ 0 ] = = '/' )
{
//Send the first 100 chars of the command
text = text . Substring ( 0 , 100 ) ;
handler . SendChatMessage ( text ) ;
}
else
2013-07-18 09:27:19 +02:00
{
2014-01-12 13:38:52 +01:00
//Send the message splitted in several messages
2013-08-18 18:26:20 +02:00
while ( text . Length > 100 )
{
handler . SendChatMessage ( text . Substring ( 0 , 100 ) ) ;
text = text . Substring ( 100 , text . Length - 100 ) ;
}
handler . SendChatMessage ( text ) ;
2013-07-18 09:27:19 +02:00
}
}
2013-08-18 18:26:20 +02:00
else handler . SendChatMessage ( text ) ;
2013-07-18 09:27:19 +02:00
}
}
}
2014-01-12 13:38:52 +01:00
switch ( text . ToLower ( ) )
2013-07-18 09:27:19 +02:00
{
2014-01-12 13:38:52 +01:00
case "/quit" : Program . Exit ( ) ; break ;
case "/reco" : Program . Restart ( ) ; break ;
2013-07-18 09:27:19 +02:00
}
}
catch ( IOException ) { }
}
/// <summary>
/// Receive the data (including chat messages) from the server, and keep the connection alive.
/// Will be automatically called on a separate Thread by StartClient()
/// </summary>
private void Updater ( )
{
try
{
//handler.DebugDump();
do
{
Thread . Sleep ( 100 ) ;
} while ( handler . Update ( ) ) ;
}
catch ( IOException ) { }
catch ( SocketException ) { }
catch ( ObjectDisposedException ) { }
if ( ! handler . HasBeenKicked )
{
ConsoleIO . WriteLine ( "Connection has been lost." ) ;
if ( ! handler . OnConnectionLost ( ) & & ! Program . ReadLineReconnect ( ) ) { t_sender . Abort ( ) ; }
}
else if ( Program . ReadLineReconnect ( ) ) { t_sender . Abort ( ) ; }
}
/// <summary>
/// Disconnect the client from the server
/// </summary>
public void Disconnect ( )
{
handler . Disconnect ( "disconnect.quitting" ) ;
Thread . Sleep ( 1000 ) ;
if ( t_updater ! = null ) { t_updater . Abort ( ) ; }
if ( t_sender ! = null ) { t_sender . Abort ( ) ; }
if ( client ! = null ) { client . Close ( ) ; }
}
}
}