using System; using System.Text; using System.Collections.Generic; using System.Data; using Woodpecker.Core; using Woodpecker.Storage; using Woodpecker.Specialized.Text; using Woodpecker.Game.Users; using Woodpecker.Game.Users.Roles; using Woodpecker.Game.Rooms.Instances; namespace Woodpecker.Game.Rooms { /// /// Provides all kinds of functions for room (instances), room categories and the navigator. /// public class roomManager { #region Fields private Dictionary mRooms = new Dictionary(); /// /// The current amount of active room instances on the server. /// public int roomCount { get { return mRooms.Count; } } private Dictionary mModels = new Dictionary(); private Dictionary mCategories = new Dictionary(); #endregion #region Methods /// /// Initializes the room category informations and stores them in a persistent collection object for further reference. /// public void initRoomCategories() { Logging.Log("Initializing room categories..."); mCategories.Clear(); Database dbClient = new Database(true, true); if (dbClient.Ready) { foreach (DataRow dRow in dbClient.getTable("SELECT * FROM rooms_categories ORDER BY orderid ASC").Rows) { roomCategoryInformation pCategory = roomCategoryInformation.Parse(dRow); if (pCategory != null) mCategories.Add(pCategory.ID, pCategory); } } Logging.Log("Initialized " + mCategories.Count + " room categories."); } /// /// Initializes the room models and stores them in a persistent collection object for further reference. /// public void initRoomModels() { Logging.Log("Initializing room models..."); mModels.Clear(); Database dbClient = new Database(true, true); if (dbClient.Ready) { foreach (DataRow dRow in dbClient.getTable("SELECT * FROM rooms_models").Rows) { roomModel pModel = roomModel.Parse(dRow); if (pModel != null) mModels.Add(pModel.typeName, pModel); } } Logging.Log("Initialized " + mModels.Count + " room models."); } #region Database related #region Flat creating & deleting /// /// Creates a new user flat room by writing the given details in the 'rooms' table of the database. The new room's ID is returned upon success. /// /// The Woodpecker.Game.Rooms.roomInformation object containing the details of the new room. public int createFlat(roomInformation Details) { int roomID = 0; Database Database = new Database(false, false); Database.addParameterWithValue("roomname", Details.Name); Database.addParameterWithValue("ownerid", Details.ownerID); Database.addParameterWithValue("modeltype", Details.modelType); Database.addParameterWithValue("accesstype", ((int)Details.accessType).ToString()); Database.addParameterWithValue("showname", Details.showOwner.ToString().ToLower()); Database.Open(); if (Database.Ready) { Database.runQuery("INSERT INTO rooms(ownerid,roomname,modeltype,showname,accesstype) VALUES (@ownerid,@roomname,@modeltype,@showname,@accesstype)"); roomID = Database.getInteger("SELECT MAX(id) FROM rooms WHERE ownerid = @ownerid LIMIT 1"); Database.Close(); } return roomID; } /// /// Deletes a given user flat from the database, /// /// The database ID of the room to delete. public void deleteFlat(int roomID) { Database Database = new Database(false, false); Database.addParameterWithValue("roomid", roomID); Database.Open(); if (Database.Ready) { Database.runQuery("DELETE FROM rooms WHERE id = @roomid LIMIT 1"); Database.runQuery("DELETE FROM rooms_rights WHERE roomid = @roomid"); Database.Close(); } } #endregion #region Navigator /// /// Returns the total amount of existing user flats that a given user has created. /// /// The database ID of the user to get the room count of. /// public int getUserRoomCount(int userID) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.Open(); if (Database.Ready) return Database.getInteger("SELECT COUNT(id) FROM rooms WHERE ownerid = @ownerid"); else return int.MaxValue; // Never make a room in this case } /// /// Returns a List of the type roomCategoryInformation with all the available flat categories for a given user role. /// /// A value of the Woodpecker.Game.Users.Roles.userRole enum. public List getAvailableFlatCategories(userRole Role) { List Categories = new List(); foreach(roomCategoryInformation lCategory in mCategories.Values) { if (lCategory.userRoleCanPutFlat(Role)) Categories.Add(lCategory); } return Categories; } /// /// Returns the instance of a room category and updates the active user count in the category if neccessary. /// /// The database ID of the category to return. public roomCategoryInformation getRoomCategory(int ID) { if (mCategories.ContainsKey(ID)) { roomCategoryInformation pCategory = mCategories[ID]; pCategory.refreshUserCounts(); return pCategory; } else return null; } /// /// Returns a List of the type roomCategoryInformation with all the room categories in a given parent category (currently only one level deep) and updates the user amounts if neccessary. /// /// The database ID of the parent category to get the child categories of. /// public List getChildRoomCategories(int parentID) { List Categories = new List(); foreach (roomCategoryInformation lCategory in mCategories.Values) { if (lCategory.parentID == parentID) { lCategory.refreshUserCounts(); Categories.Add(lCategory); } } return Categories; } /// /// Returns a List of the type roomInformation with all the rooms in a given category. /// /// The database ID of the category to get the rooms of. /// /// public List getCategoryRooms(int categoryID, bool userFlats) { List Rooms = new List(); Database Database = new Database(false, true); Database.addParameterWithValue("category", categoryID); Database.Open(); if (Database.Ready) { DataTable dTable = null; if (userFlats) dTable = Database.getTable("SELECT rooms.*,users.username AS owner FROM rooms LEFT JOIN users ON (rooms.ownerid = users.id) WHERE rooms.category = @category ORDER BY id ASC,visitors_now DESC LIMIT 40"); else dTable = Database.getTable("SELECT * FROM rooms WHERE rooms.category = @category ORDER BY id ASC"); foreach (DataRow dRow in dTable.Rows) { Rooms.Add(roomInformation.Parse(dRow, userFlats)); } } return Rooms; } /// /// Tries to find a room with a given ID. If the room is found, a full roomInformation object is created and returned. If the room is not found, then null is returned. /// /// The database ID of the room to get the information of. public roomInformation getRoomInformation(int roomID) { if (mRooms.ContainsKey(roomID)) // Why load it? :) return mRooms[roomID].Information; Database Database = new Database(false, true); Database.addParameterWithValue("roomid", roomID); Database.Open(); if (Database.Ready) { DataRow dRow = Database.getRow("SELECT rooms.*,users.username AS owner FROM rooms LEFT JOIN users ON rooms.ownerid = users.id WHERE rooms.id = @roomid LIMIT 1"); return roomInformation.Parse(dRow, true); } else return null; } public roomInformation[] getFlatsForUser(userInformation User) { List Rooms = new List(); Database Database = new Database(false, true); Database.addParameterWithValue("ownerid", User.ID); Database.Open(); if (Database.Ready) { DataTable dTable = Database.getTable("SELECT rooms.*,users.username AS owner FROM rooms LEFT JOIN users ON (rooms.ownerid = users.id) WHERE ownerid = @ownerid"); foreach (DataRow dRow in dTable.Rows) { Rooms.Add(roomInformation.Parse(dRow, true)); } } return Rooms.ToArray(); } public roomInformation[] getUserFlatsSearchResult(string Criteria) { List Rooms = new List(); Database Database = new Database(false, true); Database.addParameterWithValue("criteria", Criteria + "%"); // Only search for rooms with names starting with the criteria Database.addParameterWithValue("owner", Criteria); // Also search for rooms who's ownername is equal to the criteria Database.Open(); if (Database.Ready) { DataTable dTable = Database.getTable("SELECT rooms.*,users.username AS owner FROM rooms LEFT JOIN users ON (rooms.ownerid = users.id) WHERE rooms.ownerid > 0 AND (users.username = @owner OR rooms.roomname LIKE @criteria) ORDER BY visitors_now DESC LIMIT 30"); foreach (DataRow dRow in dTable.Rows) { Rooms.Add(roomInformation.Parse(dRow, true)); } } return Rooms.ToArray(); } #endregion #region Room privileges /// /// Returns a boolean indicating if a given user owns a given room. /// /// The database ID of the user to check. /// The database ID of the room to check. public bool userOwnsRoom(int userID, int roomID) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.addParameterWithValue("roomid", roomID); Database.Open(); return Database.findsResult("SELECT id FROM rooms WHERE id = @roomid AND ownerid = @userid LIMIT 1"); } /// /// Returns a boolean indicating if a given user has room rights in a given room. /// /// The database ID of the user to check. /// The database ID of the room to check. public bool userHasRightsInRoom(int userID, int roomID) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.addParameterWithValue("roomid", roomID); Database.Open(); return Database.findsResult("SELECT roomid FROM rooms_rights WHERE roomid = @roomid AND userid = @userid LIMIT 1"); } /// /// Inserts room rights in a given room for a given user. /// /// The database ID of the room to assign the user rights to. /// The database ID of the user that gets the rights. public void addRoomRights(int roomID, int userID) { Database Database = new Database(false, true); Database.addParameterWithValue("roomid", roomID); Database.addParameterWithValue("userid", userID); Database.Open(); Database.runQuery("INSERT INTO rooms_rights(roomid,userid) VALUES (@roomid,@userid)"); } /// /// Clears all roomrights for a given room and updates the room instance. (if active) /// /// The database ID of the room to clear the rights of. public void removeRoomRights(int roomID) { Database Database = new Database(false, true); Database.addParameterWithValue("roomid", roomID); Database.Open(); Database.runQuery("DELETE FROM rooms_rights WHERE roomid = @roomid"); // TODO: refresh in room instance } /// /// Removes roomrights for a given user in a given room. /// /// The database ID of the room to remove the rights for the user of. /// The database ID of the user that gets the rights removed. public void removeRoomRights(int roomID, int userID) { Database Database = new Database(false, true); Database.addParameterWithValue("roomid", roomID); Database.addParameterWithValue("userid", userID); Database.Open(); Database.runQuery("DELETE FROM rooms_rights WHERE roomid = @roomid AND userid = @userid LIMIT 1"); // TODO: refresh in room instance } #endregion #region Favorite rooms /// /// Returns the amount of favorite rooms a given user has in his/her list as an integer. /// /// The database ID of the user to get the favorite room count of. public int getFavoriteRoomCount(int userID) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.Open(); return Database.getInteger("SELECT COUNT(id) FROM rooms_favorites WHERE userid = @userid"); } /// /// Returns the favorite rooms of a given user as a string. /// /// The userInformation object of the user to retrieve the favorite rooms for. public string getFavoriteRooms(userInformation User) { int guestRoomCount = 0; StringBuilder Rooms = new StringBuilder(); Database Database = new Database(false, true); Database.addParameterWithValue("userid", User.ID); Database.Open(); DataTable dTable = Database.getTable("SELECT rooms.*,users.username AS owner FROM rooms LEFT JOIN users ON rooms.ownerid = users.id WHERE rooms.id IN (SELECT roomid FROM rooms_favorites WHERE userid = @userid) ORDER BY rooms.id DESC LIMIT 30"); // User flats first foreach (DataRow dRow in dTable.Rows) { roomInformation Room = roomInformation.Parse(dRow, true); if (Room.isUserFlat) guestRoomCount++; Rooms.Append(Room.ToString(User)); } fuseStringBuilder FSB = new fuseStringBuilder(); FSB.appendWired(guestRoomCount); FSB.Append(Rooms.ToString()); return FSB.ToString(); } /// /// Adds a given room to a given user's favorite room list. /// /// The database ID of the user to modify the list for. /// The database ID of the room to add to the user's favorite list. public void addFavoriteRoom(int userID, int roomID) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.addParameterWithValue("roomid", roomID); Database.Open(); if (Database.Ready) Database.runQuery("INSERT INTO rooms_favorites(userid,roomid) VALUES (@userid,@roomid)"); } /// /// Removes a given room to a given user's favorite room list. /// /// The database ID of the user to modify the list for. /// The database ID of the room to remove to the user's favorite list. public void removeFavoriteRoom(int userID, int roomID) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.addParameterWithValue("roomid", roomID); Database.Open(); if (Database.Ready) Database.runQuery("DELETE FROM rooms_favorites WHERE userid = @userid AND roomid = @roomid LIMIT 1"); } /// /// Removes all records in user favorite room lists that refer to non-existing rooms. (eg, deleted etc) /// public void dropInvalidFavoriteRoomEntries() { Database Database = new Database(true, true); if (Database.Ready) Database.runQuery("DELETE FROM rooms_favorites WHERE NOT(rooms_favorites.roomid) IN(SELECT rooms.id FROM rooms)"); } #endregion #endregion #region Room models related public roomModel getModel(string Type) { if (!mModels.ContainsKey(Type)) // Not initialized yet { Database Database = new Database(false, true); Database.addParameterWithValue("modeltype", Type); Database.Open(); if (Database.Ready) { DataRow dRow = Database.getRow("SELECT * FROM rooms_models WHERE modeltype = @modeltype"); if (dRow != null) { roomModel New = roomModel.Parse(dRow); if (New == null || dRow["modeltype"].ToString() != Type) // Not found / invalid case { Logging.Log("Room model '" + Type + "' was found but contained invalid data.", Logging.logType.commonWarning); return null; } else mModels.Add(Type, New); } else { Logging.Log("The requested room model '" + Type + "' was not found in the 'rooms_models' table of the database!", Logging.logType.commonWarning); return null; } } Logging.Log("Room model '" + Type + "' is initialized and added to cache.", Logging.logType.roomInstanceEvent); } return mModels[Type]; } #endregion #region Room instances related /// /// Returns true if the given room has an instance running. /// /// The database ID of the room to check. public bool roomInstanceRunning(int roomID) { return mRooms.ContainsKey(roomID); } /// /// Attempts to destroy the instance of a room given by ID. /// /// The database ID of the room to attempt to stop the instance of. public void destroyRoomInstance(int roomID) { if (mRooms.ContainsKey(roomID)) { mRooms[roomID].Destroy(); mRooms.Remove(roomID); Logging.Log("Room instance of room " + roomID + " has successfully been destroyed.", Logging.logType.roomInstanceEvent); } } /// /// Returns the room instance of a room given by ID. If the room instance is already running, the instance is returned, if not, then the room instance is initialized and returned. /// /// The database ID to return the room instance of. public roomInstance getRoomInstance(int roomID) { if (!mRooms.ContainsKey(roomID)) mRooms.Add(roomID, new roomInstance(roomID)); return mRooms[roomID]; } /// /// Unloads and disposes all active room instances with no active users in them. /// public void destroyInactiveRoomInstances() { List roomIDs = new List(); lock (mRooms) { foreach (roomInstance lInstance in mRooms.Values) { if (lInstance.userAmount == 0 && lInstance.Information != null) { roomIDs.Add(lInstance.roomID); } } } foreach (int lRoomID in roomIDs) { this.destroyRoomInstance(lRoomID); } } /// /// Updates the current amount of visitors in a given room instance in the database. /// /// The database ID of the room to update. /// The up to date amount of users in the instance of the given room. public void updateRoomUserAmount(int roomID, int userAmount) { Database Database = new Database(false, true); Database.addParameterWithValue("roomid", roomID); Database.addParameterWithValue("useramount", userAmount); Database.Open(); if (Database.Ready) Database.runQuery("UPDATE rooms SET visitors_now = @useramount WHERE id = @roomid LIMIT 1"); } /// /// Resets the amount of users for every room in the database to 0. /// public void resetRoomUserAmounts() { Database Database = new Database(true, true); if (Database.Ready) { Database.runQuery("UPDATE rooms SET visitors_now = '0'"); Logging.Log("Current visitor amounts of rooms set to 0."); } } #endregion #endregion } }