using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using DuckEmulator.HabboHotel.Outside.Messages.Types; using DuckEmulator.HabboHotel.Outside.Rooms.Movement; using DuckEmulator.HabboHotel.Outside.Habbos; using DuckEmulator.HabboHotel.Outside.Clients; using DuckEmulator.HabboHotel.Outside.Misc; using DuckEmulator.Security; using DuckEmulator.HabboHotel.Outside.Furniture; using System.Threading; namespace DuckEmulator.HabboHotel.Outside.Rooms { class RoomUser { internal readonly uint VirtualId; internal HabboData Habbo; internal int X = new int(); internal int Y = new int(); internal double Z = new double(); internal int RotHead = new int(); internal int RotBody = new int(); internal Boolean CanWalk = true; internal Boolean HasKicked = false; internal int GoalX = new int(); internal int GoalY = new int(); internal Boolean IsTrading { get { return Statusses.ContainsKey("trd"); } } internal uint RoomId; internal int DanceId = 0; internal Boolean Asleep = false; internal DateTime LastUpdated = DateTime.Now; internal int SetX; internal int SetY; internal double SetZ; internal Boolean IsWalking = false; internal Boolean DoingLastStep = false; internal Task WalkingTask = null; internal Dictionary Statusses; internal List Path; internal List Ignores; internal Boolean IsDancing { get { return DanceId != 0; } } internal Boolean IsSkating { get { return GetRoom().Effects.ContainsKey(VirtualId) && (GetRoom().Effects[VirtualId] == 38 || GetRoom().Effects[VirtualId] == 39); } } internal RoomUser(uint VirtualId, HabboData Habbo, uint RoomId) { this.VirtualId = VirtualId; this.Habbo = Habbo; this.RoomId = RoomId; Statusses = new Dictionary(); Path = new List(); Ignores = new List(); } internal void Chat(string Text, bool Shout) { if (Text.StartsWith(":") && ChatCommandHandler.ChatCommand(Text.Replace(":", ""), this)) { return; } int MsgId = (Shout) ? 26 : 24; ServerMessage Message = new ServerMessage((uint)MsgId); Message.AppendUInt(VirtualId); Message.AppendStringWithBreak(Text); Message.AppendInt32(GetEmoticon(Text)); foreach (RoomUser User in GetRoom().RoomEngine.Users.Values.ToList()) { if (User.GetClient() == null) { continue; } if (User.GetClient().GetConnection() == null) { continue; } if (!User.Ignores.Contains(Habbo.Id)) { User.GetClient().GetConnection().SendResponse(Message); } if (User.GetClient().GetHabbo().ProgressQuest == 11) { DuckEnvironment.QuestManager.UpdateQuest(User.GetClient().GetHabbo()); } } UpdateActivity(); } internal void Whisper(RoomUser To, string Message) { ServerMessage TellMsg = new ServerMessage(25); TellMsg.AppendUInt(VirtualId); TellMsg.AppendStringWithBreak(Message); TellMsg.AppendBoolean(false); // Send to Receiver To.GetClient().GetConnection().SendResponse(TellMsg); // Send to yourself :D GetClient().GetConnection().SendResponse(TellMsg); } internal int GetEmoticon(string Message) { Message = Message.ToLower(); if (Message.Contains(":)") || Message.Contains(":d") || Message.Contains("=]") || Message.Contains("=d") || Message.Contains(":>") || Message.Contains(":]") || Message.Contains("(;") || Message.Contains("(:")) { return 1; } if (Message.Contains(">:(") || Message.Contains(":@") || Message.Contains(">:[")) { return 2; } if (Message.Contains(":o") || Message.Contains(";o")) { return 3; } if (Message.Contains(":(") || Message.Contains("=[") || Message.Contains(":'(") || Message.Contains("='[")) { return 4; } return 0; } internal void Set(int setX, int setY, double setZ) { X = setX; Y = setY; Z = setZ; } internal void SetRot(int X, int Y, bool Update) { if (X == this.X && Y == this.Y) return; int i = new int(); int Rot = Rotation.Calculate(this.X, this.Y, X, Y); if (RotHead != Rot) { RotHead = Rot; i++; } if (RotBody != Rot) { RotBody = Rot; i++; } if (Update && i > 0) { GetRoom().BroadcastResponse(GetRoom().SerializeStatus(this)); } } internal void WalkToDoor() { if (GetRoom() == null) { return; } if (X == GetRoom().RoomModel.DoorX && Y == GetRoom().RoomModel.DoorY) { GetRoom().RemoveUserFromRoom(VirtualId, true); } else { MoveTo(GetRoom().RoomModel.DoorX, GetRoom().RoomModel.DoorY); } } internal void MoveTo(int X, int Y) { if (!CanWalk) { return; } if (this.GoalX == X && this.GoalY == Y) { return; } if (this.X == X && this.Y == Y) { return; } if (!GetRoom().CanWalk(X,Y,true)) { return; } Point Start = new Point(this.X, this.Y); Point Goal = new Point(X, Y); if (WalkingTask != null && Path.Count > 1) { IntervalWalking(Path[0]); Path = new List(); WalkingTask.Wait(); } if (WalkingTask != null && Path.Count <= 1) { WalkingTask.Wait(); } GoalX = X; GoalY = Y; PathFinder e = new PathFinder(GetRoom().GetMatrix(X, Y), GetRoom().HeightMap, (GetRoom().RoomModel.MaxX + 1), GetRoom().RoomModel.MaxY); var Route = e.FindPath(Start, Goal); if (Route != null) { Route.Remove(Route[0]); Path = Route; if (WalkingTask != null) { WalkingTask = null; } WalkingTask = new Task(ProgressWalking); WalkingTask.Start(); } else { Path = new List(); GoalX = -1; GoalY = -1; } UpdateActivity(); } internal int TileDistance(int X1, int Y1, int X2, int Y2) { return Math.Abs(X1 - X2) + Math.Abs(Y1 - Y2); } internal void ProgressWalking() { while (Path.Count > 0) { IntervalWalking(Path[0]); IsWalking = true; UpdateStatus(); SetTile(); WalkingTask.Wait(500); if (X == GoalX && Y == GoalY) { if (Statusses.ContainsKey("mv")) { Statusses.Remove("mv"); UpdateStatus(); } } IsWalking = false; UpdateOnTile(); } GoalX = -1; GoalY = -1; IsWalking = false; if (WalkingTask != null) { WalkingTask = null; } } internal void IntervalWalking(PathFinderNode Node) { if (Path == null || Path.Count <= 0 || GetRoom() == null) { return; } if (Path.Count > 0) { if (Statusses.ContainsKey("sit") || Statusses.ContainsKey("lay")) { Statusses.Remove("sit"); Statusses.Remove("lay"); } if (Statusses.ContainsKey("mv")) { Statusses.Remove("mv"); } if (GetRoom().CanWalk(Node.X, Node.Y, Path.Count == 1)) { uint FurniId = 0; var Furniture = GetRoom().GetFurnisOnTile(Node.X, Node.Y); if (Furniture != null) { foreach (Furni Furni in Furniture) { if (Furni.GetBaseItem().CanSit) { FurniId = Furni.Id; } } } double Height = GetRoom().GetAffectedAbsuluteHeight(Node.X, Node.Y); if (Statusses.ContainsKey("mv")) { Statusses.Remove("mv"); } Statusses.Add("mv", Node.X + "," + Node.Y + "," + Height.ToString().Replace(',','.')); Path.Remove(Node); SetRot(Node.X, Node.Y, false); SetX = Node.X; SetY = Node.Y; SetZ = Height; } } } internal void SetTile() { this.X = SetX; this.Y = SetY; this.Z = SetZ; if (GetRoom() != null) { if (SetX == GetRoom().RoomModel.DoorX && SetY == GetRoom().RoomModel.DoorY) { CanWalk = false; UpdateStatus(); GetRoom().RemoveUserFromRoom(VirtualId, true); } } } internal void Serialize(ServerMessage Message) { Message.AppendUInt(Habbo.Id); Message.AppendStringWithBreak(Habbo.Username); Message.AppendStringWithBreak(Habbo.Motto); Message.AppendStringWithBreak(Habbo.Look); Message.AppendUInt(VirtualId); Message.AppendInt32(X); Message.AppendInt32(Y); Message.AppendStringWithBreak(Z.ToString().Replace(',', '.')); Message.AppendInt32(2); Message.AppendInt32(1); Message.AppendStringWithBreak(Habbo.Gender.ToLower()); Message.AppendInt32(-1); Message.AppendInt32(-1); Message.AppendInt32(-1); Message.AppendStringWithBreak(""); // swimsuit Message.AppendInt32(Habbo.Score); } internal void SerializeStatus(ServerMessage Message) { Message.AppendUInt(VirtualId); Message.AppendInt32(X); Message.AppendInt32(Y); Message.AppendStringWithBreak(Z.ToString().Replace(",", ".")); Message.AppendInt32(RotHead); //rothead Message.AppendInt32(RotBody); //rotbody Message.AppendString("/"); foreach (KeyValuePair kvp in Statusses) { Message.AppendString(kvp.Key + " " + kvp.Value); Message.AppendString("/"); } Message.AppendStringWithBreak("/"); } internal void UpdateOnTile() { bool UpdateNeeded = false; if (GetRoom() == null) { return; } if (GetRoom().GetAffectedHeight(X, Y) != Z) { Z = GetRoom().GetAffectedHeight(X, Y); UpdateNeeded = true; } if (Statusses.ContainsKey("sit") || Statusses.ContainsKey("lay")) { Statusses.Remove("sit"); Statusses.Remove("lay"); UpdateNeeded = true; } if (GetRoom().HasRoller(VirtualId)) { GetRoom().RemoveRoller(VirtualId); } var Furniture = GetRoom().GetFurnisOnTile(X, Y); if (Furniture != null) { if (Furniture.Count == 0) { if (GetRoom().Effects.ContainsKey(VirtualId)) { GetRoom().Effects.Remove(VirtualId); ServerMessage EffectMessage = new ServerMessage(485); EffectMessage.AppendUInt(VirtualId); EffectMessage.AppendInt32(-1); GetRoom().BroadcastResponse(EffectMessage); } } foreach (Furni Furni in Furniture) { if (Furni.GetBaseItem().SpriteName.ToLower() == "es_skating_ice") { if (!GetRoom().Effects.ContainsKey(VirtualId)) { int eId = (GetClient().GetHabbo().Gender.ToLower() == "m") ? 38 : 39; GetRoom().Effects.Add(VirtualId,(uint)eId); ServerMessage EffectMessage = new ServerMessage(485); EffectMessage.AppendUInt(VirtualId); EffectMessage.AppendInt32(eId); GetRoom().BroadcastResponse(EffectMessage); } } else if (GetRoom().Effects.ContainsKey(VirtualId)) { GetRoom().Effects.Remove(VirtualId); ServerMessage EffectMessage = new ServerMessage(485); EffectMessage.AppendUInt(VirtualId); EffectMessage.AppendInt32(-1); GetRoom().BroadcastResponse(EffectMessage); } if (Furni.GetBaseItem().CanSit) { if (!Statusses.ContainsKey("sit")) { RotBody = Furni.Rotation; RotHead = Furni.Rotation; Statusses.Add("sit", "1.2"); UpdateNeeded = true; var Height = GetRoom().GetAffectedHeight(X, Y); Z = Height; } } if (Furni.GetBaseItem().InteractionType.ToLower() == "bed") { if (!Statusses.ContainsKey("lay")) { RotBody = Furni.Rotation; RotHead = Furni.Rotation; Statusses.Add("lay", "1.2"); UpdateNeeded = true; var Height = GetRoom().GetAffectedHeight(X, Y); Z = Height; } } if (Furni.GetBaseItem().InteractionType.ToLower() == "roller") { if (!GetRoom().HasRoller(VirtualId) && !IsWalking && GetRoom() != null) { GetRoom().UserRollers.Add(new UserRoller(this, Furni)); } } } } if (UpdateNeeded) { UpdateStatus(); } } internal void UpdateStatus() { if (GetRoom() != null) { GetRoom().BroadcastResponse(GetRoom().SerializeStatus(this)); } } internal void CheckAsleep() { if ((DateTime.Now - LastUpdated).TotalMinutes >= 5) { ServerMessage Asleep = new ServerMessage(486); Asleep.AppendUInt(VirtualId); Asleep.AppendBoolean(true); GetRoom().BroadcastResponse(Asleep); this.Asleep = true; } } internal void UpdateActivity() { if (this.Asleep) { ServerMessage Asleep = new ServerMessage(486); Asleep.AppendUInt(VirtualId); Asleep.AppendBoolean(false); GetRoom().BroadcastResponse(Asleep); this.Asleep = false; } LastUpdated = DateTime.Now; } internal void Dispose() { this.RoomId = 0; } internal Client GetClient() { return Habbo.GetConnection().GetClient(); } internal Room GetRoom() { return DuckEnvironment.RoomManager.GetRoom(RoomId); } } }