using System;
using Ion.HabboHotel.Habbos;
using Ion.Net.Connections;
using Ion.Net.Messages;
using Ion.Specialized.Encoding;
namespace Ion.HabboHotel.Client
{
///
/// Represents a connected HABBO game client. Holds information about the connection and the logged in user.
///
public class GameClient
{
#region Fields
private readonly uint mID;
private IonTcpConnection mConnection;
private ClientMessageHandler mMessageHandler;
private Habbo mHabbo;
private bool mPonged;
#endregion
#region Properties
///
/// Gets the ID of this client as a 32 bit unsigned integer.
///
public uint ID
{
get { return mID; }
}
///
/// Gets the logged in status of this client as a boolean value.
///
public bool LoggedIn
{
get { return (mHabbo != null); }
}
public bool PingOK
{
get { return mPonged; }
set { mPonged = value; }
}
#endregion
#region Constructors
///
/// Constructs a GameClient instance for a given client ID.
///
/// The ID of this client.
public GameClient(uint clientID)
{
mID = clientID;
mConnection = IonEnvironment.GetTcpConnections().GetConnection(clientID);
mMessageHandler = new ClientMessageHandler(this);
}
#endregion
#region Methods
///
/// Returns the IonTcpConnection instance of this client's connection.
///
public IonTcpConnection GetConnection()
{
return mConnection;
}
///
/// Returns the ClientMessageHandler instance of this client.
///
public ClientMessageHandler GetMessageHandler()
{
return mMessageHandler;
}
///
/// Returns the Habbo instance holding the information of the Habbo this client is logged in to.
///
public Habbo GetHabbo()
{
return mHabbo;
}
///
/// Starts the connection for this client, prepares the message handler and sends HELLO to the client.
///
public void StartConnection()
{
if (mConnection != null)
{
// Ping OK!
mPonged = true;
// Register request handlers
mMessageHandler.RegisterGlobal();
mMessageHandler.RegisterPreLogin();
// Create data router and start waiting for data
IonTcpConnection.RouteReceivedDataCallback dataRouter = new IonTcpConnection.RouteReceivedDataCallback(HandleConnectionData);
mConnection.Start(dataRouter);
}
}
///
/// Stops the client, removes this user from room, updates last online values etc.
///
public void Stop()
{
// Leave room
// Update last online
mHabbo = null;
mConnection = null;
mMessageHandler.Destroy();
mMessageHandler = null;
}
///
/// Handles a given amount of data in a given byte array, by attempting to parse messages from the received data and process them in the message handler.
///
/// The byte array with the data to process.
/// The actual amount of bytes in the byte array to process.
public void HandleConnectionData(ref byte[] data)
{
// Gameclient protocol or policyrequest?
if (data[0] != 64)
{
IonEnvironment.GetLog().WriteInformation("Client " + mID + " sent non-gameclient message: " + IonEnvironment.GetDefaultTextEncoding().GetString(data));
string xmlPolicy =
"\r\n" +
"\r\n" +
"\r\n" +
"\r\n" +
"\x0";
IonEnvironment.GetLog().WriteInformation("Client " + mID + ": sending XML cross domain policy file: " + xmlPolicy);
mConnection.SendData(xmlPolicy);
mMessageHandler.GetResponse().Initialize(1); // "@A"
mMessageHandler.GetResponse().Append("Deltar");
mMessageHandler.SendResponse();
}
else
{
int pos = 0;
while (pos < data.Length)
{
try
{
// Total length of message (without this): 3 Base64 bytes
int messageLength = Base64Encoding.DecodeInt32(new byte[] { data[pos++], data[pos++], data[pos++] });
// ID of message: 2 Base64 bytes
uint messageID = Base64Encoding.DecodeUInt32(new byte[] { data[pos++], data[pos++] });
// Data of message: (messageLength - 2) bytes
byte[] Content = new byte[messageLength - 2];
for (int i = 0; i < Content.Length; i++)
{
Content[i] = data[pos++];
}
// Create message object
ClientMessage message = new ClientMessage(messageID, Content);
// Handle message object
mMessageHandler.HandleRequest(message);
}
catch (IndexOutOfRangeException) // Bad formatting!
{
IonEnvironment.GetHabboHotel().GetClients().StopClient(mID);
}
catch (Exception ex)
{
IonEnvironment.GetLog().WriteUnhandledExceptionError("GameClient.HandleConnectionData", ex);
}
}
}
}
public void Login(string sTicket)
{
try
{
// Try to login
mHabbo = IonEnvironment.GetHabboHotel().GetAuthenticator().Login(sTicket);
// Authenticator has forced unique login now
this.CompleteLogin();
}
catch (IncorrectLoginException exLogin)
{
SendClientError(exLogin.Message);
}
catch (ModerationBanException exBan)
{
SendBanMessage(exBan.Message);
}
}
private void CompleteLogin()
{
// Actually logged in?
if (mHabbo != null)
{
// Send user rights
mMessageHandler.GetResponse().Initialize(2); // "@B"
mMessageHandler.GetResponse().AppendString("fuse_login");
mMessageHandler.SendResponse();
// Login OK!
mMessageHandler.GetResponse().Initialize(3); // "@C"
mMessageHandler.SendResponse();
// Register handlers
mMessageHandler.UnRegisterPreLogin();
mMessageHandler.RegisterUser();
mMessageHandler.RegisterNavigator();
}
}
///
/// Tries to login this client on a Habbo account with a given username and password.
///
/// The username of the Habbo to attempt to login on.
/// The login password of the Habbo username. Case sensitive.
public void Login(string sUsername, string sPassword)
{
try
{
// Try to login
mHabbo = IonEnvironment.GetHabboHotel().GetAuthenticator().Login(sUsername, sPassword);
// Authenticator has forced unique login now
this.CompleteLogin();
}
catch (IncorrectLoginException exLogin)
{
SendClientError(exLogin.Message);
}
catch (ModerationBanException exBan)
{
SendBanMessage(exBan.Message);
}
}
///
/// Reports a given error string to the client. (message 33: @a)
///
/// The error to report.
public void SendClientError(string sError)
{
ServerMessage message = new ServerMessage(33); // "@a"
message.Append(sError);
GetConnection().SendMessage(message);
}
///
/// Sends the 'You are banned' message to the client. The message holds a given ban reason.
///
/// The text to display in the ban message.
public void SendBanMessage(string sText)
{
ServerMessage message = new ServerMessage(35); // "@c"
message.Append(sText);
GetConnection().SendMessage(message);
}
#endregion
}
}