Fortera Global
Intermediate OT User
- Joined
- Nov 20, 2015
- Messages
- 1,182
- Solutions
- 2
- Reaction score
- 117
Hello, I want help (How to fix this? )...
tfs 1.2 protocol 10.99+
Without any offer in store :
1- Can open Store [ ok ]
2- Can transfer coins [ ok ]
3- Can view history [ debbug ]
With offer in store:
1- Can open Store [ debbug ]
Codes:
store.cpp
tfs 1.2 protocol 10.99+
Without any offer in store :
1- Can open Store [ ok ]
2- Can transfer coins [ ok ]
3- Can view history [ debbug ]
With offer in store:
1- Can open Store [ debbug ]
Codes:
Code:
void ProtocolGame::parseStoreOpen()
{
return sendStore();
}
void ProtocolGame::parseStoreSelectCategory(NetworkMessage& msg)
{
std::string categoryName = msg.getString();
for (auto& category : g_store->getCategories()) {
if (category.getName() == categoryName) {
return g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreOffers, getThis(), category)));
}
}
}
void ProtocolGame::parseStoreBuyOffer(NetworkMessage& msg)
{
uint32_t offerId = msg.get<uint32_t>();
StoreOfferType_t offerType = static_cast<StoreOfferType_t>(msg.getByte());
std::string param;
if (offerType == STORE_OFFERTYPE_NAMECHANGE) {
param = msg.getString();
}
auto offer = g_store->getOfferById(offerId);
if (!offer) {
sendStoreError(STORE_ERROR_PURCHASE, "Offer not found. Please reopen the store and try again.");
return;
}
if ((strcasecmp(offer->getName().c_str(), "name change") == 0) && offerType != STORE_OFFERTYPE_NAMECHANGE) {
requestPurchaseData(offerId, STORE_OFFERTYPE_NAMECHANGE);
return;
}
addGameTask(&Game::playerPurchaseStoreOffer, player->getID(), offerId, param);
}
void ProtocolGame::parseStoreOpenHistory(NetworkMessage& msg)
{
storeHistoryEntriesPerPage = msg.getByte();
g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreHistory, getThis(), 0, storeHistoryEntriesPerPage)));
}
void ProtocolGame::parseStoreRequestHistory(NetworkMessage& msg)
{
uint16_t page = msg.get<uint16_t>();
g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreHistory, getThis(), page, storeHistoryEntriesPerPage)));
}
void ProtocolGame::parseTransferCoins(NetworkMessage& msg)
{
std::string recipient = msg.getString();
uint16_t amount = msg.get<uint16_t>();
addGameTask(&Game::playerTransferCoins, player->getID(), recipient, amount);
}
store.cpp
Code:
/**
* The Forgotten Server - a free and open-source MMORPG server emulator
* Copyright (C) 2015 Mark Samman <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "otpch.h"
#include "store.h"
#include "pugicast.h"
#include "database.h"
StoreOffer& StoreCategory::createOffer(uint32_t offerId)
{
offers.emplace_back(offerId);
return offers.back();
}
Store::Store()
{
loaded = false;
runningId = 0;
}
void Store::getTransactionHistory(uint32_t accountId, uint16_t page, uint32_t entriesPerPage, std::vector<StoreTransaction>& out) const
{
Database* db = Database::getInstance();
std::ostringstream query;
query << "SELECT `id`, `coins`, `description`, `timestamp` FROM `store_history` WHERE `account_id` = " << accountId << " ORDER BY `timestamp` DESC LIMIT " << entriesPerPage + 1 << " OFFSET " << (page * entriesPerPage);
DBResult_ptr result = db->storeQuery(query.str());
if (result) {
do {
out.emplace_back(result->getNumber<uint32_t>("id"), result->getNumber<int32_t>("coins"), result->getString("description"), result->getNumber<time_t>("timestamp"));
} while (result->next());
}
}
void Store::onTransactionCompleted(uint32_t accountId, int32_t coins, const std::string& description) const
{
Database* db = Database::getInstance();
std::ostringstream query;
query << "INSERT INTO `store_history` (`account_id`, `coins`, `description`, `timestamp`) VALUES (" << accountId << "," << coins << "," << db->escapeString(description) << "," << time(nullptr) << ")";
db->executeQuery(query.str());
}
bool Store::loadFromXml(bool /*reloading = false*/)
{
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("data/store/store.xml");
if (!result) {
printXMLError("Error - Store::loadFromXml", "data/store/store.xml", result);
return false;
}
loaded = true;
std::string name;
std::string description;
StringVec icons;
for (auto categoryNode : doc.child("store").children()) {
pugi::xml_attribute attr;
name.clear();
description.clear();
icons.clear();
if ((attr = categoryNode.attribute("name"))) {
name = attr.as_string();
} else {
std::cout << "[Error - Store::loadFromXml] Missing category name." << std::endl;
continue;
}
if ((attr = categoryNode.attribute("description"))) {
description = attr.as_string();
}
if ((attr = categoryNode.attribute("icons"))) {
icons = explodeString(attr.as_string(), ";");
}
categories.emplace_back(name, description, icons);
StoreCategory& category = categories.back();
for (auto offerNode : categoryNode.children()) {
StoreOffer& offer = category.createOffer(runningId++);
if ((attr = offerNode.attribute("name"))) {
offer.name = attr.as_string();
} else {
std::cout << "[Error - Store::loadFromXml] Missing offer name in category: " << category.name << std::endl;
category.offers.pop_back();
continue;
}
if ((attr = offerNode.attribute("description"))) {
offer.description = attr.as_string();
}
if ((attr = offerNode.attribute("message"))) {
offer.message = attr.as_string();
}
if ((attr = offerNode.attribute("icons"))) {
offer.icons = explodeString(attr.as_string(), ";");
}
if ((attr = offerNode.attribute("price"))) {
offer.price = attr.as_uint();
}
for (auto subOfferNode : offerNode.children()) {
name.clear();
description.clear();
icons.clear();
if ((attr = subOfferNode.attribute("name"))) {
name = attr.as_string();
}
if ((attr = subOfferNode.attribute("description"))) {
description = attr.as_string();
}
if ((attr = subOfferNode.attribute("icons"))) {
icons = explodeString(attr.as_string(), ";");
}
offer.subOffers.push_back(SubOffer(name, description, icons));
}
if ((attr = offerNode.attribute("script"))) {
if (!scriptInterface) {
scriptInterface.reset(new LuaScriptInterface("Store Interface"));
scriptInterface->initState();
}
std::string script = attr.as_string();
if (scriptInterface->loadFile("data/store/scripts/" + script) == 0) {
offer.scriptInterface = scriptInterface.get();
offer.renderEvent = scriptInterface->getEvent("onRender");
offer.buyEvent = scriptInterface->getEvent("onBuy");
} else {
std::cout << "[Warning - Store::loadFromXml] Can not load script: " << script << std::endl;
std::cout << scriptInterface->getLastLuaError() << std::endl;
}
}
}
}
return true;
}
bool Store::reload()
{
categories.clear();
loaded = false;
scriptInterface.reset();
return loadFromXml(true);
}
boost::optional<StoreOffer&> Store::getOfferById(uint32_t id)
{
for (auto& category : getCategories()) {
for (auto& offer : category.getOffers()) {
if (offer.getId() == id) {
return boost::optional<StoreOffer&>(offer);
}
}
}
return boost::optional<StoreOffer&>();
}
bool Store::executeOnRender(Player* player, StoreOffer* offer)
{
if (offer->renderEvent != -1) {
// onRender(player, offer)
LuaScriptInterface* scriptInterface = offer->scriptInterface;
if (!scriptInterface->reserveScriptEnv()) {
std::cout << "[Error - Store::executeOnRender] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface->getScriptEnv();
env->setScriptId(offer->renderEvent, scriptInterface);
lua_State* L = scriptInterface->getLuaState();
scriptInterface->pushFunction(offer->renderEvent);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<StoreOffer>(L, offer);
LuaScriptInterface::setMetatable(L, -1, "StoreOffer");
return scriptInterface->callFunction(2);
}
return false;
}
bool Store::executeOnBuy(Player* player, StoreOffer* offer, const std::string& param)
{
if (offer->buyEvent != -1) {
// onBuy(player, offer, param)
LuaScriptInterface* scriptInterface = offer->scriptInterface;
if (!scriptInterface->reserveScriptEnv()) {
std::cout << "[Error - Store::executeOnBuy] Call stack overflow" << std::endl;
return false;
}
ScriptEnvironment* env = scriptInterface->getScriptEnv();
env->setScriptId(offer->buyEvent, scriptInterface);
lua_State* L = scriptInterface->getLuaState();
scriptInterface->pushFunction(offer->buyEvent);
LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");
LuaScriptInterface::pushUserdata<StoreOffer>(L, offer);
LuaScriptInterface::setMetatable(L, -1, "StoreOffer");
if (param.size() == 0) {
lua_pushnil(L);
} else {
LuaScriptInterface::pushString(L, param);
}
return scriptInterface->callFunction(3);
}
return false;
}
Last edited by a moderator: