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