raderde 1
raderde
Cannn6161 1
Cannn6161
noisiv 1
noisiv
Manwe Work 1
Manwe Work
Mt2Hizmet 1
Mt2Hizmet
melankolıa18 1
melankolıa18
romegames 1
romegames
Krutzo 1
Krutzo
shrpnl 1
shrpnl
Hikaye Ekle
Reklam vermek için turkmmo@gmail.com

[C++/Python/SQL]Market Promosyon Sistemi

  • Konuyu başlatan Konuyu başlatan Okan Çakın
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 7
  • Görüntüleme Görüntüleme 954
Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...

Okan Çakın

Level 4
TM Üye
Katılım
30 May 2023
Konular
38
Mesajlar
456
Çözüm
6
Online süresi
1mo 15d
Reaksiyon Skoru
354
Altın Konu
0
Başarım Puanı
103
MmoLira
11,817
DevLira
90
Ticaret - 0%
0   0   0

ROHAN2 WORLD 1-120 TR TİPİ OFFICIAL YOHARA, BALATHOR VE AMON! 80. GÜNÜNDE! +10.000 ONLİNE! HİLE VE BOT %100 ENGELLİ HEMEN TIKLA!

Herkese Merhaba

1: Sistem İlk Versiyondur.
2: Aklıma Gelen Bazı Kontrolleri Yaptım.

3: Gözden Kaçırmış Olduğum Engelleme veya Eksiklik Varsa Söylerseniz Mutlu Olurum.

Sistem Ne İşe Yarıyor?


promotion.sql İçine Ekleyeceğiniz Maximum 8 Haneli Bir Promosyon Kodu ile Oyuncular %50 İndirimli Ürün Satın Alabilecekler.

Neleri Değiştirebilirim? (Opsiyonel)

1: Yüzdelik Kısmını ( Örneğin: %25 İndirimli )
2: Promosyon Kodu Genişliği ( Örneğin 15 Haneli )


Geliştirebilir Miyim?

1: Etkinlik Olarak Kullanılabilir.
2: Farklı Sistemlere Uyarlanabilir.
3: Shop_Item.sql Genişletilebilir ve Sadece Belirli Ürünlerde Promosyon Kodu Geçerli Yapılabilir.
4: SlotWindow ile PosIndex'lerde Hangi Ürünün Promosyon Kodlu Olduğu İcon/Efekt Benzeri Yapılabilir. (
Shop_Item.sql Bağlantılı)

Bazı Düşüncelerim Var Mı?

1: Yeni Fonksiyon İsimleri ve Paket ile Sistemi Geliştirdim.
2: Dileyen Orjinal Fonksiyonların Parametresini ve İşevini Genişleterek Yapabilir.
3: Dileyen Sistemi Komple Tekrar Revize Edebilir.
4: Hepinize İyi Çalışmalar...


Eklediğiniz Promosyon Kodu

pRomotionCode.png


Oyuncunuzun, PlayerID'si Alışverişten Sonra Eklenmesi

pRomotionPlayerID.png


Oyuncunuzun PlayerID'si


playerID.png


Sistemin İşleyisi İle Alakalı Bazı Videolar...

Oyuncunuzun, Sizin Eklediğiniz Promosyon Kodu ile Marketten Alışveriş Yaptığı An




Oyuncunuz, Promosyon Kodunu Yanlış Girdiğiniz An



Oyuncunuz, Promosyon Kodunu Kullandıktan Sonra Tekrar Denediği An



Oyuncunuz, Promosyon Kodu Olmadan Marketten Alışveriş Yaptığı An



(Tıkla)
 
Son düzenleme:

En Çok Reaksiyon Alan Mesajlar

Yine çok farklı ve özgün bir içerik paylaşmışsın öncelikle eline emeğine sağlık. 👏

