using System; using System.Collections.Generic; using System.Linq; using System.Text; using DuckEmulator.HabboHotel.Outside.Messages.Types; using DuckEmulator.HabboHotel.Outside.Messages; using DuckEmulator.HabboHotel.Outside.Habbos; using DuckEmulator.HabboHotel.Outside.Clients; using DuckEmulator.HabboHotel.Outside.Rooms.Movement; using System.Windows.Forms; using System.Drawing; using System.Threading.Tasks; using System.Data; using DuckEmulator.HabboHotel.Outside.Furniture; using DuckEmulator.HabboHotel.Inside.Storage.MySql.Database.Interfaces; using DuckEmulator.Security; namespace DuckEmulator.HabboHotel.Outside.Rooms { class Room { internal readonly uint Id; internal string Name; internal string Description; internal string Owner; internal string Model; internal string Password = ""; internal Boolean HideWalls = false; internal Boolean AllowPets = false; internal Boolean AllowPetsEat = false; internal Boolean AllowWalkthough = false; internal int WallType = new int(); internal int FloorType = new int(); internal int RoomScore = new int(); internal string Landscape = "0.0"; internal string Wallpaper = "0.0"; internal string Floor = "0.0"; internal int State = 0; internal int Category = 0; internal int MaxUsers = 25; internal int IdleTime = 0; internal const ushort ROLLER_SPEED = 2; internal Boolean Cantrade { get { return (Category == 0); } } internal bool[,] Matrix; internal double[,] HeightMap; internal List Tags; internal SecurityTimer RollerTimer = null; internal SecurityList UserRollers; internal SecurityList FurniRollers; internal SecurityDictionary Effects; internal RoomEvent Event = null; internal RoomIcon Icon = null; internal int UserCount { get { if (RoomEngine != null) { return RoomEngine.Users.Count; } else { return 0; } } } internal RoomEngine RoomEngine = null; internal RoomModel RoomModel { get { return DuckEnvironment.RoomManager.RoomModel(Model.ToLower()); } } internal Boolean IsAlive { get { return RoomEngine != null; } } internal Boolean HasEvent { get { return Event != null; } } internal Room(uint Id, string Name, string Owner, string Model, Boolean HideWalls, int WallType, int FloorType, int RoomScore, string Description, string Landscape,string Wallpaper, string Floor, int State, string Password, int MaxUsers, int Category, string Tags, int ForeGround, int BackGround, string IconItems, Boolean AllowPets, Boolean AllowPetsEat, Boolean AllowWalkthough) { this.Id = Id; this.Name = Name; this.Owner = Owner; this.Model = Model; this.HideWalls = HideWalls; this.WallType = WallType; this.FloorType = FloorType; this.RoomScore = RoomScore; this.Description = Description; this.Landscape = Landscape; this.Wallpaper = Wallpaper; this.Floor = Floor; this.State = State; this.Password = Password; this.MaxUsers = MaxUsers; this.Category = Category; this.Tags = Tags.Split(',').ToList(); this.AllowPets = AllowPets; this.AllowPetsEat = AllowPetsEat; this.AllowWalkthough = AllowWalkthough; this.Icon = new RoomIcon(Id, ForeGround, BackGround, IconItems); } #region Coords and Walking internal void GenerateMatrix() { this.Matrix = new bool[RoomModel.MaxX, RoomModel.MaxY]; this.HeightMap = new double[RoomModel.MaxX, RoomModel.MaxY]; for (int y = 0; y < RoomModel.MaxY; y++) { for (int x = 0; x < RoomModel.MaxX; x++) { var Tile = RoomModel.Lines[y].Substring(x, 1); int TileHeight; if (int.TryParse(Tile, out TileHeight)) { HeightMap[x, y] = (TileHeight + 0.0); Matrix[x, y] = true; } else { Matrix[x, y] = false; HeightMap[x, y] = 0.0; } } } foreach (Furni Furni in RoomEngine.GetFloorItems()) { var Tiles = RoomEngine.GetAffectedTiles(Furni.GetBaseItem().Length, Furni.GetBaseItem().Width, Furni.X, Furni.Y, Furni.Rotation); foreach (AffectedTile Tile in Tiles.Values.ToList()) { if (Furni.GetBaseItem().CanWalk) { Matrix[Tile.X, Tile.Y] = true; } else if (Furni.GetBaseItem().Type == "gate") { int State; if (!int.TryParse(Furni.ExtraData, out State)) { State = 0; } if (State == 0) { Matrix[Tile.X, Tile.Y] = true; } else { Matrix[Tile.X, Tile.Y] = false; } } else { Matrix[Tile.X, Tile.Y] = false; } } if (Furni.GetBaseItem().CanWalk) { Matrix[Furni.X, Furni.Y] = true; } else if (Furni.GetBaseItem().Type == "gate") { int State; if (!int.TryParse(Furni.ExtraData, out State)) { State = 0; } if (State == 0) { Matrix[Furni.X, Furni.Y] = true; } else { Matrix[Furni.X, Furni.Y] = false; } } else { Matrix[Furni.X, Furni.Y] = false; } } if (!AllowWalkthough) { foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { Matrix[User.X, User.Y] = false; } } // Door state Matrix[RoomModel.DoorX, RoomModel.DoorY] = true; HeightMap[RoomModel.DoorX, RoomModel.DoorY] = RoomModel.DoorZ; } internal Boolean CanWalk(int X, int Y, bool LastStep) { if (X >= RoomModel.MaxX || Y >= RoomModel.MaxY) { return false; } var Furniture = GetFurnisOnTile(X, Y); foreach (Furni Furni in Furniture) { if (Furni.GetBaseItem().CanSit && LastStep) { return true; } else if (Furni.GetBaseItem().CanSit && !LastStep) { return false; } else if (!Furni.GetBaseItem().CanWalk) { return false; } } return Matrix[X, Y]; } internal double GetAffectedHeight(int X, int Y) { double Z = 0.0; try { Z = HeightMap[X, Y]; } catch { } foreach (Furni Furni in RoomEngine.GetFloorItems()) { if (Furni.GetBaseItem().CanSit) { continue; } var Tiles = RoomEngine.GetAffectedTiles(Furni.GetBaseItem().Length, Furni.GetBaseItem().Width, Furni.X, Furni.Y, Furni.Rotation); foreach (AffectedTile Tile in Tiles.Values.ToList()) { if (Tile.X == X && Tile.Y == Y) { Z += Furni.GetBaseItem().Height; } } if (Furni.X == X && Furni.Y == Y) { Z += Furni.GetBaseItem().Height; } } return Z; } internal double GetAffectedHeight(int X, int Y, uint FurniId) { double Z = 0.0; try { Z = HeightMap[X, Y]; } catch { } foreach (Furni Furni in GetFurnisOnTile(X,Y)) { if (Furni.GetBaseItem().CanSit || Furni.Id == FurniId) { continue; } if (Furni.X == X && Furni.Y == Y) { Z += Furni.GetBaseItem().Height; } } return Z; } internal double GetAffectedAbsuluteHeight(int X, int Y) { double Z = 0.0; try { Z = HeightMap[X, Y]; } catch { } var Furniture = GetFurnisOnTile(X, Y); if (Furniture.Count > 0) { if (Furniture[Furniture.Count - 1].GetBaseItem().CanSit) { return Furniture[Furniture.Count - 1].Z; } return Z + Furniture[Furniture.Count - 1].GetBaseItem().Height; } return Z; } internal bool[,] GetMatrix(int GoalX, int GoalY) { bool[,] newMatrix = new bool[RoomModel.MaxX, RoomModel.MaxY]; for (int y = 0; y < RoomModel.MaxY; y++) { for (int x = 0; x < RoomModel.MaxX; x++) { newMatrix[x, y] = Matrix[x, y]; } } var FurniOnTile = GetFurnisOnTile(GoalX, GoalY); // LastStep. foreach (Furni Furni in FurniOnTile) { if (Furni.GetBaseItem().CanSit) { newMatrix[Furni.X, Furni.Y] = true; var Tiles = RoomEngine.GetAffectedTiles(Furni.GetBaseItem().Length, Furni.GetBaseItem().Width, Furni.X, Furni.Y, Furni.Rotation); foreach(AffectedTile Tile in Tiles.Values.ToList()) { newMatrix[Tile.X, Tile.Y] = true; } } } return newMatrix; } #endregion #region Messages internal void SerializeNavigator(ServerMessage Message, bool Events) { Message.AppendUInt(Id); //Roomid if (!Events || !HasEvent) { Message.AppendBoolean(false); // idk Message.AppendStringWithBreak(Name); Message.AppendStringWithBreak(Owner); Message.AppendInt32(State); // idk Message.AppendInt32(UserCount); // idk Message.AppendInt32(MaxUsers); // maxusers Message.AppendStringWithBreak(Description); Message.AppendBoolean(Cantrade); // idk Message.AppendBoolean(true); // idk Message.AppendInt32(RoomScore); // category Message.AppendInt32(Category); Message.AppendStringWithBreak(""); Message.AppendInt32(Tags.Count); foreach (string Tag in Tags) { Message.AppendStringWithBreak(Tag); } } else if (Events & HasEvent) { Message.AppendBoolean(true); // idk Message.AppendStringWithBreak(Event.Name); Message.AppendStringWithBreak(Owner); Message.AppendInt32(State); // idk Message.AppendInt32(UserCount); // idk Message.AppendInt32(MaxUsers); // maxusers Message.AppendStringWithBreak(Event.Description); Message.AppendBoolean(Cantrade); // idk Message.AppendBoolean(true); // idk Message.AppendInt32(RoomScore); // category Message.AppendInt32(Event.Category); Message.AppendStringWithBreak(Event.GetTime()); Message.AppendInt32(Event.Tags.Count); foreach (string Tag in Event.Tags) { Message.AppendStringWithBreak(Tag); } } Icon.Serialize(Message); Message.AppendBoolean(true); // idk } internal void SerializeRoomData(ServerMessage Message) { Message.AppendInt32(1); SerializeNavigator(Message, false); } internal ServerMessage SerializeReliativeMap() { ServerMessage Message = new ServerMessage(31); RoomModel.SerializeRe(Message); return Message; } internal ServerMessage SerializeAlternativeMap() { ServerMessage Message = new ServerMessage(470); RoomModel.Serialize(Message); return Message; } internal ServerMessage SerializeUsers() //users { ServerMessage Message = new ServerMessage(28); Message.AppendInt32(RoomEngine.Users.Count); foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { User.Serialize(Message); } return Message; } internal ServerMessage SerializeUser(RoomUser User) { ServerMessage Message = new ServerMessage(28); Message.AppendInt32(1); User.Serialize(Message); return Message; } internal ServerMessage SerializeWallItems() { ServerMessage Message = new ServerMessage(45); Message.AppendInt32(RoomEngine.GetWallItems().Count); // no count , not coded yet foreach (Furni Furni in RoomEngine.GetWallItems()) { Furni.SerializeRoom(Message); } return Message; } internal ServerMessage SerializeFloorItems() { ServerMessage Message = new ServerMessage(32); Message.AppendInt32(RoomEngine.GetFloorItems().Count); // no count , not coded yet foreach (Furni Furni in RoomEngine.GetFloorItems()) { Furni.SerializeRoom(Message); } return Message; } internal void SerializeBefore(MessageHandler MessageHandler) { ServerMessage Link = new ServerMessage(166); Link.AppendStringWithBreak("/client/private/" + Id + "/id"); MessageHandler.SendResponse(Link); if (Wallpaper != "0.0") { ServerMessage Wallp = new ServerMessage(46); Wallp.AppendStringWithBreak("wallpaper"); Wallp.AppendStringWithBreak(Wallpaper); MessageHandler.SendResponse(Wallp); } if (Floor != "0.0") { ServerMessage Flor = new ServerMessage(46); Flor.AppendStringWithBreak("floor"); Flor.AppendStringWithBreak(Floor); MessageHandler.SendResponse(Flor); } ServerMessage LandScape = new ServerMessage(46); LandScape.AppendStringWithBreak("landscape"); LandScape.AppendStringWithBreak(Landscape); MessageHandler.SendResponse(LandScape); ServerMessage Params = new ServerMessage(69); Params.AppendStringWithBreak(Model); Params.AppendUInt(Id); MessageHandler.SendResponse(Params); ServerMessage RoomScore = new ServerMessage(345); RoomScore.AppendInt32((MessageHandler.GetClient().GetHabbo().RatedRooms.Contains(Id) || RoomEngine.HasRights(MessageHandler.GetClient().GetHabbo(), true)) ? this.RoomScore : -1); MessageHandler.SendResponse(RoomScore); ServerMessage Event = new ServerMessage(370); if (HasEvent) { this.Event.Serialize(Event); } else { Event.AppendStringWithBreak("-1"); // -1 = no event } MessageHandler.SendResponse(Event); } internal void DropEvent() { if (!HasEvent) { return; } this.Event = null; ServerMessage Event = new ServerMessage(370); Event.AppendStringWithBreak("-1"); BroadcastResponse(Event); } internal void SerializeInLine(MessageHandler MessageHandler) { if (MessageHandler.GetClient().GetHabbo() == null) { return; // can't do anything } MessageHandler.SendResponse(SerializeUsers()); // todo Spectators etc ? foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { if (User == null) { continue; } if (User.IsDancing) { ServerMessage DanceMessage = new ServerMessage(480); DanceMessage.AppendUInt(User.VirtualId); DanceMessage.AppendInt32(User.DanceId); MessageHandler.SendResponse(DanceMessage); } if (User.Asleep) { ServerMessage SleepMessage = new ServerMessage(486); SleepMessage.AppendUInt(User.VirtualId); SleepMessage.AppendBoolean(true); MessageHandler.SendResponse(SleepMessage); } if (User.GetClient() != null) { if (User.GetClient().GetHabbo() != null) { if (User.GetClient().GetHabbo().GetEffectsTable() != null) { if (User.GetClient().GetHabbo().GetEffectsTable().CurrentEffectId > 0) { ServerMessage EffectMessage = new ServerMessage(485); EffectMessage.AppendUInt(User.VirtualId); EffectMessage.AppendUInt(User.GetClient().GetHabbo().GetEffectsTable().CurrentEffectId); MessageHandler.SendResponse(EffectMessage); } } } } } foreach (KeyValuePair kvp in Effects) { ServerMessage EffectMessage = new ServerMessage(485); EffectMessage.AppendUInt(kvp.Key); EffectMessage.AppendUInt(kvp.Value); MessageHandler.SendResponse(EffectMessage); } ServerMessage StaticFurniMap = new ServerMessage(30); StaticFurniMap.AppendBoolean(false); // should be 0, but hasnt ? MessageHandler.SendResponse(StaticFurniMap); MessageHandler.SendResponse(SerializeFloorItems()); MessageHandler.SendResponse(SerializeWallItems()); RoomUser Usernew = AddUserToRoom(MessageHandler.GetClient().GetHabbo()); if (Usernew != null) { if (Usernew.GetClient() != null) { if (Usernew.GetClient().GetHabbo() != null) { if (Usernew.GetClient().GetHabbo().GetEffectsTable() != null) { if (Usernew.GetClient().GetHabbo().GetEffectsTable().CurrentEffectId > 0) { ServerMessage EffectMessage = new ServerMessage(485); EffectMessage.AppendUInt(Usernew.VirtualId); EffectMessage.AppendUInt(Usernew.GetClient().GetHabbo().GetEffectsTable().CurrentEffectId); MessageHandler.SendResponse(EffectMessage); } } } } } ServerMessage RoomStruct = new ServerMessage(472); RoomStruct.AppendBoolean(HideWalls); RoomStruct.AppendInt32(WallType); // -1 = thing, 0 = normal, 1 = fat RoomStruct.AppendInt32(FloorType); // -1 = thing, 0 = normal, 1 = fat MessageHandler.SendResponse(RoomStruct); ServerMessage OwnerShip = new ServerMessage(471); OwnerShip.AppendBoolean(true); OwnerShip.AppendUInt(MessageHandler.GetClient().GetHabbo().Id); // HabboId or RoomId? OwnerShip.AppendBoolean(RoomEngine.HasRights(MessageHandler.GetClient().GetHabbo(), true)); // has ownership MessageHandler.SendResponse(OwnerShip); ServerMessage RoomData = new ServerMessage(454); SerializeRoomData(RoomData); //todo fix this message : messed up MessageHandler.SendResponse(RoomData); MessageHandler.SendResponse(SerializeStatusses()); } #endregion #region Users internal ServerMessage SerializeStatusses() { ServerMessage Message = new ServerMessage(34); Message.AppendInt32(RoomEngine.Users.Count); foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { User.SerializeStatus(Message); } return Message; } internal ServerMessage SerializeStatus(RoomUser User) { ServerMessage Message = new ServerMessage(34); Message.AppendInt32(1); User.SerializeStatus(Message); return Message; } internal RoomUser AddUserToRoom(HabboData Habbo) { if (!IsAlive || Habbo == null || RoomEngine.GetUserByHabboId(Habbo.Id) != null) { return null; } RoomUser newUser = new RoomUser(RoomEngine.UserPointer++, Habbo, Id); if (RoomEngine.HasRights(Habbo, true)) { newUser.Statusses.Add("flatctrl", "useradmin"); Habbo.SendResponse(new ServerMessage(42)); Habbo.SendResponse(new ServerMessage(47)); } else if (RoomEngine.HasRights(Habbo, false)) { Habbo.SendResponse(new ServerMessage(42)); newUser.Statusses.Add("flatctrl", ""); } RoomEngine.AddUser(newUser); BroadcastResponse(SerializeUser(newUser)); return newUser; } internal void RemoveUserFromRoom(uint Id, bool HotelView) { if (!IsAlive || !RoomEngine.HasUser(Id)) { return; } RoomUser User = RoomEngine.GetUser(Id); if (User == null) { return; } if (HotelView) { if (User.HasKicked) { ServerMessage KickMessage = new ServerMessage(33); KickMessage.AppendInt32(4008); User.GetClient().GetMessageHandler().SendResponse(KickMessage); } User.GetClient().GetConnection().SendResponse(new ServerMessage(18)); User.GetClient().GetHabbo().OnLeaveRoom(); } ServerMessage Message = new ServerMessage(29); Message.AppendStringWithBreak(Id.ToString()); BroadcastResponse(Message); RoomEngine.RemoveUser(Id); } internal void KickUser(uint HabboId, bool Notif) { if (!IsAlive) { return; } RoomUser User = RoomEngine.GetUserByHabboId(HabboId); if (User == null) { return; } User.WalkToDoor(); User.CanWalk = false; if (User.X == RoomModel.DoorX && User.Y == RoomModel.DoorY) { RemoveUserFromRoom(Id, true); } User.HasKicked = Notif; } internal void UpdateUserInteraction(int X, int Y) { foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { if (User.X == X && User.Y == Y) { User.UpdateOnTile(); } } } internal Boolean UsersOnTile(int X, int Y) { foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { if (User.X == X && User.Y == Y) { return true; } } return false; } #endregion #region Items internal Boolean SetFloorItem(Furni Furni, int X, int Y, int Rot, bool ServerMessage) { // Validate Rights, nullable cases etc. if (Furni == null || !IsAlive) { return false; } if (Furni.X == X && Furni.Y == Y && Furni.Rotation == Rot) { return false; } if (X == RoomModel.DoorX && Y == RoomModel.DoorY) { return false; } // Generating Tiles around Main-Plate. var Tiles = RoomEngine.GetAffectedTiles(Furni.GetBaseItem().Length, Furni.GetBaseItem().Width, X, Y, Rot); // Looks in place-zone for blocking plates. if (Tiles != null) { foreach (AffectedTile Tile in Tiles.Values.ToList()) { var Furnis = GetFurnisOnTile(Tile.X, Tile.Y); if (Furnis.Count > 0) { foreach (Furni Furniture in Furnis) { if (Furniture.Id != Furni.Id) { if (!Furniture.GetBaseItem().CanStack) { return false; } } } } } } var MianTileFurnies = GetFurnisOnTile(X, Y); if (MianTileFurnies.Count > 0) { foreach (Furni Furniture in MianTileFurnies) { if (Furniture.Id != Furni.Id) { if (!Furniture.GetBaseItem().CanStack) { return false; } } } } // Gets height under new place. var Height = GetAffectedHeight(X, Y, Furni.Id); // Updates RoomId of item if not done before. if (Furni.RoomId != Id) { Furni.SetRoom(Id); Furni.Interactor.FurniPlaced(Furni); } // Updates Coordinate of Furniture. Furni.Set(X, Y, Height, Rot); // Sends Response to all users. if (ServerMessage) { // Generates MessageId if new or old item. var MessageId = ((RoomEngine.Items.ContainsKey(Furni.Id)) ? 95 : 93); ServerMessage Message = new ServerMessage((uint)MessageId); Furni.SerializeRoom(Message); BroadcastResponse(Message); } // Add Furni if it's not in the list. if (!RoomEngine.Items.ContainsKey(Furni.Id)) { RoomEngine.Items.Add(Furni.Id, Furni); } // Updates Matrix. GenerateMatrix(); // Updates users on Main-Tile. UpdateUserInteraction(X, Y); // Updates users on Greater-Tiles. foreach (AffectedTile Tile in Tiles.Values.ToList()) { UpdateUserInteraction(Tile.X, Tile.Y); } // Validated return true; } internal Boolean DeleteItem(uint FurniId) { if (!IsAlive) { return false; } Furni Furni = RoomEngine.GetFurni(FurniId); if (Furni == null) { return false; } if (Furni.IsWallItem) { ServerMessage Message = new ServerMessage(84); Message.AppendRawUInt(Furni.Id); Message.AppendStringWithBreak(""); Message.AppendBoolean(false); BroadcastResponse(Message); } else if (Furni.IsFloorItem) { ServerMessage Message = new ServerMessage(94); Message.AppendRawUInt(Furni.Id); Message.AppendStringWithBreak(""); Message.AppendBoolean(false); BroadcastResponse(Message); } RoomEngine.Items.Remove(FurniId); if (Furni.IsFloorItem) { GenerateMatrix(); var Tiles = RoomEngine.GetAffectedTiles(Furni.GetBaseItem().Length, Furni.GetBaseItem().Width, Furni.X, Furni.Y, Furni.Rotation); UpdateUserInteraction(Furni.X, Furni.Y); foreach (AffectedTile Tile in Tiles.Values.ToList()) { UpdateUserInteraction(Tile.X, Tile.Y); } Furni.Set(0, 0, 0.0, 0); } else { Furni.SetWall("", true); } if (Furni.RoomId == Id) { Furni.SetRoom(0); Furni.Interactor.FurniTaken(Furni); } return true; } internal Boolean SetWallItem(Furni Furni, string WallPos) { if (Furni == null || !IsAlive) { return false; } Furni.SetWall(WallPos, false); var MessageId = ((RoomEngine.Items.ContainsKey(Furni.Id)) ? 85 : 83); ServerMessage Message = new ServerMessage((uint)MessageId); Furni.SerializeRoom(Message); BroadcastResponse(Message); Furni.SetWall(WallPos, true); if (Furni.RoomId != Id) { Furni.SetRoom(Id); Furni.Interactor.FurniPlaced(Furni); } if (!RoomEngine.Items.ContainsKey(Furni.Id)) { RoomEngine.Items.Add(Furni.Id, Furni); } return true; } internal string WallPositionCheck(string wallPosition) { //:w=3,2 l=9,63 l try { if (wallPosition.Contains(Convert.ToChar(13))) { return null; } if (wallPosition.Contains(Convert.ToChar(9))) { return null; } string[] posD = wallPosition.Split(' '); if (posD[2] != "l" && posD[2] != "r") return null; string[] widD = posD[0].Substring(3).Split(','); int widthX = Convert.ToInt32(widD[0]); int widthY = Convert.ToInt32(widD[1]); if (widthX < 0 || widthY < 0 || widthX > 200 || widthY > 200) return null; string[] lenD = posD[1].Substring(2).Split(','); int lengthX = Convert.ToInt32(lenD[0]); int lengthY = Convert.ToInt32(lenD[1]); if (lengthX < 0 || lengthY < 0 || lengthX > 200 || lengthY > 200) return null; return ":w=" + widthX + "," + widthY + " " + "l=" + lengthX + "," + lengthY + " " + posD[2]; } catch { return null; } } internal List GetFurnisOnTile(int X, int Y) { var List = new List(); foreach (Furni Furni in RoomEngine.Items.Values.ToList()) { var Tiles = RoomEngine.GetAffectedTiles(Furni.GetBaseItem().Length,Furni.GetBaseItem().Width, Furni.X, Furni.Y, Furni.Rotation); foreach (AffectedTile Tile in Tiles.Values.ToList()) { if (Tile.X == X && Tile.Y == Y) { List.Add(Furni); } } if (Furni.X == X && Furni.Y == Y) { if (!List.Contains(Furni)) { List.Add(Furni); } } } return List.ToList(); } #endregion #region Global internal void BroadcastResponse(ServerMessage Message) { if (!IsAlive) { return; } foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { if (User.GetClient() == null) { continue; } if (User.GetClient().GetConnection() == null) { continue; } User.GetClient().GetConnection().SendResponse(Message); } } internal void Dispose() { if (IsAlive) { DropEvent(); if (RollerTimer != null) { RollerTimer.Dispose(); RollerTimer = null; } RoomEngine.Dispose(); RoomEngine = null; } } internal void ThrowAlive() { this.RoomEngine = new RoomEngine(Id); this.GenerateMatrix(); // Rollers this.RollerTimer = new SecurityTimer((int)(1000 * ROLLER_SPEED), DoRollers); this.RollerTimer.Release(); this.UserRollers = new SecurityList(); this.FurniRollers = new SecurityList(); this.Effects = new SecurityDictionary(); } internal void CheckUsers() { int i = 0; foreach (RoomUser User in RoomEngine.Users.Values.ToList()) { User.CheckAsleep(); if (!User.Asleep) { i++; } if (User.IsSkating) { User.GetClient().GetHabbo().IceTagTime++; User.GetClient().GetHabbo().UpdateVariable("icetag_time",User.GetClient().GetHabbo().IceTagTime); DuckEnvironment.AchievementManager.UpdateAchievement(User.GetClient().GetHabbo(), 105); } } if (i <= 0) { IdleTime++; if (IdleTime >= 6 || UserCount <= 0) { DuckEnvironment.RoomManager.UnloadRoom(Id); } } } #region Rollers internal void DoRollers() { if (IsAlive) { foreach (UserRoller Roller in UserRollers) { Roller.Broadcast(); } CheckRollers(); foreach (FurniRoller Roller in FurniRollers) { Roller.Broadcast(); } FurniRollers = new SecurityList(); } } private void CheckRollers() { foreach (Furni Roller in RoomEngine.GetFloorItems()) { if (Roller.GetBaseItem().InteractionType.ToLower() == "roller") { var Furnies = GetFurnisOnTile(Roller.X, Roller.Y); foreach (Furni Furni in Furnies.ToList()) { if (Furni.Id != Roller.Id && Furni.Z > Roller.Z) { if (!HasRoller(Furni)) { FurniRollers.Add(new FurniRoller(Furni, Roller)); } } } } } } internal Boolean HasRoller(uint VirtualId) { foreach (UserRoller Data in UserRollers) { if (Data.User.VirtualId == VirtualId) { return true; } } return false; } internal Boolean RemoveRoller(uint VirtualId) { foreach (UserRoller Data in UserRollers) { if (Data.User.VirtualId == VirtualId) { return UserRollers.Remove(Data); } } return false; } internal Boolean HasRoller(Furni Furni) { foreach (FurniRoller Data in FurniRollers) { if (Data.Furni.Id == Furni.Id) { return true; } } return false; } internal Boolean RemoveRoller(Furni Furni) { foreach (FurniRoller Data in FurniRollers) { if (Data.Furni.Id == Furni.Id) { return FurniRollers.Remove(Data); } } return false; } #endregion #endregion } class RoomEngine { internal SecurityDictionary Users; internal SecurityDictionary Items; private uint RoomId; internal List UsersWithRights; internal Dictionary UserBans; internal uint UserPointer = 1; internal List GetFloorItems() { var List = new List(); foreach (Furni Furni in Items.Values.ToList()) { if (Furni.IsFloorItem) { List.Add(Furni); } } return List.ToList(); } internal List GetWallItems() { var List = new List(); foreach (Furni Furni in Items.Values.ToList()) { if (Furni.IsWallItem) { List.Add(Furni); } } return List.ToList(); } internal RoomEngine(uint RoomId) { this.RoomId = RoomId; Users = new SecurityDictionary(); UserBans = new Dictionary(); LoadUsersWithRights(); LoadFurni(); } internal void LoadFurni() { Items = new SecurityDictionary(); DataTable Data = null; using (IQueryAdapter Adapter = DuckEnvironment.GetAdapter()) { Adapter.setQuery("SELECT * FROM items WHERE room_id = '" + RoomId + "'"); Data = Adapter.getTable(); } if (Data == null) return; foreach (DataRow Row in Data.Rows) { Furni Furni = new Furni( uint.Parse(Row["id"].ToString()), uint.Parse(Row["user_id"].ToString()), uint.Parse(Row["room_id"].ToString()), uint.Parse(Row["base_id"].ToString()), int.Parse(Row["x"].ToString()), int.Parse(Row["y"].ToString()), int.Parse(Row["rot"].ToString()), double.Parse(Row["z"].ToString()), Row["wall_pos"].ToString(), Row["extra_data"].ToString()); Items.Add(Furni.Id, Furni); } } internal Dictionary GetAffectedTiles(int Length, int Width, int PosX, int PosY, int Rotation) { int x = 0; var PointList = new Dictionary(); if (Length > 1) { if (Rotation == 0 || Rotation == 4) { for (int i = 1; i < Length; i++) { PointList.Add(x++, new AffectedTile(PosX, PosY + i, i)); for (int j = 1; j < Width; j++) { PointList.Add(x++, new AffectedTile(PosX + j, PosY + i, (i < j) ? j : i)); } } } else if (Rotation == 2 || Rotation == 6) { for (int i = 1; i < Length; i++) { PointList.Add(x++, new AffectedTile(PosX + i, PosY, i)); for (int j = 1; j < Width; j++) { PointList.Add(x++, new AffectedTile(PosX + i, PosY + j, (i < j) ? j : i)); } } } } if (Width > 1) { if (Rotation == 0 || Rotation == 4) { for (int i = 1; i < Width; i++) { PointList.Add(x++, new AffectedTile(PosX + i, PosY, i)); for (int j = 1; j < Length; j++) { PointList.Add(x++, new AffectedTile(PosX + i, PosY + j, (i < j) ? j : i)); } } } else if (Rotation == 2 || Rotation == 6) { for (int i = 1; i < Width; i++) { PointList.Add(x++, new AffectedTile(PosX, PosY + i, i)); for (int j = 1; j < Length; j++) { PointList.Add(x++, new AffectedTile(PosX + j, PosY + i, (i < j) ? j : i)); } } } } return PointList; } internal Furni GetFurni(uint Id) { try { return Items[Id]; } catch { return null; } } internal void LoadUsersWithRights() { UsersWithRights = new List(); } internal void AddUser(RoomUser User) { if (HasUser(User.VirtualId)) return; User.RotBody = User.GetRoom().RoomModel.DoorRot; User.RotHead = User.GetRoom().RoomModel.DoorRot; User.GetClient().GetHabbo().OnEnterRoom(); User.Set(User.GetRoom().RoomModel.DoorX, User.GetRoom().RoomModel.DoorY, User.GetRoom().RoomModel.DoorZ); Users.Add(User.VirtualId, User); } internal void RemoveUser(uint Id) { if (!HasUser(Id)) return; GetRoom().Matrix[GetUser(Id).X,GetUser(Id).Y] = true; GetUser(Id).Dispose(); Users.Remove(Id); } internal RoomUser GetUser(uint Id) { try { return Users[Id]; } catch { return null; } } internal RoomUser GetUserByHabboId(uint Id) { foreach (RoomUser User in Users.Values.ToList()) { if (User.Habbo.Id == Id) { return User; } } return null; } internal void AddBan(uint Id) { if (UserBans.ContainsKey(Id)) { UserBans[Id] = DateTime.Now; // more time to wait :D } else { UserBans.Add(Id, DateTime.Now); } } internal Boolean UserHasBanned(uint Id) { if (!UserBans.ContainsKey(Id)) return false; Boolean HASACTIVE = false; if (UserBans.ContainsKey(Id)) { if ((DateTime.Now - UserBans[Id]).TotalMinutes >= 5) { HASACTIVE = false; UserBans.Remove(Id); } else { HASACTIVE = true; } } return HASACTIVE; } internal Boolean HasRights(HabboData Habbo, bool OwnerShip) { if (Habbo == null) return false; if (OwnerShip) { if (GetRoom().Owner.ToLower() == Habbo.Username.ToLower()) return true; } else { if (GetRoom().Owner.ToLower() == Habbo.Username.ToLower() && !OwnerShip) return true; if (UsersWithRights.Contains(Habbo.Id) && !OwnerShip) return true; } return false; } internal RoomUser GetUserByHabboName(string Name) { foreach (RoomUser User in Users.Values.ToList()) { if (User.Habbo.Username.ToLower() == Name.ToLower()) { return User; } } return null; } internal Boolean HasUser(uint Id) { return Users.ContainsKey(Id); } internal Room GetRoom() { return DuckEnvironment.RoomManager.GetRoom(RoomId); } internal void UpdateVar(string Var, Object e) { using (IQueryAdapter Adapter = DuckEnvironment.GetAdapter()) { Adapter.runFastQuery("UPDATE private_rooms SET " + Var.ToLower() + " = '" + e + "' WHERE id = '" + RoomId + "' LIMIT 1"); } } internal void UpdateVar(string Var, Object e, bool Param) { using (IQueryAdapter Adapter = DuckEnvironment.GetAdapter()) { Adapter.setQuery("UPDATE private_rooms SET " + Var.ToLower() + " = @param WHERE id = '" + RoomId + "' LIMIT 1"); Adapter.addParameter("param", e); Adapter.runQuery(); } } internal void Dispose() { foreach (uint Id in Users.Keys) { GetRoom().RemoveUserFromRoom(Id, true); } Users = null; UsersWithRights = null; UserBans = null; Items = null; } } class AffectedTile { int mX; int mY; int mI; internal AffectedTile(int x, int y, int i) { mX = x; mY = y; mI = i; } internal int X { get { return mX; } } internal int Y { get { return mY; } } internal int I { get { return mI; } } } }