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 } }