Kodları inceleme fırsatım oldu ve bu haliyle potansiyel bir kaç güvenlik zafiyetine sahip, oyunculara DB ile iletişime geçen bir sistemde input imkanı verilen oyun içerisindeki her nokta mutlaka SQL injection veya buffer overflow risklerinden arındırılmalıdır, pack tarafındaki len sınırını ve max karakter kontrollerini gördüm fakat bunlar yeterli değil, önerim ana shop fonksiyonları içerisinde gerekli kontrollerin eklenmesi, bunun için bir düzenleme yaptım konuya katkım olsun;

[CODE lang="cpp" title="shop.cpp"]//En Alta Ekle


// @Sadece Latin alfabesi harfleri ve sayilar kullanilabilir.
bool IsValidPromoCode (const std::string& PromoCode)
{
const std::regex pattern ("^[a-zA-Z0-9]+$");
return std::regex_match (PromoCode, pattern);
}

int CShop::PromotionBuy (LPCHARACTER ch, uint8_t pos, const char* pRomotion)
{
// @Oyuncu kontrolu.
if (ch == nullptr)
{
sys_log (0, "Shop::PromotionBuy: CH is NULL!");
return SHOP_SUBHEADER_GC_INVALID_POS;
}

if (pos >= m_itemVector.size())
{
sys_log (0, "Shop::PromotionBuy: Invalid Position %d : %s", pos, ch->GetName());
return SHOP_SUBHEADER_GC_INVALID_POS;
}

// @Islem henuz yeni basladi, bu logun amacini anlayamadim.
//sys_log (0, "Shop::PromotionBuy: Name %s Pos %d", ch->GetName(), pos);

auto it = m_map_guest.find (ch);
if (it == m_map_guest.end())
{
return SHOP_SUBHEADER_GC_END;
}

SHOP_ITEM& r_item = m_itemVector[pos];

if (r_item.price < 0)
{
LogManager::instance().HackLog ("SHOP_BUY_GOLD_OVERFLOW", ch);
return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
}

// @Buffer Overflow Kontrol.
if (strlen (pRomotion) > MAX_PROMOTION_CODE_LENGTH)
{
return SHOP_SUBHEADER_GC_INVALID_PROMOTION;
}

// @SQL Injection Kontrol.
std::string PromoCode (pRomotion);
if (!IsValidPromoCode (PromoCode))
{
return SHOP_SUBHEADER_GC_INVALID_PROMOTION;
}

// @Daha Once Kullanildi mi?
if (ch->GetPlayerID() == ch->GetPromotionPlayerID())
{
return SHOP_SUBHEADER_GC_PROMOTION_HAVE_USED;
}

char query[1024];
snprintf (query, sizeof (query), "SELECT promotion_code FROM promotion WHERE promotion_code='%s' LIMIT 1", pRomotion);
std::unique_ptr<SQLMsg> result (DBManager::instance().DirectQuery (query));

std::string pCode;
if (result->Get()->uiNumRows > 0)
{
MYSQL_ROW row = mysql_fetch_row(result->Get()->pSQLResult);
pCode = row[0];
}

LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find (r_item.itemid);

if (IsPCShop())
{
if (!pkSelectedItem)
{
sys_log (0, "Shop::PromotionBuy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
ch->GetPlayerID(),
m_pkPC->GetPlayerID());

return false;
}

if ((pkSelectedItem->GetOwner() != m_pkPC))
{
sys_log (0, "Shop::PromotionBuy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
ch->GetPlayerID(),
m_pkPC->GetPlayerID());

return false;
}
}

DWORD dwPrice = r_item.price;

if (it->second) // if other empire, price is triple
dwPrice *= 1;

if (ch->GetGold() < (int) dwPrice)
{
sys_log(1, "Shop::PromotionBuy : Not enough money : %s has %d, price %d", ch->GetName(), ch->GetGold(), dwPrice);
return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
}

if (pCode != pRomotion)
{
return SHOP_SUBHEADER_GC_WRONG_PROMOTION;
}
else
{
dwPrice /= 2;
ch->SetPromotionPlayerID(ch->GetPlayerID());
}

LPITEM item;

if (m_pkPC)
item = r_item.pkItem;
else
item = ITEM_MANAGER::instance().CreateItem(r_item.vnum, r_item.count);

if (!item)
return SHOP_SUBHEADER_GC_SOLD_OUT;

int iEmptyPos;
if (item->IsDragonSoul())
iEmptyPos = ch->GetEmptyDragonSoulInventory(item);
else
iEmptyPos = ch->GetEmptyInventory(item->GetSize());

if (iEmptyPos < 0)
{
if (m_pkPC)
{
sys_log(1, "Shop::PromotionBuy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
else
{
sys_log(1, "Shop::PromotionBuy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
M2_DESTROY_ITEM(item);
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}

ch->PointChange(POINT_GOLD, -dwPrice, false);

ch->ChatPacket(CHAT_TYPE_INFO, "PRICE: %d", dwPrice);

DWORD dwTax = 0;
int iVal = 0;

if (LC_IsYMIR() || LC_IsKorea())
{
if (0 < (iVal = quest::CQuestManager::instance().GetEventFlag("trade_tax")))
{
if (iVal > 100)
iVal = 100;

dwTax = dwPrice * iVal / 100;
dwPrice = dwPrice - dwTax;
}
else
{
iVal = 0;
dwTax = dwPrice * iVal / 100;
dwPrice = dwPrice - dwTax;
}
}
else
{
iVal = quest::CQuestManager::instance().GetEventFlag("personal_shop");

if (0 < iVal)
{
if (iVal > 100)
iVal = 100;

dwTax = dwPrice * iVal / 100;
dwPrice = dwPrice - dwTax;
}
else
{
iVal = 0;
dwTax = 0;
}
}

if (m_pkPC)
{
m_pkPC->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);

char buf[512];

if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
{
snprintf(buf, sizeof(buf), "%s FROM: %u TO: %u PRICE: %u", item->GetName(), ch->GetPlayerID(), m_pkPC->GetPlayerID(), dwPrice);
LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), SHOP_BUY, buf);
LogManager::instance().GoldBarLog(m_pkPC->GetPlayerID(), item->GetID(), SHOP_SELL, buf);
}

item->RemoveFromCharacter();
if (item->IsDragonSoul())
item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
else
item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);


snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), m_pkPC->GetPlayerID(), m_pkPC->GetName(), dwPrice, item->GetCount());
LogManager::instance().ItemLog(ch, item, "SHOP_BUY", buf);

snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, item->GetCount());
LogManager::instance().ItemLog(m_pkPC, item, "SHOP_SELL", buf);

r_item.pkItem = NULL;
BroadcastUpdateItem(pos);

m_pkPC->PointChange(POINT_GOLD, dwPrice, false);

if (iVal > 0)
m_pkPC->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÆÇ¸Å±İ¾×ÀÇ %d %% °¡ ¼¼±İÀ¸·Î ³ª°¡°ÔµË´Ï´Ù"), iVal);
}
else
{
if (item->IsDragonSoul())
item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
else
item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);
LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());

if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
{
LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
}

DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
}

if (item)
sys_log(0, "SHOP: PromotionBuy: name %s %s(x %d):%u price %u", ch->GetName(), item->GetName(), item->GetCount(), item->GetID(), dwPrice);

ch->Save();

return (SHOP_SUBHEADER_GC_OK);
}


[/CODE]


NOT: Üstteki kodun bazı include lara ihtiyacı var;

// @Regen Destegi
#include <regex>
#include <string>
#include <iostream>

Uygun bir yere eklersini#include][/CENTER#include#include
Thank you very much for the publication.
 
Yine çok farklı ve özgün bir içerik paylaşmışsın öncelikle eline emeğine sağlık. 👏

Kodları inceleme fırsatım oldu ve bu haliyle potansiyel bir kaç güvenlik zafiyetine sahip, oyunculara DB ile iletişime geçen bir sistemde input imkanı verilen oyun içerisindeki her nokta mutlaka SQL injection veya buffer overflow risklerinden arındırılmalıdır, pack tarafındaki len sınırını ve max karakter kontrollerini gördüm fakat bunlar yeterli değil, önerim ana shop fonksiyonları içerisinde gerekli kontrollerin eklenmesi, bunun için bir düzenleme yaptım konuya katkım olsun;

