using System; using System.Data; using System.Collections.Generic; using Woodpecker.Core; using Woodpecker.Storage; using Woodpecker.Sessions; using Woodpecker.Net.Game.Messages; using Woodpecker.Game.Users.Roles; using Woodpecker.Game.Items; using Woodpecker.Game.Items.Pets; namespace Woodpecker.Game.Store { public class storeManager { #region Fields /// /// A Dictionary collection holding the storeCataloguePage objects representing the pages of the virtual item shop, the indexname of the page is the key of the collection entries. /// private Dictionary Pages; /// /// A Dictionary collection holding the storeCatalogueSale objects representing the sales of the virtual item shop, the salecode is the key of the collection entries. /// private Dictionary Sales; /// /// A string array with the attribute names for every page. This field is read only. /// private readonly string[] pageAttributes = new string[] { "name_index", "name", "layout", "label_pick", "img_headline", "img_teasers", "body", "label_extra_s" }; #endregion #region Methods #region User credit log etc /// /// Writes a new row in the users_creditlog table of the database, with the user ID of a user, the type of purchase/action and the activity. (+100, -100 etc) The current datetime is inserted aswell. This record can be viewed by the user via the 'Transactions' button in the Purse. /// /// The database ID of the user to log the action for. /// The type of the action. (win_voucher, club_habbo etc) /// The activity of the action. (+100, -100 etc) public void logTransaction(int userID, string Type, int Activity) { Database Database = new Database(false, true); Database.addParameterWithValue("userid", userID); Database.addParameterWithValue("type", Type); Database.addParameterWithValue("activity", Activity); Database.Open(); if (Database.Ready) { Database.runQuery("INSERT INTO users_creditlog(userid,moment,type,activity) VALUES (@userid,NOW(),@type,@activity)"); } } /// /// Gets the transactions (credit log) of a user on given user session and sends it to the session's game connection. /// /// The Woodpecker.Sessions.Session object to get the transaction for and to send the message to. public void sendTransactions(ref Session Session) { if (Session.User == null) return; serverMessage Message = new serverMessage(209); // "CQ" Database Database = new Database(false, true); Database.addParameterWithValue("userid", Session.User.ID); Database.Open(); if (Database.Ready) { DataTable creditLogData = Database.getTable("SELECT moment,type,activity FROM users_creditlog WHERE userid = @userid LIMIT 50"); foreach (DataRow dRow in creditLogData.Rows) { DateTime Moment = (DateTime)dRow["moment"]; Message.appendTabbedValue(Moment.ToString("dd/MM/yyyy")); Message.appendTabbedValue(Moment.ToString("hh:mm")); Message.appendTabbedValue(dRow["activity"].ToString()); Message.appendTabbedValue("0"); Message.appendTabbedValue(""); Message.Append(dRow["type"].ToString()); Message.appendChar(13); } } Session.gameConnection.sendMessage(Message); } /// /// Tries to redeem a credit/item voucher for a user session. /// /// The Woodpecker.Sessions.Session object to redeem the voucher with. /// The vouchercode the user entered. public void redeemVoucher(ref Session Session, string Code) { serverMessage Response = new serverMessage(); Database Database = new Database(false, false); Database.addParameterWithValue("code", Code); Database.Open(); if (Database.Ready) { DataRow dRow = Database.getRow("SELECT type,value FROM users_vouchers WHERE code = @code AND ISNULL(redeemer_userid)"); if (dRow != null) // Voucher found { // Mark voucher as redeemed Database.addParameterWithValue("userid", Session.User.ID); Database.runQuery("UPDATE users_vouchers SET redeemer_userid = @userid WHERE code = @code"); Database.Close(); string Type = (string)dRow["type"]; if (Type == "credits") { int Credits = int.Parse(dRow["value"].ToString()); Session.User.Credits += Credits; Session.User.updateValueables(); this.logTransaction(Session.User.ID, "win_voucher", Credits); Session.refreshCredits(); } else if (Type == "item") { string[] Items = ((string)dRow["value"]).Split(';'); } // Success! Response.Initialize(212); // "CT" Session.gameConnection.sendMessage(Response); return; } else { // Error 1! (not found) Response.Initialize(213); // "CU" Response.Append(1); } Session.gameConnection.sendMessage(Response); } } public bool purchaseSubscription(ref Session Session, string Subscription, int Choice) { if (Subscription != "club_habbo") return false; int Cost = 0; int Months = 0; if (Choice == 1) { Cost = 25; Months = 1; } else if (Choice == 2) { Cost = 60; Months = 3; } else if (Choice == 3) { Cost = 105; Months = 6; } else return false; if (Cost > Session.User.Credits) return false; else { for (int i = 1; i <= Months; i++) { if (Session.User.clubDaysLeft == 0) Session.User.clubDaysLeft = 31; else Session.User.clubMonthsLeft++; } this.logTransaction(Session.User.ID, "club_habbo", -Cost); Session.User.Credits -= Cost; Session.User.updateValueables(); Session.User.updateClub(true); return true; } } #endregion #region Item store /// /// Initializes the sales sold in the catalogue. /// public void loadSales() { if (this.Sales != null) this.Sales.Clear(); this.Sales = new Dictionary(); Database dbClient = new Database(true, false); if (dbClient.Ready) { foreach (DataRow dSale in dbClient.getTable("SELECT * FROM store_catalogue_sales").Rows) { storeCatalogueSale pSale = new storeCatalogueSale((string)dSale["salecode"], (int)dSale["price"]); // Create blank sale object bool isPackage = ( (dSale["ispackage"].ToString() == "true") && dSale["package_name"] != DBNull.Value && dSale["package_description"] != DBNull.Value); if (isPackage) { pSale.setPackage((string)dSale["package_name"], (string)dSale["package_description"]); foreach (DataRow dPackageItem in dbClient.getTable("SELECT definitionid,amount,specialspriteid FROM store_catalogue_sales_packages WHERE salecode = '" + pSale.saleCode + "'").Rows) { itemDefinition pItemDefinition = Engine.Game.Items.getItemDefinition((int)dPackageItem["definitionid"]); if (pItemDefinition != null) pSale.addPackageItem(pItemDefinition, (int)dPackageItem["amount"], (int)dPackageItem["specialspriteid"]); } } else { itemDefinition pItemDefinition = Engine.Game.Items.getItemDefinition((int)dSale["item_definitionid"]); if (pItemDefinition != null) pSale.setItem(pItemDefinition, (int)dSale["item_specialspriteid"]); } this.Sales.Add(pSale.saleCode, pSale); } dbClient.Close(); } } /// /// Initializes the store catalogue pages. /// public void loadCataloguePages() { Database dbClient = new Database(true, true); if (!dbClient.Ready) { Logging.Log("Failed to load store catalogue pages, database was not contactable!", Logging.logType.commonError); return; } this.Pages = new Dictionary(); // New collection foreach (DataRow pageData in dbClient.getTable("SELECT * FROM store_catalogue_pages ORDER BY orderid ASC").Rows) { storeCataloguePage pPage = new storeCataloguePage(); pPage.ID = (int)pageData["id"]; pPage.setMinimumAccessRole(Engine.Game.Roles.parseRoleFromString(pageData["minrole"].ToString())); // Set attributes for page foreach(string szAttribute in this.pageAttributes) pPage.setAttribute(szAttribute, pageData[szAttribute]); if (pageData["label_extra_t"] != DBNull.Value) { bool skip = false; string[] extraTypedData = pageData["label_extra_t"].ToString().Split(Environment.NewLine.ToCharArray()); foreach (string szTypedData in extraTypedData) { if (!skip) { string ID = szTypedData.Substring(0, szTypedData.IndexOf(':')); string szData = szTypedData.Substring(ID.ToString().Length + 1); pPage.setAttribute("label_extra_t_" + ID, szData); } skip = !skip; } } pPage.initializeSales(); this.Pages.Add(pPage.getStringAttribute("name_index"), pPage); } } /// /// Tries to return the storeCataloguePage of a given page ID. If the page isn't found in the collection, then null is returned. /// /// The database ID of the catalogue page to retrieve. /// public storeCataloguePage getCataloguePage(int pageID) { if (this.Pages != null) { foreach(storeCataloguePage lPage in this.Pages.Values) { if (lPage.ID == pageID) return lPage; } } return null; } /// /// Tries to return the storeCataloguePage of a given page index name. If the page isn't found in the collection, then null is returned. /// /// The index name of the storeCataloguePage to retrieve. public storeCataloguePage getCataloguePage(string indexName) { if (this.Pages != null && this.Pages.ContainsKey(indexName)) return this.Pages[indexName]; else return null; } /// /// Returns an array of the type storeCataloguePage with all the catalogue pages in the virtual store. /// /// public storeCataloguePage[] getCataloguePages() { storeCataloguePage[] tmp = new storeCataloguePage[this.Pages.Count]; this.Pages.Values.CopyTo(tmp, 0); return tmp; } /// /// Returns the storeCatalogueSale object of a given sale code. If the sale is not found, then null is returned. /// /// The sale code of the sale to retrieve. public storeCatalogueSale getSale(string saleCode) { try { return this.Sales[saleCode]; } catch { return null; } } public void requestSaleShipping(int receivingUserID, string saleCode, bool isNewPurchase, bool purchaseAsPresent, string presentNote, string customData) { storeCatalogueSale pSale = this.getSale(saleCode); if (pSale == null) { Logging.Log("Failed to purchase sale '" + saleCode + "' for user " + receivingUserID + ", the requested sale ('" + saleCode + "') was not found!", Logging.logType.commonWarning); return; } List shippedItems = new List(); if (purchaseAsPresent) { stripItem presentBox = this.createPresent(receivingUserID, saleCode, presentNote, customData); if (presentBox != null) shippedItems.Add(presentBox); else return; } else { int itemIdOffset = Engine.Game.Items.getItemIdOffset(); foreach (stripItem lItem in pSale.getItemInstances()) { lItem.ID = ++itemIdOffset; lItem.ownerID = receivingUserID; #region Special events upon purchase if (lItem.Definition.Behaviour.isTeleporter) // Teleporter, create linking teleporter { stripItem Teleporter2 = new stripItem(); Teleporter2.ID = ++itemIdOffset; Teleporter2.ownerID = receivingUserID; Teleporter2.Definition = lItem.Definition; Teleporter2.teleporterID = lItem.ID; lItem.teleporterID = Teleporter2.ID; shippedItems.Add(Teleporter2); } else if (lItem.Definition.Behaviour.isPostIt) { lItem.customData = "20"; } else if (lItem.Definition.Behaviour.isDecoration || lItem.Definition.Behaviour.isPrizeTrophy) { lItem.customData = customData; } else if (lItem.Definition.Behaviour.isRedeemable) { int creditValue = 0; if (int.TryParse(lItem.Definition.Sprite.Split('_')[1], out creditValue)) lItem.customData = creditValue.ToString(); } else if (lItem.Definition.Sprite == "nest") { string[] petData = customData.Split(Convert.ToChar(2)); string Name = petData[0]; char Type = char.Parse(petData[1]); byte Race = byte.Parse(petData[2]); string Color = petData[3]; Engine.Game.Items.createPet(lItem.ID, Name, Type, Race, Color); } #endregion shippedItems.Add(lItem); } Engine.Game.Items.createItemInstances(shippedItems); } Session Receiver = Engine.Game.Users.getUserSession(receivingUserID); if (Receiver != null) // Receiver was online { Receiver.itemStripHandler.addHandItems(shippedItems); serverMessage Notification = new serverMessage(); if (isNewPurchase) { Notification.Initialize(67); // "AC" } else #region Open as present box { stripItem displayItem = shippedItems[0]; Notification.Initialize(129); // "BA" Notification.appendNewLineValue(displayItem.Definition.Sprite); string displaySprite = displayItem.Definition.Sprite; //if (displayItem.Definition.isPartialSprite && displayItem.customData != null) // displaySprite += " " + displayItem.customData; Notification.appendNewLineValue(displaySprite); if (!displayItem.Definition.Behaviour.isWallItem) { Notification.appendStripValue(displayItem.Definition.Length.ToString()); Notification.appendStripValue(displayItem.Definition.Width.ToString()); Notification.appendStripValue(displayItem.Definition.Color); } } #endregion Receiver.gameConnection.sendMessage(Notification); } } public void openPresent(int presentID, int userID) { Database dbClient = new Database(false, true); dbClient.addParameterWithValue("presentid", presentID); dbClient.Open(); if (dbClient.Ready) { DataRow dRow = dbClient.getRow( "SELECT salecode,customdata FROM items_presents WHERE presentid = @presentid LIMIT 1;" + "DELETE FROM items_presents WHERE presentid = @presentid LIMIT 1;"); if (dRow != null) // Present found { string saleCode = (string)dRow["salecode"]; string customData = null; if(dRow["customdata"] != DBNull.Value) customData = (string)dRow["customdata"]; requestSaleShipping(userID, saleCode, false, false, null, customData); } } } public stripItem createPresent(int receivingUserID, string saleCode, string Note, string customData) { int definitionID = Engine.Game.Items.getRandomPresentBoxDefinitionID(); if (definitionID != 1) { stripItem presentBoxItem = Engine.Game.Items.createItemInstance(definitionID, receivingUserID, "!" + Note); Database dbClient = new Database(false, true); dbClient.addParameterWithValue("itemid", presentBoxItem.ID); dbClient.addParameterWithValue("salecode", saleCode); if (customData == "") dbClient.addParameterWithValue("customdata", DBNull.Value); else dbClient.addParameterWithValue("customdata", customData); dbClient.Open(); if (dbClient.Ready) dbClient.runQuery("INSERT INTO items_presents VALUES (@itemid,@salecode,@customdata)"); return presentBoxItem; } else { Logging.Log("Failed to create presentbox for sale '" + saleCode + "', one of the present box definitions is missing!", Logging.logType.commonError); return null; } } public void deliverItemsToSession(int userID, List Items, bool Refresh) { Session Receiver = Engine.Game.Users.getUserSession(userID); if (Receiver != null) // Receiver was online { Receiver.itemStripHandler.addHandItems(Items); if (Refresh) { serverMessage Message = new serverMessage(101); // "Ae" Receiver.gameConnection.sendMessage(Message); } } } #endregion #endregion } }