forked from townforge/townforge
badges
This commit is contained in:
parent
96c251c9ab
commit
2882f6bc80
@ -12,6 +12,11 @@ TBLayout: axis: y, distribution-position: "left top", distribution: "available"
|
||||
|
||||
TBScrollContainer: adapt-content: 1
|
||||
TBLayout: axis x, distribution: "available"
|
||||
TBLayout: axis: y, distribution: "available"
|
||||
lp: width: 380
|
||||
TBTextField: text: "Badges"
|
||||
TBSelectList: id: "badges", gravity: "all", scroll-mode: "auto"
|
||||
TBEditField: id: "badges-search", placeholder: "search", type: "search", gravity: "left right"
|
||||
TBLayout: axis: y, distribution: "available"
|
||||
lp: width: 280
|
||||
TBTextField: text: "Building activity"
|
||||
|
@ -44,4 +44,4 @@ TBTabContainer
|
||||
TBEditField: id: "discoveries-search", gravity: "left right", placeholder: "search", type: "search"
|
||||
|
||||
TBLayout: axis: y, distribution-position: "left top", distribution: "gravity"
|
||||
TBTextField: text: "Nothing here yet"
|
||||
TBSelectList: id: "badges", gravity: "all"
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "cc/cc_game_events.h"
|
||||
#include "cc/cc_special_events.h"
|
||||
#include "cc/cc_custom_item.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "cryptonote_basic/blobdatatype.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "cryptonote_basic/difficulty.h"
|
||||
@ -159,6 +160,7 @@ struct cc_account_data_t
|
||||
uint64_t balance;
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
std::string name;
|
||||
bool ignore;
|
||||
};
|
||||
@ -1857,6 +1859,7 @@ public:
|
||||
virtual void set_cc_account_item_balances(uint32_t id, const std::map<uint32_t, uint32_t> &item_balances) = 0;
|
||||
virtual void add_cc_account_flag(uint32_t id, uint32_t flag_id) = 0;
|
||||
virtual void remove_cc_account_flag(uint32_t id, uint32_t flag_id) = 0;
|
||||
virtual void set_cc_account_badges(uint32_t id, const std::map<uint32_t, uint8_t> &badges) = 0;
|
||||
virtual void set_cc_account_name(uint32_t id, const std::string &name) = 0;
|
||||
virtual void set_cc_account_ignore(uint32_t id, bool ignore) = 0;
|
||||
virtual bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const = 0;
|
||||
@ -1926,6 +1929,11 @@ public:
|
||||
virtual void set_cc_custom_item_ignore(uint32_t id, bool ignore) = 0;
|
||||
virtual bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const = 0;
|
||||
|
||||
virtual uint32_t allocate_new_cc_event_badge(const std::string &name, const std::string &desc) = 0;
|
||||
virtual void delete_cc_event_badge(uint32_t id) = 0;
|
||||
virtual bool get_cc_event_badge_data(uint32_t id, cc::cc_badge_data_t &cid) const = 0;
|
||||
virtual bool for_all_cc_event_badges(std::function<bool(const cc::cc_badge_data_t &cid)> f) const = 0;
|
||||
|
||||
// CC non virtual helpers, calls the virtual ones
|
||||
bool does_cc_account_exist(uint32_t id) const;
|
||||
bool does_cc_city_exist(uint32_t id) const;
|
||||
|
@ -305,6 +305,7 @@ namespace
|
||||
* cc_discoveries id {discovery metadata}
|
||||
* cc_special_events city {special event metadata}
|
||||
* cc_custom_items id {item metadata}
|
||||
* cc_event_badges id {badge metadata}
|
||||
*
|
||||
* Note: where the data items are of uniform size, DUPFIXED tables have
|
||||
* been used to save space. In most of these cases, a dummy "zerokval"
|
||||
@ -352,6 +353,7 @@ const char* const LMDB_CC_NAMES = "cc_names";
|
||||
const char* const LMDB_CC_DISCOVERIES = "cc_discoveries";
|
||||
const char* const LMDB_CC_SPECIAL_EVENTS = "cc_special_events";
|
||||
const char* const LMDB_CC_CUSTOM_ITEMS = "cc_custom_items";
|
||||
const char* const LMDB_CC_EVENT_BADGES = "cc_event_badges";
|
||||
|
||||
const char* const LMDB_PROPERTIES = "properties";
|
||||
|
||||
@ -474,6 +476,7 @@ typedef struct mdb_cc_account_data
|
||||
uint64_t balance;
|
||||
uint32_t n_item_balances;
|
||||
uint32_t n_flags;
|
||||
uint32_t n_badges;
|
||||
bool ignore;
|
||||
char name[MAX_CC_NAME_LENGTH];
|
||||
} mdb_cc_account_data;
|
||||
@ -579,6 +582,12 @@ typedef struct mdb_cc_custom_item_data_t
|
||||
char secondary_description[MAX_CC_ITEM_DESCRIPTION_LENGTH];
|
||||
} mdb_cc_custom_item_data_t;
|
||||
|
||||
typedef struct mdb_cc_event_badge_data_t
|
||||
{
|
||||
char name[MAX_CC_NAME_LENGTH];
|
||||
char desc[MAX_CC_ITEM_DESCRIPTION_LENGTH];
|
||||
} mdb_cc_event_badge_data_t;
|
||||
|
||||
std::atomic<uint64_t> mdb_txn_safe::num_active_txns{0};
|
||||
std::atomic_flag mdb_txn_safe::creation_gate = ATOMIC_FLAG_INIT;
|
||||
|
||||
@ -1664,6 +1673,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
|
||||
lmdb_db_open(txn, LMDB_CC_DISCOVERIES, MDB_INTEGERKEY | MDB_CREATE, m_cc_discoveries, "Failed to open db handle for m_cc_discoveries");
|
||||
lmdb_db_open(txn, LMDB_CC_SPECIAL_EVENTS, MDB_INTEGERKEY | MDB_CREATE, m_cc_special_events, "Failed to open db handle for m_cc_special_events");
|
||||
lmdb_db_open(txn, LMDB_CC_CUSTOM_ITEMS, MDB_INTEGERKEY | MDB_CREATE, m_cc_custom_items, "Failed to open db handle for m_cc_custom_items");
|
||||
lmdb_db_open(txn, LMDB_CC_EVENT_BADGES, MDB_INTEGERKEY | MDB_CREATE, m_cc_event_badges, "Failed to open db handle for m_cc_event_badges");
|
||||
|
||||
lmdb_db_open(txn, LMDB_PROPERTIES, MDB_CREATE, m_properties, "Failed to open db handle for m_properties");
|
||||
|
||||
@ -1698,6 +1708,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
|
||||
mdb_set_compare(txn, m_cc_discoveries, compare_uint32);
|
||||
mdb_set_compare(txn, m_cc_special_events, compare_uint32);
|
||||
mdb_set_compare(txn, m_cc_custom_items, compare_uint32);
|
||||
mdb_set_compare(txn, m_cc_event_badges, compare_uint32);
|
||||
|
||||
if (!(mdb_flags & MDB_RDONLY))
|
||||
{
|
||||
@ -1898,6 +1909,8 @@ void BlockchainLMDB::reset()
|
||||
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_special_events: ", result).c_str()));
|
||||
if (auto result = mdb_drop(txn, m_cc_custom_items, 0))
|
||||
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_custom_items: ", result).c_str()));
|
||||
if (auto result = mdb_drop(txn, m_cc_event_badges, 0))
|
||||
throw0(DB_ERROR(lmdb_error("Failed to drop m_cc_event_badges: ", result).c_str()));
|
||||
|
||||
// init with current version
|
||||
MDB_val_str(k, "version");
|
||||
@ -4619,12 +4632,13 @@ void BlockchainLMDB::drop_alt_blocks()
|
||||
TXN_POSTFIX_SUCCESS();
|
||||
}
|
||||
|
||||
static bool read_account_variable_size_data(const mdb_cc_account_data *ad, size_t bytes, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags)
|
||||
static bool read_account_variable_size_data(const mdb_cc_account_data *ad, size_t bytes, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges)
|
||||
{
|
||||
item_balances.clear();
|
||||
flags.clear();
|
||||
badges.clear();
|
||||
|
||||
if (bytes < sizeof(mdb_cc_account_data) + (2 * sizeof(uint32_t)) * ad->n_item_balances + sizeof(uint32_t) * ad->n_flags)
|
||||
if (bytes < sizeof(mdb_cc_account_data) + (2 * sizeof(uint32_t)) * ad->n_item_balances + sizeof(uint32_t) * ad->n_flags + (sizeof(uint32_t) * 2) * ad->n_badges)
|
||||
return false;
|
||||
|
||||
// variable size data
|
||||
@ -4650,18 +4664,32 @@ static bool read_account_variable_size_data(const mdb_cc_account_data *ad, size_
|
||||
flags[i] = *ptr++;
|
||||
}
|
||||
|
||||
// read badges
|
||||
for (uint32_t i = 0; i < ad->n_badges; ++i)
|
||||
{
|
||||
const unsigned idx = *ptr++;
|
||||
if (badges.find(idx) != badges.end())
|
||||
MWARNING("Two entries for badges[" << idx << "]");
|
||||
const unsigned level = *ptr++;
|
||||
if (level > NUM_BADGE_LEVELS)
|
||||
MWARNING("entry has invalid level for badges[" << idx << "]");
|
||||
else if (level > 0)
|
||||
badges[idx] = level;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void write_account_variable_size_data(MDB_val &v, mdb_cc_account_data &ad, const std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> flags)
|
||||
static void write_account_variable_size_data(MDB_val &v, mdb_cc_account_data &ad, const std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> flags, const std::map<uint32_t, uint8_t> &badges)
|
||||
{
|
||||
ad.n_item_balances = item_balances.size();
|
||||
for (const auto &e: item_balances)
|
||||
if (e.second == 0)
|
||||
--ad.n_item_balances;
|
||||
ad.n_flags = flags.size();
|
||||
ad.n_badges = badges.size();
|
||||
|
||||
v.mv_size = sizeof(mdb_cc_account_data) + (2 * sizeof(uint32_t)) * ad.n_item_balances + sizeof(uint32_t) * ad.n_flags;
|
||||
v.mv_size = sizeof(mdb_cc_account_data) + (2 * sizeof(uint32_t)) * ad.n_item_balances + sizeof(uint32_t) * ad.n_flags + (sizeof(uint32_t) * 2) * ad.n_badges;
|
||||
v.mv_data = malloc(v.mv_size);
|
||||
memcpy(v.mv_data, &ad, sizeof(mdb_cc_account_data));
|
||||
|
||||
@ -4683,6 +4711,14 @@ static void write_account_variable_size_data(MDB_val &v, mdb_cc_account_data &ad
|
||||
{
|
||||
*ptr++ = flags[i];
|
||||
}
|
||||
|
||||
// write badges
|
||||
for (const auto &e: badges)
|
||||
{
|
||||
*ptr++ = e.first;
|
||||
*ptr++ = e.second;
|
||||
}
|
||||
|
||||
if ((const uint8_t*)ptr - (const uint8_t*)v.mv_data != (ptrdiff_t)v.mv_size)
|
||||
{
|
||||
free(v.mv_data);
|
||||
@ -4732,6 +4768,7 @@ uint32_t BlockchainLMDB::allocate_new_cc_account(const crypto::public_key &publi
|
||||
ad.balance = 0;
|
||||
ad.n_item_balances = 0;
|
||||
ad.n_flags = 0;
|
||||
ad.n_badges = 0;
|
||||
ad.ignore = false;
|
||||
|
||||
memset(ad.name, 0, sizeof(ad.name));
|
||||
@ -4869,7 +4906,7 @@ bool BlockchainLMDB::get_cc_account_data(uint32_t id, cc_account_data_t &data) c
|
||||
const size_t namelen = NUL ? NUL - (const char*)ad->name : MAX_CC_NAME_LENGTH;
|
||||
data.name.assign(ad->name, namelen);
|
||||
|
||||
if (!read_account_variable_size_data(ad, v.mv_size, data.item_balances, data.flags))
|
||||
if (!read_account_variable_size_data(ad, v.mv_size, data.item_balances, data.flags, data.badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
TXN_POSTFIX_RDONLY();
|
||||
@ -4904,10 +4941,11 @@ void BlockchainLMDB::set_cc_account_balance(uint32_t id, uint64_t balance)
|
||||
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags))
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags, badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
write_account_variable_size_data(v, ad, item_balances, flags);
|
||||
write_account_variable_size_data(v, ad, item_balances, flags, badges);
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
if (v.mv_data) free(v.mv_data);
|
||||
@ -4936,12 +4974,13 @@ void BlockchainLMDB::add_cc_account_flag(uint32_t id, uint32_t flag_id)
|
||||
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags))
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags, badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
flags.push_back(flag_id);
|
||||
|
||||
write_account_variable_size_data(v, ad, item_balances, flags);
|
||||
write_account_variable_size_data(v, ad, item_balances, flags, badges);
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
if (v.mv_data) free(v.mv_data);
|
||||
@ -4970,7 +5009,8 @@ void BlockchainLMDB::remove_cc_account_flag(uint32_t id, uint32_t flag_id)
|
||||
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags))
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags, badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
bool found = false;
|
||||
@ -4986,7 +5026,7 @@ void BlockchainLMDB::remove_cc_account_flag(uint32_t id, uint32_t flag_id)
|
||||
if (!found)
|
||||
throw0(DB_ERROR("Flag to remove not found"));
|
||||
|
||||
write_account_variable_size_data(v, ad, item_balances, flags);
|
||||
write_account_variable_size_data(v, ad, item_balances, flags, badges);
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
if (v.mv_data) free(v.mv_data);
|
||||
@ -5015,10 +5055,44 @@ void BlockchainLMDB::set_cc_account_item_balances(uint32_t id, const std::map<ui
|
||||
|
||||
std::map<uint32_t, uint32_t> old_item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
if (!read_account_variable_size_data((mdb_cc_account_data*)v.mv_data, v.mv_size, old_item_balances, flags))
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
if (!read_account_variable_size_data((mdb_cc_account_data*)v.mv_data, v.mv_size, old_item_balances, flags, badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
write_account_variable_size_data(v, ad, item_balances, flags);
|
||||
write_account_variable_size_data(v, ad, item_balances, flags, badges);
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
free(v.mv_data);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add account data to db transaction: ", result).c_str()));
|
||||
}
|
||||
|
||||
void BlockchainLMDB::set_cc_account_badges(uint32_t id, const std::map<uint32_t, uint8_t> &badges)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
CURSOR(cc_accounts)
|
||||
|
||||
// find account id
|
||||
MDB_val_set(k, id);
|
||||
MDB_val v;
|
||||
int result = mdb_cursor_get(m_cur_cc_accounts, &k, &v, MDB_SET);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Account " + std::to_string(id) + " not found: ", result).c_str()));
|
||||
if (v.mv_size < sizeof(mdb_cc_account_data))
|
||||
throw0(DB_ERROR("Unexpected account data size"));
|
||||
|
||||
mdb_cc_account_data ad = *(mdb_cc_account_data*)v.mv_data;
|
||||
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::map<uint32_t, uint8_t> old_badges;
|
||||
if (!read_account_variable_size_data((mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags, old_badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
write_account_variable_size_data(v, ad, item_balances, flags, badges);
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
free(v.mv_data);
|
||||
@ -5079,10 +5153,11 @@ void BlockchainLMDB::set_cc_account_ignore(uint32_t id, bool ignore)
|
||||
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags))
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
if (!read_account_variable_size_data((const mdb_cc_account_data*)v.mv_data, v.mv_size, item_balances, flags, badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
write_account_variable_size_data(v, ad, item_balances, flags);
|
||||
write_account_variable_size_data(v, ad, item_balances, flags, badges);
|
||||
|
||||
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
|
||||
if (v.mv_data) free(v.mv_data);
|
||||
@ -5123,7 +5198,7 @@ bool BlockchainLMDB::for_all_cc_accounts(std::function<bool(const cc_account_dat
|
||||
data.balance = ad.balance;
|
||||
data.ignore = ad.ignore;
|
||||
|
||||
if (!read_account_variable_size_data((mdb_cc_account_data*)v.mv_data, v.mv_size, data.item_balances, data.flags))
|
||||
if (!read_account_variable_size_data((mdb_cc_account_data*)v.mv_data, v.mv_size, data.item_balances, data.flags, data.badges))
|
||||
throw0(DB_ERROR("Failed to read account variable size data"));
|
||||
|
||||
const char *NUL = (const char*)memchr(ad.name, 0, MAX_CC_NAME_LENGTH);
|
||||
@ -7087,6 +7162,166 @@ bool BlockchainLMDB::for_all_cc_custom_items(std::function<bool(const cc::cc_cus
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t BlockchainLMDB::allocate_new_cc_event_badge(const std::string &name, const std::string &desc)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
if (name.size() > MAX_CC_NAME_LENGTH)
|
||||
throw0(DB_ERROR("Name is too long"));
|
||||
if (desc.size() > MAX_CC_ITEM_DESCRIPTION_LENGTH)
|
||||
throw0(DB_ERROR("Description is too long"));
|
||||
|
||||
CURSOR(cc_event_badges)
|
||||
uint32_t badge_id = cc::BADGE_FIRST_EVENT;
|
||||
int result = 0;
|
||||
|
||||
// find first free badge id
|
||||
MDB_val k;
|
||||
MDB_val v;
|
||||
MDB_cursor_op op = MDB_FIRST;
|
||||
while (1)
|
||||
{
|
||||
result = mdb_cursor_get(m_cur_cc_event_badges, &k, &v, op);
|
||||
op = MDB_NEXT;
|
||||
if (result == MDB_NOTFOUND)
|
||||
break;
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate event badge data: ", result).c_str()));
|
||||
if (v.mv_size < sizeof(mdb_cc_event_badge_data_t))
|
||||
throw0(DB_ERROR("Unexpected event badge size"));
|
||||
uint32_t k_id = *(const uint32_t*)k.mv_data;
|
||||
if (k_id > badge_id)
|
||||
break;
|
||||
++badge_id;
|
||||
if (badge_id > cc::BADGE_LAST_EVENT)
|
||||
throw0(DB_ERROR("No event badge ID available"));
|
||||
}
|
||||
MINFO("Badge ID " << badge_id << " is available");
|
||||
|
||||
mdb_cc_event_badge_data_t ebd;
|
||||
|
||||
memset(ebd.name, 0, sizeof(ebd.name));
|
||||
memcpy(ebd.name, name.data(), name.size());
|
||||
memset(ebd.desc, 0, sizeof(ebd.desc));
|
||||
memcpy(ebd.desc, desc.data(), desc.size());
|
||||
|
||||
k.mv_data = (void*)&badge_id;
|
||||
k.mv_size = sizeof(badge_id);
|
||||
v.mv_data = (void*)&ebd;
|
||||
v.mv_size = sizeof(ebd);
|
||||
result = mdb_cursor_put(m_cur_cc_event_badges, &k, &v, 0);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add event badge data to db transaction: ", result).c_str()));
|
||||
|
||||
return badge_id;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::delete_cc_event_badge(uint32_t id)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
CURSOR(cc_event_badges)
|
||||
|
||||
// find badge id
|
||||
MDB_val_set(k, id);
|
||||
MDB_val v;
|
||||
int result = mdb_cursor_get(m_cur_cc_event_badges, &k, &v, MDB_SET);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Event badge " + std::to_string(id) + " not found: ", result).c_str()));
|
||||
if (v.mv_size < sizeof(mdb_cc_event_badge_data_t))
|
||||
throw0(DB_ERROR("Unexpected event badge data size"));
|
||||
|
||||
result = mdb_cursor_del(m_cur_cc_event_badges, 0);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Error deleting badge " + std::to_string(id) + ": ", result).c_str()));
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::get_cc_event_badge_data(uint32_t id, cc::cc_badge_data_t &bd) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(cc_event_badges);
|
||||
|
||||
MDB_val_set(k, id);
|
||||
MDB_val v;
|
||||
int result = mdb_cursor_get(m_cur_cc_event_badges, &k, &v, MDB_SET);
|
||||
if (result == MDB_NOTFOUND)
|
||||
return false;
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve event badge data: ", result).c_str()));
|
||||
if (v.mv_size < sizeof(mdb_cc_event_badge_data_t))
|
||||
throw0(DB_ERROR("Unexpected event badge data size"));
|
||||
|
||||
const mdb_cc_event_badge_data_t *badge_data = (const mdb_cc_event_badge_data_t *)v.mv_data;
|
||||
|
||||
bd.id = id;
|
||||
|
||||
const char *NUL = (const char*)memchr(badge_data->name, 0, MAX_CC_NAME_LENGTH);
|
||||
const size_t namelen = NUL ? NUL - (const char*)badge_data->name : MAX_CC_NAME_LENGTH;
|
||||
bd.name.assign(badge_data->name, namelen);
|
||||
|
||||
NUL = (const char*)memchr(badge_data->desc, 0, MAX_CC_ITEM_DESCRIPTION_LENGTH);
|
||||
const size_t description_len = NUL ? NUL - (const char*)badge_data->desc : MAX_CC_ITEM_DESCRIPTION_LENGTH;
|
||||
bd.desc.assign(badge_data->desc, description_len);
|
||||
|
||||
TXN_POSTFIX_RDONLY();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::for_all_cc_event_badges(std::function<bool(const cc::cc_badge_data_t &bd)> f) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(cc_event_badges);
|
||||
|
||||
bool ret = true;
|
||||
MDB_val k, v;
|
||||
MDB_cursor_op op = MDB_FIRST;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int result = mdb_cursor_get(m_cur_cc_event_badges, &k, &v, op);
|
||||
if (result == MDB_NOTFOUND)
|
||||
return true;
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve event badge data: ", result).c_str()));
|
||||
if (v.mv_size < sizeof(mdb_cc_event_badge_data_t))
|
||||
throw0(DB_ERROR("Unexpected event badge data size"));
|
||||
|
||||
op = MDB_NEXT;
|
||||
|
||||
const uint32_t &id = *(const uint32_t*)k.mv_data;
|
||||
const mdb_cc_event_badge_data_t &badge_data = *(const mdb_cc_event_badge_data_t *)v.mv_data;
|
||||
|
||||
cc::cc_badge_data_t bd;
|
||||
|
||||
const char *NUL = (const char*)memchr(badge_data.name, 0, MAX_CC_NAME_LENGTH);
|
||||
const size_t namelen = NUL ? NUL - (const char*)badge_data.name : MAX_CC_NAME_LENGTH;
|
||||
bd.name.assign(badge_data.name, namelen);
|
||||
|
||||
NUL = (const char*)memchr(badge_data.desc, 0, MAX_CC_ITEM_DESCRIPTION_LENGTH);
|
||||
const size_t description_len = NUL ? NUL - (const char*)badge_data.desc : MAX_CC_ITEM_DESCRIPTION_LENGTH;
|
||||
bd.desc.assign(badge_data.desc, description_len);
|
||||
|
||||
if (!f(bd))
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TXN_POSTFIX_RDONLY();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::get_database_size() const
|
||||
{
|
||||
uint64_t size = 0;
|
||||
|
@ -87,6 +87,7 @@ typedef struct mdb_txn_cursors
|
||||
MDB_cursor *m_txc_cc_discoveries;
|
||||
MDB_cursor *m_txc_cc_special_events;
|
||||
MDB_cursor *m_txc_cc_custom_items;
|
||||
MDB_cursor *m_txc_cc_event_badges;
|
||||
} mdb_txn_cursors;
|
||||
|
||||
#define m_cur_blocks m_cursors->m_txc_blocks
|
||||
@ -121,6 +122,7 @@ typedef struct mdb_txn_cursors
|
||||
#define m_cur_cc_discoveries m_cursors->m_txc_cc_discoveries
|
||||
#define m_cur_cc_special_events m_cursors->m_txc_cc_special_events
|
||||
#define m_cur_cc_custom_items m_cursors->m_txc_cc_custom_items
|
||||
#define m_cur_cc_event_badges m_cursors->m_txc_cc_event_badges
|
||||
|
||||
typedef struct mdb_rflags
|
||||
{
|
||||
@ -157,6 +159,7 @@ typedef struct mdb_rflags
|
||||
bool m_rf_cc_discoveries;
|
||||
bool m_rf_cc_special_events;
|
||||
bool m_rf_cc_custom_items;
|
||||
bool m_rf_cc_event_badges;
|
||||
} mdb_rflags;
|
||||
|
||||
typedef struct mdb_threadinfo
|
||||
@ -475,6 +478,7 @@ private:
|
||||
bool does_cc_account_exist(uint32_t id) const;
|
||||
void set_cc_account_balance(uint32_t id, uint64_t balance);
|
||||
void set_cc_account_item_balances(uint32_t id, const std::map<uint32_t, uint32_t> &item_balances);
|
||||
void set_cc_account_badges(uint32_t id, const std::map<uint32_t, uint8_t> &badges);
|
||||
void set_cc_account_name(uint32_t id, const std::string &name);
|
||||
void set_cc_account_ignore(uint32_t id, bool ignore);
|
||||
void add_cc_account_flag(uint32_t id, uint32_t flag_id);
|
||||
@ -546,6 +550,11 @@ private:
|
||||
void set_cc_custom_item_ignore(uint32_t id, bool ignore);
|
||||
bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const;
|
||||
|
||||
uint32_t allocate_new_cc_event_badge(const std::string &name, const std::string &desc);
|
||||
void delete_cc_event_badge(uint32_t id);
|
||||
bool get_cc_event_badge_data(uint32_t id, cc::cc_badge_data_t &cid) const;
|
||||
bool for_all_cc_event_badges(std::function<bool(const cc::cc_badge_data_t &cid)> f) const;
|
||||
|
||||
// fix up anything that may be wrong due to past bugs
|
||||
virtual void fixup();
|
||||
|
||||
@ -613,6 +622,7 @@ private:
|
||||
MDB_dbi m_cc_discoveries;
|
||||
MDB_dbi m_cc_special_events;
|
||||
MDB_dbi m_cc_custom_items;
|
||||
MDB_dbi m_cc_event_badges;
|
||||
|
||||
mutable uint64_t m_cum_size; // used in batch size estimation
|
||||
mutable unsigned int m_cum_count;
|
||||
|
@ -175,6 +175,7 @@ public:
|
||||
virtual void set_cc_account_item_balances(uint32_t id, const std::map<uint32_t, uint32_t> &item_balances) {}
|
||||
virtual void add_cc_account_flag(uint32_t id, uint32_t flag_id) {}
|
||||
virtual void remove_cc_account_flag(uint32_t id, uint32_t flag_id) {}
|
||||
virtual void set_cc_account_badges(uint32_t id, const std::map<uint32_t, uint8_t> &badges) {}
|
||||
virtual void set_cc_account_name(uint32_t id, const std::string &name) {}
|
||||
virtual void set_cc_account_ignore(uint32_t id, bool ignore) {}
|
||||
virtual bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const { return true; }
|
||||
@ -244,6 +245,11 @@ public:
|
||||
virtual void set_cc_custom_item_ignore(uint32_t id, bool ignore) {}
|
||||
virtual bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const { return true; }
|
||||
|
||||
virtual uint32_t allocate_new_cc_event_badge(const std::string &name, const std::string &desc) { return 0; }
|
||||
virtual void delete_cc_event_badge(uint32_t id) {}
|
||||
virtual bool get_cc_event_badge_data(uint32_t id, cc::cc_badge_data_t &cid) const { return false; }
|
||||
virtual bool for_all_cc_event_badges(std::function<bool(const cc::cc_badge_data_t &cid)> f) const { return false; }
|
||||
|
||||
private:
|
||||
uint32_t n_accounts;
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ set(cc_sources
|
||||
cc_command_handler_give.cpp
|
||||
cc_command_handler_ignore.cpp
|
||||
cc_command_handler_match.cpp
|
||||
cc_command_handler_new_event_badge.cpp
|
||||
cc_command_handler_new_item.cpp
|
||||
cc_command_handler_none.cpp
|
||||
cc_command_handler_rename.cpp
|
||||
@ -48,6 +49,7 @@ set(cc_sources
|
||||
cc_command_handler_research.cpp
|
||||
cc_command_handler_trade.cpp
|
||||
cc_command_handler_transfer.cpp
|
||||
cc_badge.cpp
|
||||
cc_discoveries.cpp
|
||||
cc_game_update.cpp
|
||||
cc_influence.cpp
|
||||
@ -72,6 +74,7 @@ set(cc_headers
|
||||
cc_command_handler_give.h
|
||||
cc_command_handler_ignore.h
|
||||
cc_command_handler_match.h
|
||||
cc_command_handler_new_event_badge.h
|
||||
cc_command_handler_new_item.h
|
||||
cc_command_handler_none.h
|
||||
cc_command_handler_rename.h
|
||||
@ -79,6 +82,7 @@ set(cc_headers
|
||||
cc_command_handler_research.h
|
||||
cc_command_handler_trade.h
|
||||
cc_command_handler_transfer.h
|
||||
cc_badge.h
|
||||
cc_discoveries.h
|
||||
cc_game_update.h
|
||||
cc_influence.h
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "cc_command_handler_give.h"
|
||||
#include "cc_command_handler_ignore.h"
|
||||
#include "cc_command_handler_match.h"
|
||||
#include "cc_command_handler_new_event_badge.h"
|
||||
#include "cc_command_handler_new_item.h"
|
||||
#include "cc_command_handler_none.h"
|
||||
#include "cc_command_handler_rename.h"
|
||||
@ -1611,6 +1612,7 @@ static cc_command_handler &get_cc_command(const cryptonote::cc_command_t &cmd)
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_give_t &cmd) const { return cc_command_handler_give::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_ignore_t &cmd) const { return cc_command_handler_ignore::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_match_t &cmd) const { return cc_command_handler_match::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_new_event_badge_t &cmd) const { return cc_command_handler_new_event_badge::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_new_item_t &cmd) const { return cc_command_handler_new_item::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_none_t &cmd) const { return cc_command_handler_none::instance; }
|
||||
cc_command_handler &operator()(const cryptonote::cc_command_rename_t &cmd) const { return cc_command_handler_rename::instance; }
|
||||
|
66
src/cc/cc_badge.cpp
Normal file
66
src/cc/cc_badge.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "sqrtint.h"
|
||||
#include "cc_badge.h"
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *name;
|
||||
const char *desc;
|
||||
} predefined_badges_data[cc::NUM_PREDEFINED_BADGES] = {
|
||||
{}, // none
|
||||
{
|
||||
"Builder",
|
||||
"Max number of buildings",
|
||||
},
|
||||
{
|
||||
"Experimenter",
|
||||
"Max number of building types",
|
||||
},
|
||||
{
|
||||
"Hoarder",
|
||||
"Number of blocks in inventory",
|
||||
},
|
||||
{
|
||||
"Steadfast",
|
||||
"Overall size of military buildings",
|
||||
},
|
||||
{
|
||||
"Cultured",
|
||||
"Overall size of cultural buildings",
|
||||
},
|
||||
};
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
bool get_badge_data(const cryptonote::BlockchainDB &db, cc_badge_t badge, cc_badge_data_t &data)
|
||||
{
|
||||
if (badge < BADGE_FIRST || badge >= NUM_BADGES)
|
||||
return false;
|
||||
|
||||
// predefined
|
||||
if (badge < NUM_PREDEFINED_BADGES)
|
||||
{
|
||||
data.id = badge;
|
||||
data.name = predefined_badges_data[badge].name;
|
||||
data.desc = predefined_badges_data[badge].desc;
|
||||
return true;
|
||||
}
|
||||
|
||||
// event
|
||||
if (!db.get_cc_event_badge_data(badge, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<uint32_t, uint32_t> get_badge_score(const std::vector<uint32_t> badges)
|
||||
{
|
||||
if (badges.size() != NUM_BADGE_LEVELS)
|
||||
return std::make_pair(0, 0);
|
||||
uint32_t score = badges[0] + badges[1] * 2 + badges[2] * 5 + badges[3] * 10 + badges[4] * 25;
|
||||
uint32_t level = sqrtint(score);
|
||||
return std::make_pair(score, level);
|
||||
}
|
||||
|
||||
}
|
44
src/cc/cc_badge.h
Normal file
44
src/cc/cc_badge.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
class BlockchainDB;
|
||||
}
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
#define NUM_BADGE_LEVELS 5
|
||||
|
||||
enum cc_badge_t
|
||||
{
|
||||
BADGE_NONE = 0,
|
||||
BADGE_FIRST = 1,
|
||||
|
||||
BADGE_BUILDER = BADGE_FIRST,
|
||||
BADGE_EXPERIMENTER,
|
||||
BADGE_HOARDER,
|
||||
BADGE_STEADFAST,
|
||||
BADGE_CULTURED,
|
||||
|
||||
BADGE_LAST = 4096 - 1,
|
||||
NUM_PREDEFINED_BADGES,
|
||||
|
||||
BADGE_FIRST_EVENT = NUM_PREDEFINED_BADGES,
|
||||
|
||||
BADGE_LAST_EVENT = 4096 + 4096 - 1,
|
||||
|
||||
NUM_BADGES
|
||||
};
|
||||
|
||||
struct cc_badge_data_t
|
||||
{
|
||||
uint32_t id;
|
||||
std::string name;
|
||||
std::string desc;
|
||||
};
|
||||
|
||||
bool get_badge_data(const cryptonote::BlockchainDB &db, cc_badge_t badge, cc_badge_data_t &data);
|
||||
std::pair<uint32_t, uint32_t> get_badge_score(const std::vector<uint32_t> badges);
|
||||
|
||||
}
|
@ -207,6 +207,24 @@ bool cc_command_handler_game_update::execute(cryptonote::BlockchainDB &db, const
|
||||
if (!execute_city(db, game.cities[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto &adj: game.badges)
|
||||
{
|
||||
cryptonote::cc_account_data_t data;
|
||||
if (!db.get_cc_account_data(adj.account, data))
|
||||
{
|
||||
MERROR("Failed to get account " << adj.account << " data");
|
||||
return false;
|
||||
}
|
||||
data.badges[adj.badge] += adj.delta_level;
|
||||
if (data.badges[adj.badge] == 0 || data.badges[adj.badge] > NUM_BADGE_LEVELS)
|
||||
{
|
||||
MERROR("Badge level out of range: " << data.badges[adj.badge]);
|
||||
return false;
|
||||
}
|
||||
db.set_cc_account_badges(adj.account, data.badges);
|
||||
}
|
||||
|
||||
db.add_cc_events(db.height() - 1, last_events);
|
||||
return true;
|
||||
}
|
||||
@ -308,6 +326,25 @@ bool cc_command_handler_game_update::revert(cryptonote::BlockchainDB &db, const
|
||||
|
||||
db.remove_cc_events(db.height() - 1);
|
||||
|
||||
for (const auto &adj: game.badges)
|
||||
{
|
||||
cryptonote::cc_account_data_t data;
|
||||
if (!db.get_cc_account_data(adj.account, data))
|
||||
{
|
||||
MERROR("Failed to get account " << adj.account << " data");
|
||||
return false;
|
||||
}
|
||||
if (data.badges[adj.badge] < adj.delta_level)
|
||||
{
|
||||
MERROR("Badge level out of range: " << data.badges[adj.badge] << ", adj " << (int)adj.delta_level);
|
||||
return false;
|
||||
}
|
||||
data.badges[adj.badge] -= adj.delta_level;
|
||||
if (data.badges[adj.badge] == 0)
|
||||
data.badges.erase(adj.badge);
|
||||
db.set_cc_account_badges(adj.account, data.badges);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < game.cities.size(); ++i)
|
||||
{
|
||||
const cryptonote::cc_command_game_update_t::city_t &city = game.cities[game.cities.size() - 1 - i];
|
||||
|
110
src/cc/cc_command_handler_new_event_badge.cpp
Normal file
110
src/cc/cc_command_handler_new_event_badge.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2019, Crypto City
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "cc/cc.h"
|
||||
#include "cc_command_handler_new_event_badge.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
cc_command_handler_new_event_badge cc_command_handler_new_event_badge::instance;
|
||||
|
||||
void cc_command_handler_new_event_badge::get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const
|
||||
{
|
||||
cc_in = 0;
|
||||
cc_out = 0;
|
||||
}
|
||||
|
||||
uint64_t cc_command_handler_new_event_badge::get_cost(const cryptonote::cc_command_t &cmd) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cc_command_handler_new_event_badge::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, cryptonote::tx_verification_context &tvc) const
|
||||
{
|
||||
const cryptonote::cc_command_new_event_badge_t &new_event_badge = boost::get<cryptonote::cc_command_new_event_badge_t>(cmd);
|
||||
std::string error;
|
||||
uint32_t type, id;
|
||||
|
||||
CHECK_COMMAND_SET(new_event_badge.name.size() <= MAX_CC_NAME_LENGTH, tvc.m_cc_too_large, "Name is too long");
|
||||
CHECK_COMMAND_SET(!db.is_cc_name_used(new_event_badge.name, type, id), tvc.m_cc_conflict, "Name already taken");
|
||||
CHECK_COMMAND_SET(new_event_badge.description.size() <= MAX_CC_ITEM_DESCRIPTION_LENGTH, tvc.m_cc_too_large, "Description is too long");
|
||||
CHECK_COMMAND_SET(cc::validate_item_name(new_event_badge.name, error), tvc.m_cc_forbidden_character, error);
|
||||
for (const auto &e: new_event_badge.instances)
|
||||
{
|
||||
CHECK_COMMAND_SET(e.level > 0 && e.level <= NUM_BADGE_LEVELS, tvc.m_cc_out_of_range, "Level out of range");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cc_command_handler_new_event_badge::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const
|
||||
{
|
||||
const cryptonote::cc_command_new_event_badge_t &new_event_badge = boost::get<cryptonote::cc_command_new_event_badge_t>(cmd);
|
||||
|
||||
const uint32_t id = db.allocate_new_cc_event_badge(new_event_badge.name, new_event_badge.description);
|
||||
CHECK_AND_ASSERT_MES(id >= BADGE_FIRST_EVENT && id <= BADGE_LAST_EVENT, false, "Badge creation failed");
|
||||
|
||||
for (const auto &e: new_event_badge.instances)
|
||||
{
|
||||
cryptonote::cc_account_data_t data;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_account_data(e.account_id, data), false, "Failed to get account data");
|
||||
data.badges[id] = e.level;
|
||||
db.set_cc_account_badges(e.account_id, data.badges);
|
||||
}
|
||||
|
||||
db.add_cc_name(new_event_badge.name, NAME_TYPE_EVENT_BADGE, id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cc_command_handler_new_event_badge::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const
|
||||
{
|
||||
const cryptonote::cc_command_new_event_badge_t &new_event_badge = boost::get<cryptonote::cc_command_new_event_badge_t>(cmd);
|
||||
|
||||
uint32_t type, id;
|
||||
CHECK_AND_ASSERT_MES(db.is_cc_name_used(new_event_badge.name, type, id), false, "Badge not found");
|
||||
CHECK_AND_ASSERT_MES(type == NAME_TYPE_EVENT_BADGE, false, "Name is not registered to a badge");
|
||||
|
||||
for (const auto &e: new_event_badge.instances)
|
||||
{
|
||||
cryptonote::cc_account_data_t data;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_account_data(e.account_id, data), false, "Failed to get account data");
|
||||
CHECK_AND_ASSERT_MES(data.badges.find(id) != data.badges.end(), false, "Player does not have the expected badge");
|
||||
CHECK_AND_ASSERT_MES(data.badges[id] == e.level, false, "Player does not have the expected badge level");
|
||||
data.badges.erase(id);
|
||||
db.set_cc_account_badges(e.account_id, data.badges);
|
||||
}
|
||||
|
||||
db.delete_cc_event_badge(id);
|
||||
db.remove_cc_name(new_event_badge.name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
48
src/cc/cc_command_handler_new_event_badge.h
Normal file
48
src/cc/cc_command_handler_new_event_badge.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2019, Crypto City
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cc_command_handler.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
class cc_command_handler_new_event_badge: public cc_command_handler
|
||||
{
|
||||
public:
|
||||
virtual void get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const;
|
||||
virtual uint64_t get_cost(const cryptonote::cc_command_t &cmd) const;
|
||||
virtual bool check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, cryptonote::tx_verification_context &tvc) const;
|
||||
virtual bool execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const;
|
||||
virtual bool revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const;
|
||||
|
||||
static cc_command_handler_new_event_badge instance;
|
||||
};
|
||||
|
||||
}
|
@ -93,6 +93,7 @@
|
||||
|
||||
#define NAME_TYPE_PLAYER 1
|
||||
#define NAME_TYPE_CUSTOM_ITEM 2
|
||||
#define NAME_TYPE_EVENT_BADGE 3
|
||||
|
||||
enum BuildingRole
|
||||
{
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "cc_discoveries.h"
|
||||
#include "cc_game_events.h"
|
||||
#include "cc_special_events.h"
|
||||
#include "cc_badge.h"
|
||||
#include "cc_game_update.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
@ -197,6 +198,26 @@ static void pick_point_border(uint32_t &x, uint32_t &y, uint32_t x0, uint32_t y0
|
||||
}
|
||||
}
|
||||
|
||||
static void award_badge(const cryptonote::BlockchainDB &db, cc_command_game_update_t &cg, cc::game_update_events_t &events, const cryptonote::cc_account_data_t &ad, cc::cc_badge_t badge, uint64_t value, const uint64_t thresholds[NUM_BADGE_LEVELS])
|
||||
{
|
||||
for (uint8_t level = NUM_BADGE_LEVELS; level > 0; --level)
|
||||
{
|
||||
if (value >= thresholds[level - 1])
|
||||
{
|
||||
const auto it = ad.badges.find(badge);
|
||||
uint8_t cur = it == ad.badges.end() ? 0 : it->second;
|
||||
if (level > cur)
|
||||
{
|
||||
cc::cc_badge_data_t bd;
|
||||
cc::get_badge_data(db, badge, bd);
|
||||
events.add(ad.id, 0) << "Awarded badge '" << bd.name << "' level " << (unsigned)level;
|
||||
cg.badges.push_back({ad.id, badge, (uint8_t)(level - cur)});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
@ -1032,6 +1053,65 @@ static void add_cities(const BlockchainDB &db, cc_command_game_update_t &cg, gam
|
||||
id = e.first.first;
|
||||
id2 = e.first.second;
|
||||
}
|
||||
|
||||
// badges
|
||||
std::map<uint32_t, cc_account_data_t> account_data;
|
||||
std::map<uint32_t, cc_flag_data_t> flag_data;
|
||||
CHECK_AND_ASSERT_THROW_MES(db.for_all_cc_accounts([&account_data](const cc_account_data_t &data) {
|
||||
account_data[data.id] = data;
|
||||
return true;
|
||||
}), "Failed to enumerate accounts");
|
||||
CHECK_AND_ASSERT_THROW_MES(db.for_all_cc_flags([&flag_data](const cc_flag_data_t &data) {
|
||||
flag_data[data.id] = data;
|
||||
return true;
|
||||
}), "Failed to enumerate flags");
|
||||
|
||||
static const uint64_t builder_thresholds[NUM_BADGE_LEVELS] = {3, 10, 30, 100, 350};
|
||||
static const uint64_t experimenter_thresholds[NUM_BADGE_LEVELS] = {3, 5, 8, 11, 16};
|
||||
static const uint64_t hoarder_thresholds[NUM_BADGE_LEVELS] = {100000ull, 250000ull, 750000ull, 10000000ull, 50000000ull};
|
||||
static const uint64_t steadfast_thresholds[NUM_BADGE_LEVELS] = {200000ull, 500000ull, 2000000ull, 5000000ull, 15000000ull};
|
||||
static const uint64_t cultured_thresholds[NUM_BADGE_LEVELS] = {200000ull, 500000ull, 2000000ull, 5000000ull, 15000000ull};
|
||||
for (const auto &e: account_data)
|
||||
{
|
||||
const uint32_t account_id = e.first;
|
||||
const cc_account_data_t &ad = e.second;
|
||||
uint64_t n_buildings = 0;
|
||||
uint64_t n_military_shares = 0, n_cultural_shares = 0;
|
||||
uint64_t n_blocks = 0;
|
||||
uint64_t roles = 0;
|
||||
for (uint32_t flag_id: ad.flags)
|
||||
{
|
||||
const auto it = flag_data.find(flag_id);
|
||||
if (it != flag_data.end())
|
||||
{
|
||||
const cc_flag_data_t &fd = it->second;
|
||||
if (fd.role != ROLE_EMPTY)
|
||||
{
|
||||
++n_buildings;
|
||||
roles |= 1 << fd.role;
|
||||
}
|
||||
if (fd.role == ROLE_MILITARY)
|
||||
n_military_shares += cc::get_shares(fd.x0, fd.y0, fd.x1, fd.y1, fd.role, fd.economic_power, fd.repair, 100);
|
||||
if (fd.role == ROLE_CULTURAL)
|
||||
n_cultural_shares += cc::get_shares(fd.x0, fd.y0, fd.x1, fd.y1, fd.role, fd.economic_power, fd.repair, 100);
|
||||
}
|
||||
else
|
||||
MERROR("Flag " << flag_id << " not found, inconsistent blockchain database");
|
||||
}
|
||||
for (const auto &e: ad.item_balances)
|
||||
if (e.first >= ITEM_FIRST_BLOCK && e.first <= ITEM_LAST_BLOCK)
|
||||
n_blocks += e.second;
|
||||
uint64_t n_roles = 0;
|
||||
for (int i = 1; i < 63; ++i)
|
||||
if ((roles >> i) & 1)
|
||||
++n_roles;
|
||||
|
||||
award_badge(db, cg, events, ad, BADGE_BUILDER, n_buildings, builder_thresholds);
|
||||
award_badge(db, cg, events, ad, BADGE_EXPERIMENTER, n_roles, experimenter_thresholds);
|
||||
award_badge(db, cg, events, ad, BADGE_HOARDER, n_blocks, hoarder_thresholds);
|
||||
award_badge(db, cg, events, ad, BADGE_STEADFAST, n_military_shares, steadfast_thresholds);
|
||||
award_badge(db, cg, events, ad, BADGE_CULTURED, n_cultural_shares, cultured_thresholds);
|
||||
}
|
||||
}
|
||||
|
||||
cc_command_game_update_t create_cc_game_update_command(const BlockchainDB &db, game_update_events_t &events, bool use_cache)
|
||||
|
@ -59,6 +59,7 @@ const cc_command_base_t *get_cc_command_base(const cc_command_t &cmd)
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_give_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_ignore_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_match_t &cmd) const { return NULL; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_new_event_badge_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_new_item_t &cmd) const { return &cmd; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_none_t &cmd) const { return NULL; }
|
||||
const cc_command_base_t *operator()(const cryptonote::cc_command_rename_t &cmd) const { return &cmd; }
|
||||
@ -88,6 +89,7 @@ cc_command_base_t *get_cc_command_base(cc_command_t &cmd)
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_give_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_ignore_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_match_t &cmd) const { return NULL; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_new_event_badge_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_new_item_t &cmd) const { return &cmd; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_none_t &cmd) const { return NULL; }
|
||||
cc_command_base_t *operator()(cryptonote::cc_command_rename_t &cmd) const { return &cmd; }
|
||||
|
@ -461,6 +461,31 @@ namespace cryptonote
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct cc_command_new_event_badge_t: public cc_command_base_t
|
||||
{
|
||||
struct badge_t
|
||||
{
|
||||
uint32_t account_id;
|
||||
uint8_t level;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VARINT_FIELD(account_id)
|
||||
FIELD(level)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::vector<badge_t> instances;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELDS(*static_cast<cc_command_base_t*>(this))
|
||||
FIELD(name)
|
||||
FIELD(description)
|
||||
FIELD(instances)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct cc_command_game_update_t
|
||||
{
|
||||
struct flag_t
|
||||
@ -568,6 +593,19 @@ namespace cryptonote
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct badge_t
|
||||
{
|
||||
uint32_t account;
|
||||
uint32_t badge;
|
||||
uint8_t delta_level;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VARINT_FIELD(account)
|
||||
VARINT_FIELD(badge)
|
||||
FIELD(delta_level)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct city_t
|
||||
{
|
||||
uint32_t city_id;
|
||||
@ -600,6 +638,7 @@ namespace cryptonote
|
||||
};
|
||||
|
||||
std::vector<city_t> cities;
|
||||
std::vector<badge_t> badges;
|
||||
|
||||
static std::string test_payload_template;
|
||||
std::string test_payload;
|
||||
@ -609,6 +648,7 @@ namespace cryptonote
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(cities)
|
||||
FIELD(badges)
|
||||
if (!test_payload_template.empty())
|
||||
{
|
||||
test_payload = test_payload_template;
|
||||
@ -638,7 +678,8 @@ namespace cryptonote
|
||||
cc_command_match_t,
|
||||
cc_command_new_item_t,
|
||||
cc_command_dividend_t,
|
||||
cc_command_ignore_t
|
||||
cc_command_ignore_t,
|
||||
cc_command_new_event_badge_t
|
||||
> cc_command_t;
|
||||
|
||||
cc_command_base_t *get_cc_command_base(cc_command_t &cmd);
|
||||
@ -750,6 +791,7 @@ CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_match_t, (uint8_t)0x11);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_new_item_t, (uint8_t)0x12);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_dividend_t, (uint8_t)0x13);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_ignore_t, (uint8_t)0x14);
|
||||
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_new_event_badge_t, (uint8_t)0x15);
|
||||
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_none_t, (const char*)"none");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_create_account_t, (const char*)"create_account");
|
||||
@ -772,6 +814,7 @@ CC_VARIANT_TAG(json_archive, cryptonote::cc_command_match_t, (const char*)"match
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_new_item_t, (const char*)"new_item");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_dividend_t, (const char*)"dividend");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_ignore_t, (const char*)"ignore");
|
||||
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_new_event_badge_t, (const char*)"new_event_badge");
|
||||
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_none_t, "none");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_create_account_t, "create_account");
|
||||
@ -794,3 +837,4 @@ VARIANT_TAG(debug_archive, cryptonote::cc_command_match_t, "match");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_new_item_t, "new_item");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_dividend_t, "dividend");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_ignore_t, "ignore");
|
||||
VARIANT_TAG(debug_archive, cryptonote::cc_command_new_event_badge_t, "new_event_badge");
|
||||
|
@ -106,11 +106,13 @@ struct cc_snapshot
|
||||
uint32_t id;
|
||||
std::string name;
|
||||
bool ignore;
|
||||
std::vector<uint32_t> badges;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(id)
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(ignore)
|
||||
KV_SERIALIZE(badges)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
@ -70,6 +70,8 @@ DISABLE_VS_WARNINGS(4355)
|
||||
// basically at least how many bytes the block itself serializes to without the miner tx
|
||||
#define BLOCK_SIZE_SANITY_LEEWAY 100
|
||||
|
||||
static uint32_t allow_gm_commands_from_account = GAME_ACCOUNT;
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
const command_line::arg_descriptor<bool, false> arg_testnet_on = {
|
||||
@ -222,6 +224,11 @@ namespace cryptonote
|
||||
, "Keep alternative blocks on restart"
|
||||
, false
|
||||
};
|
||||
const command_line::arg_descriptor<uint32_t> arg_debug_allow_gm_commands_from_account = {
|
||||
"debug-allow-gm-commands-from-account"
|
||||
, "Change which account may issue GM commands for testing purposes (do not use on real network)."
|
||||
, GAME_ACCOUNT
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
core::core(i_cryptonote_protocol* pprotocol):
|
||||
@ -342,6 +349,7 @@ namespace cryptonote
|
||||
command_line::add_arg(desc, arg_reorg_notify);
|
||||
command_line::add_arg(desc, arg_block_rate_notify);
|
||||
command_line::add_arg(desc, arg_keep_alt_blocks);
|
||||
command_line::add_arg(desc, arg_debug_allow_gm_commands_from_account);
|
||||
|
||||
miner::init_options(desc);
|
||||
BlockchainDB::init_options(desc);
|
||||
@ -389,6 +397,7 @@ namespace cryptonote
|
||||
test_drop_download();
|
||||
|
||||
epee::debug::g_test_dbg_lock_sleep() = command_line::get_arg(vm, arg_test_dbg_lock_sleep);
|
||||
allow_gm_commands_from_account = command_line::get_arg(vm, arg_debug_allow_gm_commands_from_account);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1190,12 +1199,13 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
// GM only commands
|
||||
if (tx.cc_cmd.type() == typeid(cc_command_ignore_t))
|
||||
if (tx.cc_cmd.type() == typeid(cc_command_ignore_t) || tx.cc_cmd.type() == typeid(cc_command_new_event_badge_t))
|
||||
{
|
||||
const cryptonote::cc_command_base_t *base = cryptonote::get_cc_command_base(tx.cc_cmd);
|
||||
if (!base || base->cc_account != GAME_ACCOUNT)
|
||||
if (!base || base->cc_account != allow_gm_commands_from_account)
|
||||
{
|
||||
MERROR_VER("Only the game account may issue ignore commands");
|
||||
MERROR_VER("Only the game account may issue this command");
|
||||
MERROR_VER("Allowed: " << allow_gm_commands_from_account << ", actual " << base->cc_account);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2478,6 +2478,10 @@ bool t_rpc_command_executor::cc_get_account(uint32_t id)
|
||||
ss << (ss.str().empty() ? "" : ", ") << e.type << ": " << e.amount;
|
||||
tools::success_msg_writer() << "Item balances: " << ss.str();
|
||||
tools::success_msg_writer() << "Flags: " << boost::join(res.flags | boost::adaptors::transformed([](uint32_t id){return std::to_string(id);}), " ");
|
||||
ss = {};
|
||||
for (const auto &e: res.badges)
|
||||
ss << (ss.str().empty() ? "" : ", ") << e.type << ": level " << (unsigned)(e.level + 1);
|
||||
tools::success_msg_writer() << "Badges: " << ss.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ void PlayerState::update(const std::shared_ptr<GameWallet> &wallet)
|
||||
id = w->get_cc_account();
|
||||
if (id)
|
||||
{
|
||||
w->get_cc_account_data(id, public_key, balance, item_balances, flags, name, ignored);
|
||||
w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, name, ignored);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -73,7 +73,8 @@ GameState::GameState(Urho3D::Context *ctx):
|
||||
events_timestamp(0),
|
||||
research_leaderboard("Discoveries"),
|
||||
building_activity_leaderboard("Building activity"),
|
||||
largest_buildings_leaderboard("Largest buildings")
|
||||
largest_buildings_leaderboard("Largest buildings"),
|
||||
badge_leaderboard("Badges")
|
||||
{
|
||||
}
|
||||
|
||||
@ -351,6 +352,11 @@ bool GameState::process_new_item(const cryptonote::cc_command_new_item_t &cmd, c
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameState::process_new_event_badge(const cryptonote::cc_command_new_event_badge_t &cmd, const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameState::process_none(const cryptonote::cc_command_none_t &cmd, const std::shared_ptr<GameWallet> &w)
|
||||
{
|
||||
return true;
|
||||
@ -439,6 +445,7 @@ bool GameState::process_command(const cryptonote::cc_command_t &cmd, const std::
|
||||
bool operator()(const cryptonote::cc_command_give_t &cmd) const { return self.process_give(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_ignore_t &cmd) const { return self.process_ignore(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_match_t &cmd) const { return self.process_match(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_new_event_badge_t &cmd) const { return self.process_new_event_badge(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_new_item_t &cmd) const { return self.process_new_item(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_none_t &cmd) const { return self.process_none(cmd, w); }
|
||||
bool operator()(const cryptonote::cc_command_rename_t &cmd) const { return self.process_rename(cmd, w); }
|
||||
@ -611,6 +618,29 @@ std::string GameState::get_city_name(uint32_t id) const
|
||||
return "City " + std::to_string(id);
|
||||
}
|
||||
|
||||
void GameState::get_badge_name_and_desc(uint32_t id, std::string &name, std::string &desc) const
|
||||
{
|
||||
auto i = badge_names.find(id);
|
||||
if (i == badge_names.end())
|
||||
{
|
||||
Urho3D::VariantMap newEventData;
|
||||
newEventData[RequestBadgeData::P_ID] = id;
|
||||
GameState *self = const_cast<GameState*>(this);
|
||||
self->SendEvent(E_CRYPTOCITY_REQUEST_BADGE_DATA, newEventData);
|
||||
}
|
||||
i = badge_names.find(id);
|
||||
if (i != badge_names.end())
|
||||
{
|
||||
name = i->second.first;
|
||||
desc = i->second.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "Badge " + std::to_string(id);
|
||||
desc = "";
|
||||
}
|
||||
}
|
||||
|
||||
void GameState::set_ignore(const tools::cc_ignore_t &ignore)
|
||||
{
|
||||
cc_ignore.reset(new tools::cc_ignore_t{});
|
||||
@ -661,6 +691,7 @@ bool GameState::reset(const cryptonote::cc_snapshot *snapshot)
|
||||
research_leaderboard.clear();
|
||||
building_activity_leaderboard.clear();
|
||||
largest_buildings_leaderboard.clear();
|
||||
badge_leaderboard.clear();
|
||||
if (snapshot)
|
||||
{
|
||||
uint32_t ox = cityState.ox, oy = cityState.oy;
|
||||
@ -737,7 +768,12 @@ bool GameState::reset(const cryptonote::cc_snapshot *snapshot)
|
||||
}
|
||||
|
||||
for (const auto &e: snapshot->player_data)
|
||||
{
|
||||
set_player_name(e.id, e.name, e.ignore);
|
||||
const auto score_level = cc::get_badge_score(e.badges);
|
||||
if (score_level.first > 0)
|
||||
badge_leaderboard.set_score(e.id, score_level.first);
|
||||
}
|
||||
|
||||
for (const auto &s: snapshot->shares)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@ URHO3D_EVENT(E_CRYPTOCITY_REQUEST_PLAYER_DATA, RequestPlayerData)
|
||||
URHO3D_PARAM(P_NAME, Name);
|
||||
URHO3D_PARAM(P_ITEM_BALANCES, ItemBalances);
|
||||
URHO3D_PARAM(P_FLAGS, Flags);
|
||||
URHO3D_PARAM(P_BADGES, Badges);
|
||||
}
|
||||
URHO3D_EVENT(E_CRYPTOCITY_REQUEST_ITEM_DATA, RequestItemData)
|
||||
{
|
||||
@ -30,6 +31,12 @@ URHO3D_EVENT(E_CRYPTOCITY_REQUEST_ITEM_DATA, RequestItemData)
|
||||
URHO3D_PARAM(P_PRIMARY_DESCRIPTION, PrimaryDescription);
|
||||
URHO3D_PARAM(P_SECONDARY_DESCRIPTION, SecondaryDescription);
|
||||
}
|
||||
URHO3D_EVENT(E_CRYPTOCITY_REQUEST_BADGE_DATA, RequestBadgeData)
|
||||
{
|
||||
URHO3D_PARAM(P_ID, ID);
|
||||
URHO3D_PARAM(P_NAME, Name);
|
||||
URHO3D_PARAM(P_DESCRIPTION, Description);
|
||||
}
|
||||
URHO3D_EVENT(E_CRYPTOCITY_GAME_NOTIFICATION, GameNotification) { URHO3D_PARAM(P_TEXT, Text); }
|
||||
|
||||
class GameWallet;
|
||||
@ -66,6 +73,7 @@ struct PlayerState
|
||||
std::string name;
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
bool has_wallet;
|
||||
bool ignored;
|
||||
|
||||
@ -88,10 +96,12 @@ public:
|
||||
uint64_t events_timestamp;
|
||||
std::map<uint32_t, std::pair<std::string, bool>> player_names;
|
||||
std::map<uint32_t, std::pair<std::string, bool>> item_names;
|
||||
std::map<uint32_t, std::pair<std::string, std::string>> badge_names;
|
||||
std::vector<cryptonote::city_t> cities;
|
||||
cc::leaderboard_t research_leaderboard;
|
||||
cc::leaderboard_t building_activity_leaderboard;
|
||||
cc::leaderboard_t largest_buildings_leaderboard;
|
||||
cc::leaderboard_t badge_leaderboard;
|
||||
std::shared_ptr<tools::cc_ignore_t> cc_ignore;
|
||||
|
||||
public:
|
||||
@ -104,10 +114,12 @@ public:
|
||||
bool reset(const cryptonote::cc_snapshot *snapshot = NULL);
|
||||
void set_player_name(uint32_t id, const std::string &name, bool ignore) { player_names[id] = std::make_pair(name, ignore); }
|
||||
void set_item_name(uint32_t id, const std::string &name, bool ignore) { item_names[id] = std::make_pair(name, ignore); }
|
||||
void set_badge_name_and_desc(uint32_t id, const std::string &name, const std::string &desc) { badge_names[id] = std::make_pair(name, desc); }
|
||||
std::string get_player_name(uint32_t id) const;
|
||||
std::string get_item_name(uint32_t id) const;
|
||||
std::string get_flag_name(uint32_t id) const;
|
||||
std::string get_city_name(uint32_t id) const;
|
||||
void get_badge_name_and_desc(uint32_t id, std::string &name, std::string &desc) const;
|
||||
void set_ignore(const tools::cc_ignore_t &ignore);
|
||||
void change_ignore(uint8_t type, uint32_t id);
|
||||
bool ignore_player(uint32_t id) const;
|
||||
@ -131,6 +143,7 @@ private:
|
||||
bool process_give(const cryptonote::cc_command_give_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_ignore(const cryptonote::cc_command_ignore_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_match(const cryptonote::cc_command_match_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_new_event_badge(const cryptonote::cc_command_new_event_badge_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_new_item(const cryptonote::cc_command_new_item_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_none(const cryptonote::cc_command_none_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
bool process_rename(const cryptonote::cc_command_rename_t &cmd, const std::shared_ptr<GameWallet> &w);
|
||||
|
@ -275,9 +275,11 @@ public:
|
||||
void requestSnapshot(uint32_t city_id);
|
||||
uint32_t get_cc_account();
|
||||
bool get_cc_account_data(uint32_t id, std::string &name);
|
||||
bool get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::string &name, bool &ignore);
|
||||
bool get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges, std::string &name, bool &ignore);
|
||||
bool get_cc_custom_item_data(uint32_t id, std::string &name);
|
||||
bool get_cc_custom_item_data(uint32_t id, uint32_t &amount, std::string &name, std::string &primary_description, std::string &secondary_description, bool &ignore);
|
||||
bool get_cc_badge_data(uint32_t id, cc::cc_badge_data_t &data);
|
||||
bool get_cc_badge_totals(std::vector<std::pair<uint32_t, std::vector<uint32_t>>> &badges);
|
||||
bool get_last_update_events(uint64_t &block_height, uint64_t ×tamp, cc::game_update_events_t &events);
|
||||
bool send_command(const cryptonote::cc_command_t &cmd, uint64_t *nonce = NULL);
|
||||
void set_attribute(const std::string &key, const std::string &value);
|
||||
@ -867,9 +869,9 @@ uint32_t GameWalletInternal::get_cc_account()
|
||||
return w->get_cc_account();
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::string &name, bool &ignore)
|
||||
bool GameWalletInternal::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges, std::string &name, bool &ignore)
|
||||
{
|
||||
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, name, ignore))
|
||||
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, name, ignore))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -879,9 +881,10 @@ bool GameWalletInternal::get_cc_account_data(uint32_t id, std::string &name)
|
||||
uint64_t balance;
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
std::string public_key;
|
||||
bool ignore;
|
||||
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, name, ignore))
|
||||
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, name, ignore))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -912,6 +915,16 @@ bool GameWalletInternal::get_cc_custom_item_data(uint32_t id, std::string &name)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_badge_data(uint32_t id, cc::cc_badge_data_t &data)
|
||||
{
|
||||
return w->get_cc_badge_data(id, data);
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_badge_totals(std::vector<std::pair<uint32_t, std::vector<uint32_t>>> &badges)
|
||||
{
|
||||
return w->get_cc_badge_totals(badges);
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_last_update_events(uint64_t &block_height, uint64_t ×tamp, cc::game_update_events_t &events)
|
||||
{
|
||||
crypto::hash block_hash;
|
||||
@ -1354,9 +1367,9 @@ bool GameWallet::get_cc_account_data(uint32_t id, std::string &name)
|
||||
return internal->get_cc_account_data(id, name);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::string &name, bool &ignore)
|
||||
bool GameWallet::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges, std::string &name, bool &ignore)
|
||||
{
|
||||
return internal->get_cc_account_data(id, public_key, balance, item_balances, flags, name, ignore);
|
||||
return internal->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, name, ignore);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_custom_item_data(uint32_t id, uint32_t &amount, std::string &name, std::string &primary_description, std::string &secondary_description, bool &ignore)
|
||||
@ -1369,6 +1382,16 @@ bool GameWallet::get_cc_custom_item_data(uint32_t id, std::string &name)
|
||||
return internal->get_cc_custom_item_data(id, name);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_badge_data(uint32_t id, cc::cc_badge_data_t &data)
|
||||
{
|
||||
return internal->get_cc_badge_data(id, data);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_badge_totals(std::vector<std::pair<uint32_t, std::vector<uint32_t>>> &badges)
|
||||
{
|
||||
return internal->get_cc_badge_totals(badges);
|
||||
}
|
||||
|
||||
bool GameWallet::get_last_update_events(uint64_t &block_height, uint64_t ×tamp, cc::game_update_events_t &events)
|
||||
{
|
||||
return internal->get_last_update_events(block_height, timestamp, events);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <Urho3D/Core/StringUtils.h>
|
||||
#include "cc/cc_game_events.h"
|
||||
#include "cc/cc_custom_item.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "cryptonote_basic/cc_command_defs.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
@ -46,9 +47,11 @@ public:
|
||||
void requestSnapshot(uint32_t city_id);
|
||||
uint32_t get_cc_account();
|
||||
bool get_cc_account_data(uint32_t id, std::string &name);
|
||||
bool get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::string &name, bool &ignore);
|
||||
bool get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges, std::string &name, bool &ignore);
|
||||
bool get_cc_custom_item_data(uint32_t id, std::string &name);
|
||||
bool get_cc_custom_item_data(uint32_t id, uint32_t &amount, std::string &name, std::string &primary_description, std::string &secondary_description, bool &ignore);
|
||||
bool get_cc_badge_data(uint32_t id, cc::cc_badge_data_t &data);
|
||||
bool get_cc_badge_totals(std::vector<std::pair<uint32_t, std::vector<uint32_t>>> &badges);
|
||||
bool get_last_update_events(uint64_t &block_height, uint64_t ×tamp, cc::game_update_events_t &events);
|
||||
bool send_command(const cryptonote::cc_command_t &cmd, uint64_t *nonce = NULL);
|
||||
void set_attribute(const std::string &key, const std::string &value);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "misc_log_ex.h"
|
||||
#include "common/util.h"
|
||||
#include "cc/cc.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "selection.h"
|
||||
#include "game-util.h"
|
||||
#include "game-wallet.h"
|
||||
@ -171,6 +172,7 @@ public:
|
||||
void HandleGetGameUpdateEvents(StringHash eventType, VariantMap& eventData);
|
||||
void HandleRequestPlayerData(StringHash eventType, VariantMap& eventData);
|
||||
void HandleRequestItemData(StringHash eventType, VariantMap& eventData);
|
||||
void HandleRequestBadgeData(StringHash eventType, VariantMap& eventData);
|
||||
void HandleConsoleCommand(StringHash eventType, VariantMap& eventData);
|
||||
void HandleChat(StringHash eventType, VariantMap& eventData);
|
||||
void HandleResearch(StringHash eventType, VariantMap& eventData);
|
||||
@ -731,6 +733,7 @@ void CryptoCityUrho3D::SetupUI()
|
||||
SubscribeToEvent(ui, E_CRYPTOCITY_GROUND_TYPE, URHO3D_HANDLER(CryptoCityUrho3D, HandleGroundType));
|
||||
SubscribeToEvent(&gameState, E_CRYPTOCITY_REQUEST_PLAYER_DATA, URHO3D_HANDLER(CryptoCityUrho3D, HandleRequestPlayerData));
|
||||
SubscribeToEvent(&gameState, E_CRYPTOCITY_REQUEST_ITEM_DATA, URHO3D_HANDLER(CryptoCityUrho3D, HandleRequestItemData));
|
||||
SubscribeToEvent(&gameState, E_CRYPTOCITY_REQUEST_BADGE_DATA, URHO3D_HANDLER(CryptoCityUrho3D, HandleRequestBadgeData));
|
||||
SubscribeToEvent(&gameState, E_CRYPTOCITY_GAME_NOTIFICATION, URHO3D_HANDLER(CryptoCityUrho3D, HandleGameNotification));
|
||||
SubscribeToEvent(console, E_UI_CONSOLE_COMMAND, URHO3D_HANDLER(CryptoCityUrho3D, HandleConsoleCommand));
|
||||
}
|
||||
@ -3537,6 +3540,14 @@ static VariantMap make_flag_variant(const uint32_t id)
|
||||
return v;
|
||||
}
|
||||
|
||||
static VariantMap make_badge_variant(const std::pair<uint32_t, uint8_t> &e)
|
||||
{
|
||||
VariantMap v;
|
||||
v["id"] = e.first;
|
||||
v["level"] = e.second;
|
||||
return v;
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleRequestPlayerData(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
if (wallet)
|
||||
@ -3547,8 +3558,9 @@ void CryptoCityUrho3D::HandleRequestPlayerData(StringHash eventType, VariantMap&
|
||||
uint64_t balance;
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
bool ignore;
|
||||
if (wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, name, ignore))
|
||||
if (wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, name, ignore))
|
||||
{
|
||||
gameState.set_player_name(id, name, ignore);
|
||||
|
||||
@ -3559,6 +3571,8 @@ void CryptoCityUrho3D::HandleRequestPlayerData(StringHash eventType, VariantMap&
|
||||
eventData[RequestPlayerData::P_ITEM_BALANCES] = ItemBalances;
|
||||
Vector<VariantMap> Flags; for (uint32_t id: flags) Flags.Push(make_flag_variant(id));
|
||||
eventData[RequestPlayerData::P_FLAGS] = Flags;
|
||||
Vector<VariantMap> Badges; for (const auto &e: badges) Badges.Push(make_badge_variant(e));
|
||||
eventData[RequestPlayerData::P_BADGES] = Badges;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3584,6 +3598,23 @@ void CryptoCityUrho3D::HandleRequestItemData(StringHash eventType, VariantMap& e
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleRequestBadgeData(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
if (wallet)
|
||||
{
|
||||
const uint32_t id = eventData[RequestBadgeData::P_ID].GetUInt();
|
||||
cc::cc_badge_data_t data;
|
||||
if (wallet->get_cc_badge_data(id, data))
|
||||
{
|
||||
gameState.set_badge_name_and_desc(id, data.name, data.desc);
|
||||
|
||||
eventData[RequestBadgeData::P_ID] = id;
|
||||
eventData[RequestBadgeData::P_NAME] = data.name.c_str();
|
||||
eventData[RequestBadgeData::P_DESCRIPTION] = data.desc.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleConsoleCommand(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> w = wallet->wallet();
|
||||
|
@ -70,10 +70,13 @@ UILeaderboardsDialog::UILeaderboardsDialog(Context *ctx, const GameState *game):
|
||||
buildingActivitySearchWidget = GetWidgetByIDAndType<TBEditField>("building-activity-search");
|
||||
largestBuildingsList = GetWidgetByIDAndType<TBSelectList>("largest-buildings");
|
||||
largestBuildingsSearchWidget = GetWidgetByIDAndType<TBEditField>("largest-buildings-search");
|
||||
badgesList = GetWidgetByIDAndType<TBSelectList>("badges");
|
||||
badgesSearchWidget = GetWidgetByIDAndType<TBEditField>("badges-search");
|
||||
|
||||
discoveriesList->SetSource(&discoveriesLeaderboardSource);
|
||||
buildingActivityList->SetSource(&buildingActivityLeaderboardSource);
|
||||
largestBuildingsList->SetSource(&largestBuildingsLeaderboardSource);
|
||||
badgesList->SetSource(&badgesLeaderboardSource);
|
||||
|
||||
UpdateDiscoveries();
|
||||
UpdateBuildingActivity();
|
||||
@ -88,6 +91,7 @@ UILeaderboardsDialog::~UILeaderboardsDialog()
|
||||
discoveriesList->SetSource(NULL);
|
||||
buildingActivityList->SetSource(NULL);
|
||||
largestBuildingsList->SetSource(NULL);
|
||||
badgesList->SetSource(NULL);
|
||||
}
|
||||
|
||||
void UILeaderboardsDialog::RegisterObject(Context* context)
|
||||
@ -138,6 +142,11 @@ void UILeaderboardsDialog::UpdateLargestBuildings()
|
||||
UpdateLeaderboard(largestBuildingsLeaderboardSource, game->largest_buildings_leaderboard, true);
|
||||
}
|
||||
|
||||
void UILeaderboardsDialog::UpdateBadges()
|
||||
{
|
||||
UpdateLeaderboard(badgesLeaderboardSource, game->badge_leaderboard, false);
|
||||
}
|
||||
|
||||
void UILeaderboardsDialog::Update()
|
||||
{
|
||||
if (refresh || game->top_hash != last_refresh_stop_hash)
|
||||
@ -145,6 +154,7 @@ void UILeaderboardsDialog::Update()
|
||||
UpdateDiscoveries();
|
||||
UpdateBuildingActivity();
|
||||
UpdateLargestBuildings();
|
||||
UpdateBadges();
|
||||
refresh = false;
|
||||
last_refresh_stop_hash = game->top_hash;
|
||||
}
|
||||
@ -173,6 +183,7 @@ void UILeaderboardsDialog::HandleTBMessage(StringHash eventType, VariantMap& eve
|
||||
CONNECT("discoveries-search", [this](StringHash, VariantMap&) { discoveriesList->SetFilter(discoveriesSearchWidget->GetText()); });
|
||||
CONNECT("building-activity-search", [this](StringHash, VariantMap&) { buildingActivityList->SetFilter(buildingActivitySearchWidget->GetText()); });
|
||||
CONNECT("largest-buildings-search", [this](StringHash, VariantMap&) { largestBuildingsList->SetFilter(largestBuildingsSearchWidget->GetText()); });
|
||||
CONNECT("badges-search", [this](StringHash, VariantMap&) { badgesList->SetFilter(badgesSearchWidget->GetText()); });
|
||||
}
|
||||
|
||||
#undef CONNECT
|
||||
|
@ -45,6 +45,7 @@ private:
|
||||
void UpdateDiscoveries();
|
||||
void UpdateBuildingActivity();
|
||||
void UpdateLargestBuildings();
|
||||
void UpdateBadges();
|
||||
void Refresh();
|
||||
void Filter();
|
||||
|
||||
@ -60,6 +61,8 @@ private:
|
||||
tb::TBEditField *buildingActivitySearchWidget;
|
||||
tb::TBSelectList *largestBuildingsList;
|
||||
tb::TBEditField *largestBuildingsSearchWidget;
|
||||
tb::TBSelectList *badgesList;
|
||||
tb::TBEditField *badgesSearchWidget;
|
||||
|
||||
class LeaderboardItem: public tb::TBGenericStringItem
|
||||
{
|
||||
@ -95,6 +98,7 @@ private:
|
||||
LeaderboardSource discoveriesLeaderboardSource;
|
||||
LeaderboardSource buildingActivityLeaderboardSource;
|
||||
LeaderboardSource largestBuildingsLeaderboardSource;
|
||||
LeaderboardSource badgesLeaderboardSource;
|
||||
|
||||
std::string last_refresh_stop_hash;
|
||||
bool refresh;
|
||||
|
@ -579,6 +579,7 @@ UIPlayerInfoDialog::UIPlayerInfoDialog(Context *ctx, const GameState *game, uint
|
||||
columnsWidget = GetWidgetByIDAndType<TBSelectDropdown>(TBIDC("columns"));
|
||||
discoveriesWidget = GetWidgetByIDAndType<TBSelectList>(TBIDC("discoveries"));
|
||||
discoveriesSearchWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("discoveries-search"));
|
||||
badgesWidget = GetWidgetByIDAndType<TBSelectList>(TBIDC("badges"));
|
||||
|
||||
flagsWidget->SetHeader(flagsHeaderWidget = new FlagListHeaderWidget(context_), true);
|
||||
SubscribeToEvent(flagsHeaderWidget, E_LIST_HEADER_RESIZED, URHO3D_HANDLER(UIPlayerInfoDialog, HandleListHeaderResized));
|
||||
@ -587,6 +588,7 @@ UIPlayerInfoDialog::UIPlayerInfoDialog(Context *ctx, const GameState *game, uint
|
||||
flagsWidget->SetSource(&flag_source);
|
||||
discoveriesWidget->SetSource(&discovery_source);
|
||||
columnsWidget->SetSource(&columns_source);
|
||||
badgesWidget->SetSource(&badge_source);
|
||||
|
||||
InitColumnsList();
|
||||
|
||||
@ -611,6 +613,7 @@ UIPlayerInfoDialog::~UIPlayerInfoDialog()
|
||||
flagsWidget->SetSource(NULL);
|
||||
discoveriesWidget->SetSource(NULL);
|
||||
columnsWidget->SetSource(NULL);
|
||||
badgesWidget->SetHeader(NULL);
|
||||
flagsWidget->SetHeader(NULL);
|
||||
if (flagsHeaderWidget)
|
||||
{
|
||||
@ -654,6 +657,7 @@ void UIPlayerInfoDialog::FillData(const std::shared_ptr<GameWallet> &w, uint32_t
|
||||
uint64_t balance = eventData[RequestPlayerData::P_BALANCE].GetUInt64();
|
||||
Vector<VariantMap> item_balances = eventData[RequestPlayerData::P_ITEM_BALANCES].GetVariantMapVector();
|
||||
Vector<VariantMap> flags = eventData[RequestPlayerData::P_FLAGS].GetVariantMapVector();
|
||||
Vector<VariantMap> badges = eventData[RequestPlayerData::P_BADGES].GetVariantMapVector();
|
||||
player_name = name.CString();
|
||||
public_key = eventData[RequestPlayerData::P_PUBLIC_KEY].GetString().CString();
|
||||
|
||||
@ -695,6 +699,18 @@ void UIPlayerInfoDialog::FillData(const std::shared_ptr<GameWallet> &w, uint32_t
|
||||
discovery_source.AddItem(new DiscoveryItem(discovery, game->top_height));
|
||||
}
|
||||
}
|
||||
|
||||
badge_source.DeleteAllItems();
|
||||
for (const auto &e: badges)
|
||||
{
|
||||
const uint32_t badge_id = e["id"]->GetUInt();
|
||||
const uint8_t level = e["level"]->GetUInt();
|
||||
std::string name, desc;
|
||||
game->get_badge_name_and_desc(badge_id, name, desc);
|
||||
const std::string s = name + ": level " + std::to_string(level);
|
||||
badge_source.AddItem(new TBGenericStringItem(s.c_str()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UIPlayerInfoDialog::HandleGiveItems(StringHash eventType, VariantMap& eventData)
|
||||
|
@ -173,6 +173,7 @@ private:
|
||||
tb::TBSelectList *discoveriesWidget;
|
||||
tb::TBEditField *discoveriesSearchWidget;
|
||||
tb::TBSelectDropdown *columnsWidget;
|
||||
tb::TBSelectList *badgesWidget;
|
||||
|
||||
uint32_t player_id;
|
||||
std::string last_refresh_stop_hash;
|
||||
@ -184,6 +185,7 @@ private:
|
||||
FlagSource flag_source;
|
||||
DiscoverySource discovery_source;
|
||||
ColumnsSource columns_source;
|
||||
tb::TBGenericStringItemSource badge_source;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -62,6 +62,7 @@ using namespace epee;
|
||||
#include "cc/cc_influence.h"
|
||||
#include "cc/cc_game_events.h"
|
||||
#include "cc/cc_discoveries.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "cc/cc_command_handler_game_update.h"
|
||||
#include "version.h"
|
||||
|
||||
@ -3429,6 +3430,8 @@ namespace cryptonote
|
||||
if (e.second > 0)
|
||||
res.item_balances.push_back({e.first, e.second});
|
||||
res.flags = std::move(data.flags);
|
||||
for (const auto &e: data.badges)
|
||||
res.badges.push_back({e.first, e.second});
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@ -3801,7 +3804,11 @@ namespace cryptonote
|
||||
cryptonote::cc_account_data_t data;
|
||||
if (db.get_cc_account_data(account_id, data))
|
||||
{
|
||||
res.snapshot.player_data.push_back({account_id, std::move(data.name), data.ignore});
|
||||
std::vector<uint32_t> badges(NUM_BADGE_LEVELS, 0);
|
||||
for (const auto &e: data.badges)
|
||||
if (e.second > 0 && e.second <= NUM_BADGE_LEVELS)
|
||||
badges[e.second-1] += 1;
|
||||
res.snapshot.player_data.push_back({account_id, std::move(data.name), data.ignore, std::move(badges)});
|
||||
--n_accounts;
|
||||
}
|
||||
++account_id;
|
||||
@ -4257,6 +4264,65 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_cc_get_badge(const COMMAND_RPC_CC_GET_BADGE::request& req, COMMAND_RPC_CC_GET_BADGE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
|
||||
{
|
||||
PERF_TIMER(on_cc_get_badge);
|
||||
|
||||
try
|
||||
{
|
||||
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
|
||||
cc::cc_badge_data_t data;
|
||||
if (!cc::get_badge_data(db, (cc::cc_badge_t)req.id, data))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error retrieving badge data";
|
||||
return false;
|
||||
}
|
||||
res.name = data.name;
|
||||
res.desc = data.desc;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error retrieving badge data";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_cc_get_badge_totals(const COMMAND_RPC_CC_GET_BADGE_TOTALS::request& req, COMMAND_RPC_CC_GET_BADGE_TOTALS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
|
||||
{
|
||||
PERF_TIMER(on_cc_get_badge_totals);
|
||||
|
||||
try
|
||||
{
|
||||
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
|
||||
if (!db.for_all_cc_accounts([&res](const cryptonote::cc_account_data_t &ad){
|
||||
std::vector<uint32_t> counts(NUM_BADGE_LEVELS, 0);
|
||||
for (const auto &e: ad.badges)
|
||||
counts[e.second-1] += 1;
|
||||
res.entries.push_back({ad.id, std::move(counts)});
|
||||
return true;
|
||||
}))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error retrieving badge data";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error retrieving badge data";
|
||||
return false;
|
||||
}
|
||||
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
const command_line::arg_descriptor<std::string, false, true, 2> core_rpc_server::arg_rpc_bind_port = {
|
||||
"rpc-bind-port"
|
||||
, "Port for RPC server"
|
||||
|
@ -207,6 +207,8 @@ namespace cryptonote
|
||||
MAP_JON_RPC_WE("cc_get_custom_items", on_cc_get_custom_items, COMMAND_RPC_CC_GET_CUSTOM_ITEMS)
|
||||
MAP_JON_RPC_WE("cc_get_accounts", on_cc_get_accounts, COMMAND_RPC_CC_GET_ACCOUNTS)
|
||||
MAP_JON_RPC_WE("cc_get_flags", on_cc_get_flags, COMMAND_RPC_CC_GET_FLAGS)
|
||||
MAP_JON_RPC_WE("cc_get_badge", on_cc_get_badge, COMMAND_RPC_CC_GET_BADGE)
|
||||
MAP_JON_RPC_WE("cc_get_badge_totals", on_cc_get_badge_totals, COMMAND_RPC_CC_GET_BADGE_TOTALS)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
@ -307,6 +309,8 @@ namespace cryptonote
|
||||
bool on_cc_get_custom_items(const COMMAND_RPC_CC_GET_CUSTOM_ITEMS::request& req, COMMAND_RPC_CC_GET_CUSTOM_ITEMS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_accounts(const COMMAND_RPC_CC_GET_ACCOUNTS::request& req, COMMAND_RPC_CC_GET_ACCOUNTS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_flags(const COMMAND_RPC_CC_GET_FLAGS::request& req, COMMAND_RPC_CC_GET_FLAGS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_badge(const COMMAND_RPC_CC_GET_BADGE::request& req, COMMAND_RPC_CC_GET_BADGE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
bool on_cc_get_badge_totals(const COMMAND_RPC_CC_GET_BADGE_TOTALS::request& req, COMMAND_RPC_CC_GET_BADGE_TOTALS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
|
||||
//-----------------------
|
||||
|
||||
private:
|
||||
|
@ -2741,12 +2741,24 @@ namespace cryptonote
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct badge_t
|
||||
{
|
||||
uint32_t type;
|
||||
uint8_t level;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(type)
|
||||
KV_SERIALIZE(level)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response_t
|
||||
{
|
||||
std::string public_key;
|
||||
uint64_t balance;
|
||||
std::vector<item_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::vector<badge_t> badges;
|
||||
std::string name;
|
||||
bool ignore;
|
||||
std::string status;
|
||||
@ -2756,6 +2768,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(balance)
|
||||
KV_SERIALIZE(item_balances)
|
||||
KV_SERIALIZE(flags)
|
||||
KV_SERIALIZE(badges)
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(ignore)
|
||||
KV_SERIALIZE(status)
|
||||
@ -3669,4 +3682,68 @@ namespace cryptonote
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CC_GET_BADGE
|
||||
{
|
||||
struct request_t
|
||||
{
|
||||
uint32_t id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
std::string name;
|
||||
std::string desc;
|
||||
std::string status;
|
||||
bool untrusted;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(desc)
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(untrusted)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CC_GET_BADGE_TOTALS
|
||||
{
|
||||
struct request_t
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct entry_t
|
||||
{
|
||||
uint32_t account_id;
|
||||
std::vector<uint32_t> badges;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(account_id)
|
||||
KV_SERIALIZE(badges)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response_t
|
||||
{
|
||||
std::vector<entry_t> entries;
|
||||
std::string status;
|
||||
bool untrusted;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(entries)
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(untrusted)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2943,10 +2943,11 @@ bool simple_wallet::cc_status(const std::vector<std::string> &args_)
|
||||
uint64_t balance;
|
||||
std::map<uint32_t, uint32_t> item_balances;
|
||||
std::vector<uint32_t> flags;
|
||||
std::map<uint32_t, uint8_t> badges;
|
||||
std::string name;
|
||||
std::string public_key;
|
||||
bool ignore;
|
||||
m_wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, name, ignore);
|
||||
m_wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, name, ignore);
|
||||
|
||||
message_writer() << tr("Account number: ") << id << " (" << tr("address: ") << m_wallet->get_cc_pkey() << ")";
|
||||
message_writer() << tr("Name: ") << name;
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "cc/cc_game_update.h"
|
||||
#include "cc/cc_special_events.h"
|
||||
#include "cc/cc_custom_item.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "wallet_light_rpc.h"
|
||||
#include "wallet_rpc_helpers.h"
|
||||
|
||||
@ -916,7 +917,7 @@ private:
|
||||
// CC
|
||||
bool get_new_cc_flag_cost(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint64_t &cost);
|
||||
bool get_cc_build_budget(uint32_t flag, uint32_t dx, uint32_t dy, uint32_t width, uint32_t height, uint16_t min_height, const std::vector<uint8_t> &tiles, bool encoded, std::map<uint32_t, uint32_t> &budget);
|
||||
bool get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::string &name, bool &ignore);
|
||||
bool get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges, std::string &name, bool &ignore);
|
||||
bool get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t &treasury, uint32_t &mayor, std::string &name, uint64_t &treasury_balance, uint32_t &max_level);
|
||||
bool get_cc_special_events(uint32_t city, bool all, std::vector<cc::special_event_data_t> &special_events);
|
||||
bool get_cc_snapshot(cryptonote::cc_snapshot &snapshot, uint32_t city_id, uint64_t &height, crypto::hash &top_hash, std::vector<cryptonote::cc_command_t> &top_commands);
|
||||
@ -928,6 +929,8 @@ private:
|
||||
bool get_cc_custom_items(const std::vector<uint32_t> &ids, std::vector<cc::cc_custom_item_t> &items);
|
||||
bool get_cc_accounts(std::vector<std::tuple<uint32_t, std::string, bool>> &accounts);
|
||||
bool get_cc_flags(std::vector<std::tuple<uint32_t, std::string, bool>> &flags);
|
||||
bool get_cc_badge_data(uint32_t id, cc::cc_badge_data_t &data);
|
||||
bool get_cc_badge_totals(std::vector<std::pair<uint32_t, std::vector<uint32_t>>> &badges);
|
||||
bool set_ignore_settings(const cc_ignore_t &ignore);
|
||||
bool get_ignore_settings(cc_ignore_t &ignore);
|
||||
void get_new_txpool_cc_commands(const std::unordered_set<crypto::hash> &ignore, std::unordered_map<crypto::hash, std::pair<cryptonote::cc_command_t, uint64_t>> &txs);
|
||||
|
@ -105,7 +105,7 @@ bool wallet2::get_cc_build_budget(uint32_t flag, uint32_t dx, uint32_t dy, uint3
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet2::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::string &name, bool &ignore)
|
||||
bool wallet2::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t &balance, std::map<uint32_t, uint32_t> &item_balances, std::vector<uint32_t> &flags, std::map<uint32_t, uint8_t> &badges, std::string &name, bool &ignore)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_CC_GET_ACCOUNT::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_CC_GET_ACCOUNT::response res;
|
||||
@ -124,6 +124,9 @@ bool wallet2::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t
|
||||
if (e.amount > 0)
|
||||
item_balances[e.type] += e.amount;
|
||||
flags = res.flags;
|
||||
badges.clear();
|
||||
for (const auto &e: res.badges)
|
||||
badges[e.type] = e.level;
|
||||
name = res.name;
|
||||
ignore = res.ignore;
|
||||
return true;
|
||||
@ -440,6 +443,44 @@ bool wallet2::get_cc_flags(std::vector<std::tuple<uint32_t, std::string, bool>>
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet2::get_cc_badge_data(uint32_t id, cc::cc_badge_data_t &data)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_CC_GET_BADGE::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_CC_GET_BADGE::response res;
|
||||
|
||||
req.id = id;
|
||||
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_badge", req, res);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
if (!r || res.status != CORE_RPC_STATUS_OK)
|
||||
return false;
|
||||
data.id = id;
|
||||
data.name = res.name;
|
||||
data.desc = res.desc;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet2::get_cc_badge_totals(std::vector<std::pair<uint32_t, std::vector<uint32_t>>> &badges)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_CC_GET_BADGE_TOTALS::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_CC_GET_BADGE_TOTALS::response res;
|
||||
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_badge_totals", req, res);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
if (!r || res.status != CORE_RPC_STATUS_OK)
|
||||
return false;
|
||||
|
||||
badges.clear();
|
||||
badges.reserve(res.entries.size());
|
||||
for (auto &e: res.entries)
|
||||
{
|
||||
badges.push_back(std::make_pair(e.account_id, std::move(e.badges)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet2::set_ignore_settings(const tools::cc_ignore_t &ignore)
|
||||
{
|
||||
m_cc_ignore = ignore;
|
||||
|
@ -5170,6 +5170,47 @@ namespace tools
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_cc_new_event_badge(const wallet_rpc::COMMAND_RPC_CC_NEW_EVENT_BADGE::request& req, wallet_rpc::COMMAND_RPC_CC_NEW_EVENT_BADGE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
|
||||
{
|
||||
LOG_PRINT_L3("on_cc_new_event_badge starts");
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_restricted)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
cryptonote::cc_command_new_event_badge_t cmd;
|
||||
cmd.cc_account = m_wallet->get_cc_account();
|
||||
cmd.name = req.name;
|
||||
cmd.description = req.description;
|
||||
for (const auto &e: req.instances)
|
||||
cmd.instances.push_back({e.account_id, e.level});
|
||||
uint32_t priority = m_wallet->adjust_priority(req.priority);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_cc_transactions(cmd, priority);
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
|
||||
er.message = "No transaction created";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string dummy_tx_key;
|
||||
uint64_t dummy_amount;
|
||||
return fill_response(ptx_vector, false, dummy_tx_key, dummy_amount, res.fee, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
class t_daemon
|
||||
|
@ -176,6 +176,7 @@ namespace tools
|
||||
MAP_JON_RPC_WE("cc_new_item", on_cc_new_item, wallet_rpc::COMMAND_RPC_CC_NEW_ITEM)
|
||||
MAP_JON_RPC_WE("cc_dividend", on_cc_dividend, wallet_rpc::COMMAND_RPC_CC_DIVIDEND)
|
||||
MAP_JON_RPC_WE("cc_ignore", on_cc_ignore, wallet_rpc::COMMAND_RPC_CC_IGNORE)
|
||||
MAP_JON_RPC_WE("cc_new_event_badge", on_cc_new_event_badge, wallet_rpc::COMMAND_RPC_CC_NEW_EVENT_BADGE)
|
||||
END_JSON_RPC_MAP()
|
||||
END_URI_MAP2()
|
||||
|
||||
@ -282,6 +283,7 @@ namespace tools
|
||||
bool on_cc_new_item(const wallet_rpc::COMMAND_RPC_CC_NEW_ITEM::request& req, wallet_rpc::COMMAND_RPC_CC_NEW_ITEM::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
bool on_cc_dividend(const wallet_rpc::COMMAND_RPC_CC_DIVIDEND::request& req, wallet_rpc::COMMAND_RPC_CC_DIVIDEND::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
bool on_cc_ignore(const wallet_rpc::COMMAND_RPC_CC_IGNORE::request& req, wallet_rpc::COMMAND_RPC_CC_IGNORE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
bool on_cc_new_event_badge(const wallet_rpc::COMMAND_RPC_CC_NEW_EVENT_BADGE::request& req, wallet_rpc::COMMAND_RPC_CC_NEW_EVENT_BADGE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
|
||||
//json rpc v2
|
||||
bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
|
||||
|
@ -3685,5 +3685,63 @@ namespace wallet_rpc
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CC_NEW_EVENT_BADGE
|
||||
{
|
||||
struct instance_t
|
||||
{
|
||||
uint32_t account_id;
|
||||
uint8_t level;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(account_id)
|
||||
KV_SERIALIZE(level)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct request_t
|
||||
{
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::vector<instance_t> instances;
|
||||
|
||||
uint32_t priority;
|
||||
bool do_not_relay;
|
||||
bool get_tx_hex;
|
||||
bool get_tx_metadata;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(description)
|
||||
KV_SERIALIZE(instances)
|
||||
|
||||
KV_SERIALIZE_OPT(priority, (uint32_t)0)
|
||||
KV_SERIALIZE_OPT(do_not_relay, false)
|
||||
KV_SERIALIZE_OPT(get_tx_hex, false)
|
||||
KV_SERIALIZE_OPT(get_tx_metadata, false)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
||||
struct response_t
|
||||
{
|
||||
std::string tx_hash;
|
||||
uint64_t fee;
|
||||
std::string tx_blob;
|
||||
std::string tx_metadata;
|
||||
std::string multisig_txset;
|
||||
std::string unsigned_txset;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tx_hash)
|
||||
KV_SERIALIZE(fee)
|
||||
KV_SERIALIZE(tx_blob)
|
||||
KV_SERIALIZE(tx_metadata)
|
||||
KV_SERIALIZE(multisig_txset)
|
||||
KV_SERIALIZE(unsigned_txset)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3319,3 +3319,20 @@ bool gen_cc_tx_invalid_cc_bare_ignore_wrong_account::generate(std::vector<test_e
|
||||
|
||||
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
|
||||
}
|
||||
|
||||
bool gen_cc_tx_invalid_cc_bare_new_event_badge_wrong_account::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
init_cc_test_accounts();
|
||||
const unsigned int mixin = 10;
|
||||
const uint64_t amount_paid = 0;
|
||||
std::vector<std::tuple<std::string, cryptonote::cc_command_t, uint64_t>> cmds;
|
||||
|
||||
cryptonote::cc_command_new_event_badge_t new_event_badge;
|
||||
new_event_badge.cc_account = 4;
|
||||
new_event_badge.name = "test badge";
|
||||
new_event_badge.description = "test badge desc";
|
||||
new_event_badge.instances.push_back({4, 1});
|
||||
cmds.push_back(std::make_tuple("", new_event_badge, BARE_TX_FEE));
|
||||
|
||||
return generate_with(events, boost::none, boost::none, prep_none, cmds.size(), mixin, amount_paid, true, cmds, false, invalid, NULL, NULL);
|
||||
}
|
||||
|
@ -607,3 +607,9 @@ struct gen_cc_tx_invalid_cc_bare_ignore_wrong_account: public gen_cc_tx_validati
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
template<> struct get_test_options<gen_cc_tx_invalid_cc_bare_ignore_wrong_account>: public get_test_options<gen_cc_tx_validation_base> {};
|
||||
|
||||
struct gen_cc_tx_invalid_cc_bare_new_event_badge_wrong_account: public gen_cc_tx_validation_base
|
||||
{
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
template<> struct get_test_options<gen_cc_tx_invalid_cc_bare_new_event_badge_wrong_account>: public get_test_options<gen_cc_tx_validation_base> {};
|
||||
|
@ -342,6 +342,7 @@ int main(int argc, char* argv[])
|
||||
GENERATE_AND_PLAY(gen_cc_tx_invalid_cc_bare_new_item_invalid_name);
|
||||
GENERATE_AND_PLAY(gen_cc_tx_invalid_cc_bare_new_item_duplicate_name);
|
||||
GENERATE_AND_PLAY(gen_cc_tx_invalid_cc_bare_ignore_wrong_account);
|
||||
GENERATE_AND_PLAY(gen_cc_tx_invalid_cc_bare_new_event_badge_wrong_account);
|
||||
|
||||
el::Level level = (failed_tests.empty() ? el::Level::Info : el::Level::Error);
|
||||
if (!list_tests)
|
||||
|
@ -1614,6 +1614,12 @@ class CCTest():
|
||||
state['discoveries'] = res
|
||||
res = daemon.cc_get_custom_items()
|
||||
state['custom_items'] = res
|
||||
for i in range(16):
|
||||
try:
|
||||
res = daemon.cc_get_badge(i)
|
||||
state['badge_' + str(i)] = res
|
||||
except:
|
||||
pass
|
||||
return state
|
||||
|
||||
def get_diff(self, state0, state1):
|
||||
@ -1743,6 +1749,9 @@ class CCTest():
|
||||
self.test_revert_cmd(daemon, lambda self: self.wallet[3].cc_dividend(custom_item_id, 0, 100))
|
||||
self.test_revert_cmd(daemon, lambda self: self.wallet[3].cc_dividend(custom_item_id, ITEM_STONE, 16))
|
||||
|
||||
# new event badge
|
||||
self.test_revert_cmd(daemon, lambda self: self.wallet[3].cc_new_event_badge("Test badge for testing revert", "Event badge desc", [{"account_id": 4, "level": 2}]))
|
||||
|
||||
def test_distance_from_generator(self):
|
||||
daemon = Daemon()
|
||||
|
||||
|
@ -39,7 +39,7 @@ N_WALLETS = 4
|
||||
WALLET_DIRECTORY = builddir + "/functional-tests-directory"
|
||||
DIFFICULTY = 10
|
||||
|
||||
monerod_base = [builddir + "/bin/townforged", "--regtest", "--fixed-difficulty", str(DIFFICULTY), "--offline", "--no-igd", "--p2p-bind-port", "monerod_p2p_port", "--rpc-bind-port", "monerod_rpc_port", "--zmq-rpc-bind-port", "monerod_zmq_port", "--non-interactive", "--disable-dns-checkpoints", "--check-updates", "disabled", "--rpc-ssl", "disabled", "--log-level", "1"]
|
||||
monerod_base = [builddir + "/bin/townforged", "--regtest", "--fixed-difficulty", str(DIFFICULTY), "--offline", "--no-igd", "--p2p-bind-port", "monerod_p2p_port", "--rpc-bind-port", "monerod_rpc_port", "--zmq-rpc-bind-port", "monerod_zmq_port", "--non-interactive", "--disable-dns-checkpoints", "--check-updates", "disabled", "--rpc-ssl", "disabled", "--log-level", "1", "--debug-allow-gm-commands-from-account", "7"]
|
||||
monerod_extra = [
|
||||
[],
|
||||
["--rpc-payment-address", "CC1MM9BNc8w9fXr3hMfuj4zAcW2uwkRXmL8JmC8kusgfaxoKAzc3dWJvP3wV6q8sCR6PDUTu2u2c3vK4Pekw1A2urHw4KFzeZ2n", "--rpc-payment-difficulty", str(DIFFICULTY), "--rpc-payment-credits", "5000", "--data-dir", builddir + "/functional-tests-directory/townforged1"],
|
||||
|
@ -2475,6 +2475,10 @@ TEST(cc, type_tags)
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x12);
|
||||
cmd = cryptonote::cc_command_dividend_t();
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x13);
|
||||
cmd = cryptonote::cc_command_ignore_t();
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x14);
|
||||
cmd = cryptonote::cc_command_new_event_badge_t();
|
||||
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x15);
|
||||
}
|
||||
|
||||
TEST(cc, staff)
|
||||
|
@ -880,3 +880,25 @@ class Daemon(object):
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_custom_items)
|
||||
|
||||
def cc_get_badge(self, id):
|
||||
cc_get_badge = {
|
||||
'method': 'cc_get_badge',
|
||||
'params': {
|
||||
'id': id,
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_badge)
|
||||
|
||||
def cc_get_badge_totals(self, id):
|
||||
cc_get_badge_totals = {
|
||||
'method': 'cc_get_badge_totals',
|
||||
'params': {
|
||||
'id': id,
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_badge_totals)
|
||||
|
@ -1451,3 +1451,20 @@ class Wallet(object):
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_ignore)
|
||||
|
||||
def cc_new_event_badge(self, name, description, instances, priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
|
||||
cc_new_event_badge = {
|
||||
'method': 'cc_new_event_badge',
|
||||
'params': {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'instances': instances,
|
||||
'priority': priority,
|
||||
'do_not_relay': do_not_relay,
|
||||
'get_tx_hex': get_tx_hex,
|
||||
'get_tx_metadata': get_tx_metadata,
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_new_event_badge)
|
||||
|
Loading…
Reference in New Issue
Block a user