using System;
using System.Net.Sockets;
using System.Collections.Generic;
using Woodpecker.Core;
using Woodpecker.Net.Game;
using Woodpecker.Net.Game.Messages;
using Woodpecker.Game.Users;
using Woodpecker.Game.Items;
using Woodpecker.Game.Rooms;
using Woodpecker.Game.Rooms.Instances;
using Woodpecker.Game.Rooms.Instances.Interaction;
namespace Woodpecker.Sessions
{
///
/// A global class for a user session, containing connections to the server for game client and MUS.
///
public class Session
{
#region Fields
///
/// The session ID (connection ID) of this session. Datatype is unsigned 32 bits integer.
///
public uint ID;
///
/// The DateTime object containing the date and time of this session's start.
///
private DateTime Started;
///
/// The gameConnection object, representing the gameclient connection to the server.
///
public gameConnection gameConnection;
///
/// True if this session can still process packets etc.
///
public bool isValid = true;
///
/// The userInformation object containing data about this session user. (after login)
///
public userInformation User;
public userAccessInformation Access = new userAccessInformation();
///
/// True if this session is currently holding a user. (so 'is logged in')
///
public bool isHoldingUser
{
get { return this.User != null; }
}
///
/// Gets the IP address of this session user from the gameConnection object.
///
public string ipAddress
{
get
{
if (this.gameConnection != null)
return this.gameConnection.ipAddress;
else
return "";
}
}
///
/// True if pong ('CD') has been received.
///
public bool pongReceived;
///
/// True if this connection is ready to send packets to.
///
public bool isReady
{
get { return (this.gameConnection != null); }
}
#region Room related
///
/// The database ID of the room the user currently is in.
///
public int roomID;
///
/// True if this user is currently an active user in a room.
///
public bool inRoom
{
get { return this.roomID > 0 && this.roomInstance != null; }
}
///
/// The Woodpecker.Game.Rooms.Instances.Room room instance of the room the user is currently entering/is active in.
///
public roomInstance roomInstance;
///
/// The database ID of the room the user has authenticated for.
///
public int authenticatedFlat;
///
/// The database ID of the room the user is waiting for a doorbell response of.
///
public int waitingFlat;
///
/// The database ID of the teleporter item ('door') that this user is currently using to 'teleport' between two room instances.
///
public int authenticatedTeleporter;
public itemStripHandler itemStripHandler;
#endregion
#endregion
#region Constructors
///
/// Initializes the Session object.
///
/// The ID this session was assigned to by the Woodpecker.Sessions.sessionManager.
/// The System.Net.Sockets.Socket object of the game client that has been accepted by the game connection listener.
public Session(uint sessionID, Socket gameClient)
{
this.ID = sessionID;
this.gameConnection = new gameConnection(this, gameClient);
}
#endregion
#region Methods
#region Core methods
///
/// Starts the message procedure for the game client.
///
public void Start()
{
this.gameConnection.Initialize();
DateTime dtNow = DateTime.Now;
this.Started = dtNow;
}
///
/// Destroys the session and clears up all used resources.
///
public void Destroy()
{
if (this.isHoldingUser)
{
Engine.Game.Users.removeUserSession(this.User.ID);
this.leaveRoom(false);
this.User = null;
this.itemStripHandler.saveHandItems();
this.itemStripHandler.Clear();
this.itemStripHandler = null;
}
this.gameConnection.Abort();
this.gameConnection = null;
}
#endregion
#region Room instance related methods
///
/// Tries to remove this session's user from it's current room instance.
///
public void leaveRoom(bool cleanupReactors)
{
this.abortTrade();
if (this.waitingFlat > 0)
{
if (Engine.Game.Rooms.roomInstanceRunning(this.waitingFlat))
Engine.Game.Rooms.getRoomInstance(this.waitingFlat).unRegisterSession(this.ID);
}
else
{
if (this.inRoom)
this.roomInstance.unRegisterSession(this.ID);
}
if (cleanupReactors) // Cleanup!
{
gameConnection.reactorHandler.unRegister(new flatReactor().GetType());
gameConnection.reactorHandler.unRegister(new roomReactor().GetType());
}
this.roomInstance = null;
this.roomID = 0;
if(this.authenticatedTeleporter == 0)
this.authenticatedFlat = 0;
this.waitingFlat = 0;
}
///
/// Kicks a user from it's current room and optionally sends a 'moderator warning' message.
///
/// Optional. The moderator message to display.
public void kickFromRoom(string Alert)
{
gameConnection.sendMessage(new serverMessage(18)); // "@R"
leaveRoom(true);
if (Alert.Length > 0)
{
gameConnection.sendLocalizedError("mod_warn/" + Alert);
}
}
#endregion
#region Item inventory and trading
///
/// Modifies the hand page index with a given mode and sends the current hand page of this user.
///
/// 'How-to' modify the hand page index.
public void sendHandStrip(string szMode)
{
if (this.itemStripHandler != null)
{
this.itemStripHandler.changeHandStripPage(szMode); // Switch!
serverMessage Message = new serverMessage(140); // "BL"
Message.Append(this.itemStripHandler.getHandItemCasts());
Message.appendChar(13);
Message.Append(this.itemStripHandler.handItemCount);
this.gameConnection.sendMessage(Message);
}
}
///
/// Refresh the trade boxes for this session's user and his/her trade partner's session user. Only works when both users are trading.
///
public void refreshTradeBoxes()
{
if (this.itemStripHandler.isTrading)
{
Session partnerSession = Engine.Sessions.getSession(this.itemStripHandler.tradePartnerSessionID);
if (partnerSession == null || !partnerSession.itemStripHandler.isTrading)
return;
string myBox = itemStripHandler.generateTradeBox(this);
string partnerBox = itemStripHandler.generateTradeBox(partnerSession);
serverMessage Message = new serverMessage(108); // "Al"
Message.Append(myBox);
Message.Append(partnerBox);
this.gameConnection.sendMessage(Message);
Message.Initialize(108); // "Al"
Message.Append(partnerBox);
Message.Append(myBox);
partnerSession.gameConnection.sendMessage(Message);
}
}
///
/// Aborts the current trade.
///
public void abortTrade()
{
if (this.itemStripHandler.isTrading && this.inRoom)
{
serverMessage tradeWindowCloser = new serverMessage(110); // "An"
serverMessage forcedRefresh = new serverMessage(101); // "Ae"
Session partnerSession = Engine.Sessions.getSession(this.itemStripHandler.tradePartnerSessionID);
this.itemStripHandler.stopTrade();
partnerSession.itemStripHandler.stopTrade();
this.roomInstance.getRoomUser(this.ID).removeStatus("trd");
this.roomInstance.getRoomUser(partnerSession.ID).removeStatus("trd");
this.gameConnection.sendMessage(tradeWindowCloser);
this.gameConnection.sendMessage(forcedRefresh);
partnerSession.gameConnection.sendMessage(tradeWindowCloser);
partnerSession.gameConnection.sendMessage(forcedRefresh);
}
}
#endregion
#region Refresh methods
///
/// Sends the available figure parts for this session user.
///
public void refreshFigureParts()
{
serverMessage Message = new serverMessage(8); // "@H"
Message.Append("[");
if (this.isHoldingUser && this.User.hasClub) // Can use 'Club' parts
Message.Append(Configuration.getConfigurationValue("users.figure.parts.club"));
else
Message.Append(Configuration.getConfigurationValue("users.figure.parts.default"));
Message.Append("]");
this.gameConnection.sendMessage(Message);
}
///
/// Retrieves the FUSE rights for the user on this session and sends it to the client.
///
public void refreshFuseRights()
{
if (this.isHoldingUser)
{
serverMessage Message = new serverMessage(2); // "@B"
Message.Append(Engine.Game.Roles.getRightsForRole(this.User.Role, this.User.hasClub));
this.gameConnection.sendMessage(Message);
}
}
///
/// Refreshes the session user's credit amount. (message 6: @F)
///
public void refreshCredits()
{
if (this.isHoldingUser)
{
serverMessage Message = new serverMessage(6); // "@F"
Message.Append(this.User.Credits);
Message.Append(".0");
this.gameConnection.sendMessage(Message);
}
}
///
/// Refreshes the session user's game ticket amount. (message 124: A|)
///
public void refreshTickets()
{
if (this.isHoldingUser)
{
serverMessage Message = new serverMessage(124); // "A|"
Message.Append(this.User.Credits);
this.gameConnection.sendMessage(Message);
}
}
///
/// Refreshes the session user's film amount for the camera. (message 4: @D)
///
public void refreshFilm()
{
if (this.isHoldingUser)
{
serverMessage Message = new serverMessage(4); // "@D"
Message.Append(this.User.Film);
this.gameConnection.sendMessage(Message);
}
}
///
/// Refreshes the badges for this session user and re-builds the badges message. (229, "Ce")
///
public void refreshBadgeList()
{
if (this.isHoldingUser)
{
List myBadges = Engine.Game.Roles.getDefaultBadgesForRole(this.User.Role);
myBadges.Remove("HC1");
Engine.Game.Users.addPrivateBadgesToList(this.User.ID, this.User.Role, ref myBadges);
if (this.User.hasClub) // Regular club member
myBadges.Add("HC1"); // TODO: make this configurable
if (this.User.hasGoldClub) // Gold club member
myBadges.Add("HC2"); // TODO: make this configurable
if (!myBadges.Contains(this.User.Badge)) // Set badge not valid anymore
this.User.Badge = "";
serverMessage Message = new serverMessage(229); // "Ce"
Message.appendWired(myBadges.Count);
int badgeSlot = 0;
int slotCounter = 0;
foreach (string lBadge in myBadges)
{
Message.appendClosedValue(lBadge);
if (lBadge == this.User.Badge) // Current badge, set slot
badgeSlot = slotCounter;
slotCounter++;
}
Message.appendWired(badgeSlot);
Message.appendWired((this.User.Badge.Length > 0));
this.gameConnection.sendMessage(Message);
}
}
///
/// Refreshes the session user's club status.
///
public void refreshClubStatus()
{
if (this.isHoldingUser)
{
serverMessage Message = new serverMessage(7); // "@G"
Message.appendClosedValue("club_habbo");
Message.appendWired(this.User.clubDaysLeft);
Message.appendWired(this.User.clubMonthsExpired);
Message.appendWired(this.User.clubMonthsLeft);
Message.appendWired(true); // Hide/shows 'days left' label
this.gameConnection.sendMessage(Message);
}
}
///
/// Only works if the session user is in a room. If so, then a whisper with a given message is sent to the user only.
///
/// The text message to whisper to the user.
public void castWhisper(string sMessage)
{
if (this.inRoom)
{
serverMessage Message = new serverMessage(25); // "@Y"
Message.appendWired(this.roomInstance.getSessionRoomUnitID(this.ID));
Message.appendClosedValue(sMessage);
this.gameConnection.sendMessage(Message);
}
}
#endregion
#endregion
}
}