[CODE lang="cpp" title="shop.cpp"]//En Alta Ekle


// @Sadece Latin alfabesi harfleri ve sayilar kullanilabilir.
bool IsValidPromoCode (const std::string& PromoCode)
{
const std::regex pattern ("^[a-zA-Z0-9]+$");
return std::regex_match (PromoCode, pattern);
}

int CShop::PromotionBuy (LPCHARACTER ch, uint8_t pos, const char* pRomotion)
{
// @Oyuncu kontrolu.
if (ch == nullptr)
{
sys_log (0, "Shop::PromotionBuy: CH is NULL!");
return SHOP_SUBHEADER_GC_INVALID_POS;
}

if (pos >= m_itemVector.size())
{
sys_log (0, "Shop::PromotionBuy: Invalid Position %d : %s", pos, ch->GetName());
return SHOP_SUBHEADER_GC_INVALID_POS;
}

// @Islem henuz yeni basladi, bu logun amacini anlayamadim.
//sys_log (0, "Shop::PromotionBuy: Name %s Pos %d", ch->GetName(), pos);

auto it = m_map_guest.find (ch);
if (it == m_map_guest.end())
{
return SHOP_SUBHEADER_GC_END;
}

SHOP_ITEM& r_item = m_itemVector[pos];

if (r_item.price < 0)
{
LogManager::instance().HackLog ("SHOP_BUY_GOLD_OVERFLOW", ch);
return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
}

// @Buffer Overflow Kontrol.
if (strlen (pRomotion) > MAX_PROMOTION_CODE_LENGTH)
{
return SHOP_SUBHEADER_GC_INVALID_PROMOTION;
}

// @SQL Injection Kontrol.
std::string PromoCode (pRomotion);
if (!IsValidPromoCode (PromoCode))
{
return SHOP_SUBHEADER_GC_INVALID_PROMOTION;
}

// @Daha Once Kullanildi mi?
if (ch->GetPlayerID() == ch->GetPromotionPlayerID())
{
return SHOP_SUBHEADER_GC_PROMOTION_HAVE_USED;
}

char query[1024];
snprintf (query, sizeof (query), "SELECT promotion_code FROM promotion WHERE promotion_code='%s' LIMIT 1", pRomotion);
std::unique_ptr<SQLMsg> result (DBManager::instance().DirectQuery (query));

std::string pCode;
if (result->Get()->uiNumRows > 0)
{
MYSQL_ROW row = mysql_fetch_row(result->Get()->pSQLResult);
pCode = row[0];
}

LPITEM pkSelectedItem = ITEM_MANAGER::instance().Find (r_item.itemid);

if (IsPCShop())
{
if (!pkSelectedItem)
{
sys_log (0, "Shop::PromotionBuy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
ch->GetPlayerID(),
m_pkPC->GetPlayerID());

return false;
}

if ((pkSelectedItem->GetOwner() != m_pkPC))
{
sys_log (0, "Shop::PromotionBuy : Critical: This user seems to be a hacker : invalid pcshop item : BuyerPID:%d SellerPID:%d",
ch->GetPlayerID(),
m_pkPC->GetPlayerID());

return false;
}
}

DWORD dwPrice = r_item.price;

if (it->second) // if other empire, price is triple
dwPrice *= 1;

if (ch->GetGold() < (int) dwPrice)
{
sys_log(1, "Shop::PromotionBuy : Not enough money : %s has %d, price %d", ch->GetName(), ch->GetGold(), dwPrice);
return SHOP_SUBHEADER_GC_NOT_ENOUGH_MONEY;
}

if (pCode != pRomotion)
{
return SHOP_SUBHEADER_GC_WRONG_PROMOTION;
}
else
{
dwPrice /= 2;
ch->SetPromotionPlayerID(ch->GetPlayerID());
}

LPITEM item;

if (m_pkPC)
item = r_item.pkItem;
else
item = ITEM_MANAGER::instance().CreateItem(r_item.vnum, r_item.count);

if (!item)
return SHOP_SUBHEADER_GC_SOLD_OUT;

int iEmptyPos;
if (item->IsDragonSoul())
iEmptyPos = ch->GetEmptyDragonSoulInventory(item);
else
iEmptyPos = ch->GetEmptyInventory(item->GetSize());

if (iEmptyPos < 0)
{
if (m_pkPC)
{
sys_log(1, "Shop::PromotionBuy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
else
{
sys_log(1, "Shop::PromotionBuy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
M2_DESTROY_ITEM(item);
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}

ch->PointChange(POINT_GOLD, -dwPrice, false);

ch->ChatPacket(CHAT_TYPE_INFO, "PRICE: %d", dwPrice);

DWORD dwTax = 0;
int iVal = 0;

if (LC_IsYMIR() || LC_IsKorea())
{
if (0 < (iVal = quest::CQuestManager::instance().GetEventFlag("trade_tax")))
{
if (iVal > 100)
iVal = 100;

dwTax = dwPrice * iVal / 100;
dwPrice = dwPrice - dwTax;
}
else
{
iVal = 0;
dwTax = dwPrice * iVal / 100;
dwPrice = dwPrice - dwTax;
}
}
else
{
iVal = quest::CQuestManager::instance().GetEventFlag("personal_shop");

if (0 < iVal)
{
if (iVal > 100)
iVal = 100;

dwTax = dwPrice * iVal / 100;
dwPrice = dwPrice - dwTax;
}
else
{
iVal = 0;
dwTax = 0;
}
}

if (m_pkPC)
{
m_pkPC->SyncQuickslot(QUICKSLOT_TYPE_ITEM, item->GetCell(), 255);

char buf[512];

if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
{
snprintf(buf, sizeof(buf), "%s FROM: %u TO: %u PRICE: %u", item->GetName(), ch->GetPlayerID(), m_pkPC->GetPlayerID(), dwPrice);
LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), SHOP_BUY, buf);
LogManager::instance().GoldBarLog(m_pkPC->GetPlayerID(), item->GetID(), SHOP_SELL, buf);
}

item->RemoveFromCharacter();
if (item->IsDragonSoul())
item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
else
item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);


snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), m_pkPC->GetPlayerID(), m_pkPC->GetName(), dwPrice, item->GetCount());
LogManager::instance().ItemLog(ch, item, "SHOP_BUY", buf);

snprintf(buf, sizeof(buf), "%s %u(%s) %u %u", item->GetName(), ch->GetPlayerID(), ch->GetName(), dwPrice, item->GetCount());
LogManager::instance().ItemLog(m_pkPC, item, "SHOP_SELL", buf);

r_item.pkItem = NULL;
BroadcastUpdateItem(pos);

m_pkPC->PointChange(POINT_GOLD, dwPrice, false);

if (iVal > 0)
m_pkPC->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÆÇ¸Å±İ¾×ÀÇ %d %% °¡ ¼¼±İÀ¸·Î ³ª°¡°ÔµË´Ï´Ù"), iVal);
}
else
{
if (item->IsDragonSoul())
item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
else
item->AddToCharacter(ch, TItemPos(INVENTORY, iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);
LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());

if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
{
LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
}

DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
}

if (item)
sys_log(0, "SHOP: PromotionBuy: name %s %s(x %d):%u price %u", ch->GetName(), item->GetName(), item->GetCount(), item->GetID(), dwPrice);

ch->Save();

return (SHOP_SUBHEADER_GC_OK);
}


[/CODE]


NOT: Üstteki kodun bazı include lara ihtiyacı var;

// @Regen Destegi
#include <regex>
#include <string>
#include <iostream>

Uygun bir yere eklersini#include][/CENTER#include#include
 
Son düzenleme:
Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst