Guest User

Untitled

a guest
Dec 19th, 2016
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.50 KB | None | 0 0
  1. /**
  2. * The Forgotten Server - a free and open-source MMORPG server emulator
  3. * Copyright (C) 2015 Mark Samman <mark.samman@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19.  
  20. #include "otpch.h"
  21.  
  22. #include "store.h"
  23.  
  24. #include "pugicast.h"
  25. #include "database.h"
  26.  
  27. StoreOffer& StoreCategory::createOffer(uint32_t offerId)
  28. {
  29. offers.emplace_back(offerId);
  30. return offers.back();
  31. }
  32.  
  33. Store::Store()
  34. {
  35. loaded = false;
  36. runningId = 0;
  37. }
  38.  
  39. void Store::getTransactionHistory(uint32_t accountId, uint16_t page, uint32_t entriesPerPage, std::vector<StoreTransaction>& out) const
  40. {
  41. Database* db = Database::getInstance();
  42.  
  43. std::ostringstream query;
  44. query << "SELECT `id`, `coins`, `description`, `timestamp` FROM `store_history` WHERE `account_id` = " << accountId << " ORDER BY `timestamp` DESC LIMIT " << entriesPerPage + 1 << " OFFSET " << (page * entriesPerPage);
  45.  
  46. DBResult_ptr result = db->storeQuery(query.str());
  47. if (result) {
  48. do {
  49. out.emplace_back(result->getNumber<uint32_t>("id"), result->getNumber<int32_t>("coins"), result->getString("description"), result->getNumber<time_t>("timestamp"));
  50. } while (result->next());
  51. }
  52. }
  53.  
  54. void Store::onTransactionCompleted(uint32_t accountId, int32_t coins, const std::string& description) const
  55. {
  56. Database* db = Database::getInstance();
  57.  
  58. std::ostringstream query;
  59. query << "INSERT INTO `store_history` (`account_id`, `coins`, `description`, `timestamp`) VALUES (" << accountId << "," << coins << "," << db->escapeString(description) << "," << time(nullptr) << ")";
  60.  
  61. db->executeQuery(query.str());
  62. }
  63.  
  64. bool Store::loadFromXml(bool /*reloading = false*/)
  65. {
  66. pugi::xml_document doc;
  67. pugi::xml_parse_result result = doc.load_file("data/store/store.xml");
  68. if (!result) {
  69. printXMLError("Error - Store::loadFromXml", "data/store/store.xml", result);
  70. return false;
  71. }
  72.  
  73. loaded = true;
  74.  
  75. std::string name;
  76. std::string description;
  77. StringVec icons;
  78.  
  79. for (auto categoryNode : doc.child("store").children()) {
  80. pugi::xml_attribute attr;
  81.  
  82. name.clear();
  83. description.clear();
  84. icons.clear();
  85.  
  86. if ((attr = categoryNode.attribute("name"))) {
  87. name = attr.as_string();
  88. } else {
  89. std::cout << "[Error - Store::loadFromXml] Missing category name." << std::endl;
  90. continue;
  91. }
  92.  
  93. if ((attr = categoryNode.attribute("description"))) {
  94. description = attr.as_string();
  95. }
  96.  
  97. if ((attr = categoryNode.attribute("icons"))) {
  98. icons = explodeString(attr.as_string(), ";");
  99. }
  100.  
  101. categories.emplace_back(name, description, icons);
  102. StoreCategory& category = categories.back();
  103.  
  104. for (auto offerNode : categoryNode.children()) {
  105. StoreOffer& offer = category.createOffer(runningId++);
  106.  
  107. if ((attr = offerNode.attribute("name"))) {
  108. offer.name = attr.as_string();
  109. } else {
  110. std::cout << "[Error - Store::loadFromXml] Missing offer name in category: " << category.name << std::endl;
  111. category.offers.pop_back();
  112. continue;
  113. }
  114.  
  115. if ((attr = offerNode.attribute("description"))) {
  116. offer.description = attr.as_string();
  117. }
  118.  
  119. if ((attr = offerNode.attribute("message"))) {
  120. offer.message = attr.as_string();
  121. }
  122.  
  123. if ((attr = offerNode.attribute("icons"))) {
  124. offer.icons = explodeString(attr.as_string(), ";");
  125. }
  126.  
  127. if ((attr = offerNode.attribute("price"))) {
  128. offer.price = attr.as_uint();
  129. }
  130.  
  131. for (auto subOfferNode : offerNode.children()) {
  132. name.clear();
  133. description.clear();
  134. icons.clear();
  135.  
  136. if ((attr = subOfferNode.attribute("name"))) {
  137. name = attr.as_string();
  138. }
  139.  
  140. if ((attr = subOfferNode.attribute("description"))) {
  141. description = attr.as_string();
  142. }
  143.  
  144. if ((attr = subOfferNode.attribute("icons"))) {
  145. icons = explodeString(attr.as_string(), ";");
  146. }
  147.  
  148. offer.subOffers.push_back(SubOffer(name, description, icons));
  149. }
  150.  
  151. if ((attr = offerNode.attribute("script"))) {
  152. if (!scriptInterface) {
  153. scriptInterface.reset(new LuaScriptInterface("Store Interface"));
  154. scriptInterface->initState();
  155. }
  156.  
  157. std::string script = attr.as_string();
  158. if (scriptInterface->loadFile("data/store/scripts/" + script) == 0) {
  159. offer.scriptInterface = scriptInterface.get();
  160. offer.renderEvent = scriptInterface->getEvent("onRender");
  161. offer.buyEvent = scriptInterface->getEvent("onBuy");
  162. } else {
  163. std::cout << "[Warning - Store::loadFromXml] Can not load script: " << script << std::endl;
  164. std::cout << scriptInterface->getLastLuaError() << std::endl;
  165. }
  166. }
  167. }
  168. }
  169.  
  170. return true;
  171. }
  172.  
  173. bool Store::reload()
  174. {
  175. categories.clear();
  176.  
  177. loaded = false;
  178.  
  179. scriptInterface.reset();
  180.  
  181. return loadFromXml(true);
  182. }
  183.  
  184. boost::optional<StoreOffer&> Store::getOfferById(uint32_t id)
  185. {
  186. for (auto& category : getCategories()) {
  187. for (auto& offer : category.getOffers()) {
  188. if (offer.getId() == id) {
  189. return boost::optional<StoreOffer&>(offer);
  190. }
  191. }
  192. }
  193.  
  194. return boost::optional<StoreOffer&>();
  195. }
  196.  
  197. bool Store::executeOnRender(Player* player, StoreOffer* offer)
  198. {
  199. if (offer->renderEvent != -1) {
  200. // onRender(player, offer)
  201. LuaScriptInterface* scriptInterface = offer->scriptInterface;
  202. if (!scriptInterface->reserveScriptEnv()) {
  203. std::cout << "[Error - Store::executeOnRender] Call stack overflow" << std::endl;
  204. return false;
  205. }
  206.  
  207. ScriptEnvironment* env = scriptInterface->getScriptEnv();
  208. env->setScriptId(offer->renderEvent, scriptInterface);
  209.  
  210. lua_State* L = scriptInterface->getLuaState();
  211. scriptInterface->pushFunction(offer->renderEvent);
  212.  
  213. LuaScriptInterface::pushUserdata<Player>(L, player);
  214. LuaScriptInterface::setMetatable(L, -1, "Player");
  215.  
  216. LuaScriptInterface::pushUserdata<StoreOffer>(L, offer);
  217. LuaScriptInterface::setMetatable(L, -1, "StoreOffer");
  218.  
  219. return scriptInterface->callFunction(2);
  220. }
  221.  
  222. return false;
  223. }
  224.  
  225. bool Store::executeOnBuy(Player* player, StoreOffer* offer, const std::string& param)
  226. {
  227. if (offer->buyEvent != -1) {
  228. // onBuy(player, offer, param)
  229. LuaScriptInterface* scriptInterface = offer->scriptInterface;
  230. if (!scriptInterface->reserveScriptEnv()) {
  231. std::cout << "[Error - Store::executeOnBuy] Call stack overflow" << std::endl;
  232. return false;
  233. }
  234.  
  235. ScriptEnvironment* env = scriptInterface->getScriptEnv();
  236. env->setScriptId(offer->buyEvent, scriptInterface);
  237.  
  238. lua_State* L = scriptInterface->getLuaState();
  239. scriptInterface->pushFunction(offer->buyEvent);
  240.  
  241. LuaScriptInterface::pushUserdata<Player>(L, player);
  242. LuaScriptInterface::setMetatable(L, -1, "Player");
  243.  
  244. LuaScriptInterface::pushUserdata<StoreOffer>(L, offer);
  245. LuaScriptInterface::setMetatable(L, -1, "StoreOffer");
  246.  
  247. if (param.size() == 0) {
  248. lua_pushnil(L);
  249. } else {
  250. LuaScriptInterface::pushString(L, param);
  251. }
  252.  
  253. return scriptInterface->callFunction(3);
  254. }
  255.  
  256. return false;
  257. }
Add Comment
Please, Sign In to add comment