players can now have a title

chosen among a set of predefined components
This commit is contained in:
Crypto City 2023-03-29 10:34:08 +00:00
parent ffe4b0df3b
commit 2c378941dd
66 changed files with 1710 additions and 111 deletions

View File

@ -0,0 +1,41 @@
WindowInfo
title Change title
centered-relative-size: 0.6 0.4
modal: 1
TBLayout: axis: y, distribution-position: "left top", distribution: "gravity"
TBLayout: axis: x
TBTextField: text: "You title currently is:"
TBTextField: id: "current-title"
TBSeparator
TBLayout: axis: x
TBClickLabel: text: "Compound:"
TBRadioButton: id: "style-compound", group-id: "style", data: 0, value: 1
TBClickLabel: text: "Unique:"
TBRadioButton: id: "style-unique", group-id: "style", data: 1, value: 0
TBToggleContainer: id: "toggle-style-compound", toggle: "expanded", value: 1
TBLayout: axis: y
TBTextField: text: "You can build your title from available components"
TBTextField: text: "All components are optional"
TBLayout: axis: x
TBSelectDropdown: id: "adjectives"
TBSelectDropdown: id: "nouns"
TBSelectDropdown: id: "origins"
TBToggleContainer: id: "toggle-style-unique", toggle: "expanded", value: 0
TBLayout: axis: x
TBSelectDropdown: id: "uniques"
TBSeparator
TBLayout: axis: x
TBTextField: text: "New title:"
TBTextField: id: "new-title"
TBLayout: axis: x
TBButton: text: "OK", id: "ok"
TBButton: text: "Cancel", id: "cancel"

View File

@ -16,49 +16,53 @@ TBTabContainer
TBButton: text: "History"
TBButton: text: "Invitations"
TBLayout: axis: x, distribution: "gravity"
TBLayout: axis: y, distribution: "gravity", gravity: "top bottom", distribution-position: "left", size: "available"
TBLayout: axis: x, distribution-position: "top", gravity: "top"
TBLayout: axis: y, distribution-position: "top left"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Name:"
TBTextField: id: "name"
TBButton: id: "select-account", text: "Select other"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Level:"
TBTextField: id: "level"
TBButton: id: "level-up", text: "Level up"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Prestige:"
TBTextField: id: "prestige-main"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Player ID:"
TBTextField: id: "id"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Public key:"
TBEditField: id: "public_key", readonly: 1, multiline: 0, adapt-to-content: 1, skin: "TBEditField.public-key"
font: size: 12px
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Balance:"
TBTextField: id: "balance"
TBLayout: axis: y, distribution-position: "top right"
TBButton: id: "give-money", text: "Give gold"
TBButton: id: "give-items", text: "Give items"
TBButton: id: "give-land", text: "Give land"
TBButton: id: "send-message", text: "Send message"
TBSelectList: id: "attributes"
TBClickLabel: text: "Ignore", gravity: "bottom"
TBCheckBox: id: "ignore"
TBLayout: axis: y, distribution: "gravity"
TBEditField: id: "player-profile", text: "", multiline: 1, gravity: "all", placeholder: "Player profile"
TBToggleContainer: id: "profile-error-container", toggle: "expanded", gravity: "left right"
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
TBImageWidget: filename: "images/warning.png"
lp:
width: 24
height: 24
TBTextField: id: "profile-error", gravity: "left right", text-align: "left", skin: "text-error"
TBButton: id: "save-player-profile", text: "Save"
TBLayout: axis: y, distribution: "gravity"
TBTextField
TBTextField: id: "title", gravity: "left right", text-align: "center", underline: 1, skin: "title-link"
TBTextField
TBLayout: axis: x, distribution: "gravity"
TBLayout: axis: y, distribution: "gravity", gravity: "top bottom", distribution-position: "left", size: "available"
TBLayout: axis: x, distribution-position: "top", gravity: "top"
TBLayout: axis: y, distribution-position: "top left"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Name:"
TBTextField: id: "name"
TBButton: id: "select-account", text: "Select other"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Level:"
TBTextField: id: "level"
TBButton: id: "level-up", text: "Level up"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Prestige:"
TBTextField: id: "prestige-main"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Player ID:"
TBTextField: id: "id"
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Public key:"
TBEditField: id: "public_key", readonly: 1, multiline: 0, adapt-to-content: 1, skin: "TBEditField.public-key"
font: size: 12px
TBLayout: axis: x, distribution-position: "left top"
TBTextField: text: "Balance:"
TBTextField: id: "balance"
TBLayout: axis: y, distribution-position: "top right"
TBButton: id: "give-money", text: "Give gold"
TBButton: id: "give-items", text: "Give items"
TBButton: id: "give-land", text: "Give land"
TBButton: id: "send-message", text: "Send message"
TBSelectList: id: "attributes"
TBClickLabel: text: "Ignore", gravity: "bottom"
TBCheckBox: id: "ignore"
TBLayout: axis: y, distribution: "gravity"
TBEditField: id: "player-profile", text: "", multiline: 1, gravity: "all", placeholder: "Player profile"
TBToggleContainer: id: "profile-error-container", toggle: "expanded", gravity: "left right"
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
TBImageWidget: filename: "images/warning.png"
lp:
width: 24
height: 24
TBTextField: id: "profile-error", gravity: "left right", text-align: "left", skin: "text-error"
TBButton: id: "save-player-profile", text: "Save"
TBLayout: axis: y, distribution-position: "left top", distribution: "gravity"
TBLayout: axis: x, distribution: "gravity"

View File

@ -328,6 +328,9 @@ elements
history-new-tag:
text-color #cf3f3f
title-link:
text-color: #71ebc4
# litehtml
litehtml.list-marker.circle: type: Image, bitmap: litehtml/list-marker.circle.png, min-width: 3, min-height: 3
litehtml.list-marker.disc: type: Image, bitmap: litehtml/list-marker.disc.png, min-width: 3, min-height: 3

View File

@ -799,6 +799,20 @@ bool BlockchainDB::change_cc_account_num_pearls_found(uint32_t id, int32_t delta
return true;
}
bool BlockchainDB::set_cc_account_title(uint32_t id, int32_t adjective, int32_t noun, int32_t origin, int32_t unique, const std::string &title)
{
cryptonote::cc_account_data_t ad;
if (!get_cc_account_data(id, ad))
return false;
ad.title_adjective = adjective;
ad.title_noun = noun;
ad.title_origin = origin;
ad.title_unique = unique;
ad.title = title;
set_cc_account_data(id, ad);
return true;
}
void BlockchainDB::reset_stats()
{
num_calls = 0;

View File

@ -212,6 +212,13 @@ struct cc_account_data_t
std::vector<uint32_t> textures_created;
std::vector<uint32_t> textures_licenced;
std::vector<std::string> unique_titles;
int32_t title_adjective;
int32_t title_noun;
int32_t title_origin;
int32_t title_unique;
std::string title;
};
struct cc_flag_data_t
@ -2052,6 +2059,8 @@ public:
virtual void unreserve_cc_account(uint32_t id, uint32_t account, uint64_t balance, const std::map<uint32_t, uint32_t> &items) = 0;
virtual void set_cc_account_script_variable(uint32_t id, const std::string &name, uint64_t value, bool local) = 0;
virtual void set_cc_account_prestige(uint32_t id, uint64_t prestige) = 0;
virtual void grant_cc_account_unique_title(uint32_t id, const std::string &unique_title) = 0;
virtual void rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title) = 0;
virtual bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const = 0;
virtual uint32_t allocate_new_cc_city(uint32_t seed, uint32_t mayor, const std::string &name, const std::string &tagline) = 0;
@ -2287,6 +2296,7 @@ public:
bool change_cc_account_gold_smelted(uint32_t id, int64_t delta);
bool change_cc_account_num_auctions_created(uint32_t id, int32_t delta);
bool change_cc_account_num_pearls_found(uint32_t id, int32_t delta);
bool set_cc_account_title(uint32_t id, int32_t adjective, int32_t noun, int32_t origin, int32_t unique, const std::string &title);
virtual void remove_block() = 0;

View File

@ -661,6 +661,12 @@ typedef struct mdb_cc_account_data
serializable_map<uint32_t, std::tuple<uint32_t, uint32_t, uint32_t, background_script_state_locals_t>> background_script_states;
std::vector<uint32_t> textures_created;
std::vector<uint32_t> textures_licenced;
std::vector<std::string> unique_titles;
int32_t title_adjective;
int32_t title_noun;
int32_t title_origin;
int32_t title_unique;
std::string title;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0) // do not allow going over 1 byte without changing fast balance get/set/change
@ -702,6 +708,12 @@ typedef struct mdb_cc_account_data
FIELD(background_script_states)
FIELD(textures_created)
FIELD(textures_licenced)
FIELD(unique_titles)
VARINT_FIELD_SIGNED(title_adjective)
VARINT_FIELD_SIGNED(title_noun)
VARINT_FIELD_SIGNED(title_origin)
VARINT_FIELD_SIGNED(title_unique)
FIELD(title)
END_SERIALIZE()
} mdb_cc_account_data;
@ -5796,6 +5808,10 @@ uint32_t BlockchainLMDB::allocate_new_cc_account(const crypto::public_key &publi
ad.demonetized = 0;
ad.num_auctions_created = 0;
ad.num_pearls_found = 0;
ad.title_adjective = -1;
ad.title_noun = -1;
ad.title_origin = -1;
ad.title_unique = -1;
k.mv_data = (void*)&account_id;
k.mv_size = sizeof(account_id);
@ -5971,6 +5987,12 @@ bool BlockchainLMDB::get_cc_account_data(uint32_t id, cc_account_data_t &data) c
}
data.textures_created = std::move(ad.textures_created);
data.textures_licenced = std::move(ad.textures_licenced);
data.unique_titles = std::move(ad.unique_titles);
data.title_adjective = ad.title_adjective;
data.title_noun = ad.title_noun;
data.title_origin = ad.title_origin;
data.title_unique = ad.title_unique;
data.title = std::move(ad.title);
TXN_POSTFIX_RDONLY();
return true;
@ -6051,6 +6073,12 @@ void BlockchainLMDB::set_cc_account_data(uint32_t id, const cc_account_data_t &a
cad.textures_created = ad.textures_created;
cad.textures_licenced = ad.textures_licenced;
cad.unique_titles = ad.unique_titles;
cad.title_adjective = ad.title_adjective;
cad.title_noun = ad.title_noun;
cad.title_origin = ad.title_origin;
cad.title_unique = ad.title_unique;
cad.title = ad.title;
if (!write_account_data(v, cad))
throw0(DB_ERROR("Failed to serialize account data"));
@ -6837,6 +6865,69 @@ void BlockchainLMDB::set_cc_account_prestige(uint32_t id, uint64_t prestige)
throw0(DB_ERROR(lmdb_error("Failed to add account data to db transaction: ", result).c_str()));
}
void BlockchainLMDB::grant_cc_account_unique_title(uint32_t id, const std::string &unique_title)
{
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()));
mdb_cc_account_data ad;
if (!read_account_data(v, ad))
throw0(DB_ERROR("Failed to deserialize account data"));
ad.unique_titles.push_back(unique_title);
if (!write_account_data(v, ad))
throw0(DB_ERROR("Failed to serialize account data"));
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
if (v.mv_data) free(v.mv_data);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to add account data to db transaction: ", result).c_str()));
}
void BlockchainLMDB::rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title)
{
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()));
mdb_cc_account_data ad;
if (!read_account_data(v, ad))
throw0(DB_ERROR("Failed to deserialize account data"));
if (ad.unique_titles.empty() || ad.unique_titles.back() != unique_title)
throw0(DB_ERROR("Unexpected last unique title in account data"));
ad.unique_titles.pop_back();
if (!write_account_data(v, ad))
throw0(DB_ERROR("Failed to serialize account data"));
result = mdb_cursor_put(m_cur_cc_accounts, &k, &v, 0);
if (v.mv_data) free(v.mv_data);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to add account data to db transaction: ", result).c_str()));
}
bool BlockchainLMDB::for_all_cc_accounts(std::function<bool(const cc_account_data_t &data)> f) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@ -6917,6 +7008,12 @@ bool BlockchainLMDB::for_all_cc_accounts(std::function<bool(const cc_account_dat
data.textures_created = std::move(ad.textures_created);
data.textures_licenced = std::move(ad.textures_licenced);
data.unique_titles = std::move(ad.unique_titles);
data.title_adjective = ad.title_adjective;
data.title_noun = ad.title_noun;
data.title_origin = ad.title_origin;
data.title_unique = ad.title_unique;
data.title = std::move(ad.title);
if (!f(data))
{
@ -10739,6 +10836,12 @@ bool BlockchainLMDB::get_as_cc_account(const cryptonote::blobdata &bd, cc_accoun
}
data.textures_created = std::move(ad.textures_created);
data.textures_licenced = std::move(ad.textures_licenced);
data.unique_titles = std::move(ad.unique_titles);
data.title_adjective = ad.title_adjective;
data.title_noun = ad.title_noun;
data.title_origin = ad.title_origin;
data.title_unique = ad.title_unique;
data.title = std::move(ad.title);
return true;
}

View File

@ -574,6 +574,8 @@ private:
void unreserve_cc_account(uint32_t id, uint32_t account, uint64_t balance, const std::map<uint32_t, uint32_t> &items);
void set_cc_account_script_variable(uint32_t id, const std::string &name, uint64_t value, bool local);
void set_cc_account_prestige(uint32_t id, uint64_t prestige);
void grant_cc_account_unique_title(uint32_t id, const std::string &unique_title);
void rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title);
bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const;
uint32_t allocate_new_cc_city(uint32_t seed, uint32_t mayor, const std::string &name, const std::string &tagline);

View File

@ -202,6 +202,8 @@ public:
virtual void unreserve_cc_account(uint32_t id, uint32_t account, uint64_t balance, const std::map<uint32_t, uint32_t> &items) {}
virtual void set_cc_account_script_variable(uint32_t id, const std::string &name, uint64_t value, bool local) {}
virtual void set_cc_account_prestige(uint32_t id, uint64_t prestige) {}
virtual void grant_cc_account_unique_title(uint32_t id, const std::string &unique_title) {}
virtual void rescind_cc_account_unique_title(uint32_t id, const std::string &unique_title) {}
virtual bool for_all_cc_accounts(std::function<bool(const cc_account_data_t&)>) const { return true; }
virtual uint32_t allocate_new_cc_city(uint32_t seed, uint32_t mayor, const std::string &name, const std::string &tagline) { return 0; }

View File

@ -87,6 +87,7 @@ set(cc_sources
cc_command_handler_salt_food.cpp
cc_command_handler_script_choice.cpp
cc_command_handler_service.cpp
cc_command_handler_set_title.cpp
cc_command_handler_add_tax_break_zone.cpp
cc_command_handler_set_merchant_ship_items.cpp
cc_command_handler_set_script_variables.cpp
@ -126,6 +127,7 @@ set(cc_sources
cc_temperature.cpp
cc_terrain.cc
cc_terrain_features.cc
cc_title.cc
cc_whisper.cc
cc.cpp
dds.c
@ -192,6 +194,7 @@ set(cc_headers
cc_command_handler_salt_food.h
cc_command_handler_script_choice.h
cc_command_handler_service.h
cc_command_handler_set_title.h
cc_command_handler_add_tax_break_zone.h
cc_command_handler_set_merchant_ship_items.h
cc_command_handler_set_script_variables.h
@ -232,6 +235,7 @@ set(cc_headers
cc_temperature.h
cc_terrain.h
cc_terrain_features.h
cc_title.h
cc.h)
set(cc_private_headers

View File

@ -99,6 +99,7 @@
#include "cc_command_handler_service.h"
#include "cc_command_handler_set_merchant_ship_items.h"
#include "cc_command_handler_set_script_variables.h"
#include "cc_command_handler_set_title.h"
#include "cc_command_handler_add_tax_break_zone.h"
#include "cc_command_handler_smelt.h"
#include "cc_command_handler_sow.h"
@ -4245,6 +4246,7 @@ static cc_command_handler &get_cc_command_handler(const cryptonote::cc_command_t
cc_command_handler &operator()(const cryptonote::cc_command_service_t &cmd) const { return cc_command_handler_service::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return cc_command_handler_set_merchant_ship_items::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return cc_command_handler_set_script_variables::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_set_title_t &cmd) const { return cc_command_handler_set_title::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return cc_command_handler_add_tax_break_zone::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_smelt_t &cmd) const { return cc_command_handler_smelt::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_sow_t &cmd) const { return cc_command_handler_sow::instance; }

View File

@ -17,6 +17,8 @@ static const struct
const char *desc;
const char *icon;
bool manual;
const char *title_adjective;
const char *title_noun;
uint64_t thresholds[NUM_BADGE_LEVELS];
const char *threshold_text[NUM_BADGE_LEVELS];
std::string (*convert_score)(uint64_t score);
@ -27,6 +29,7 @@ static const struct
"Awarded to people who helped prior to launch",
"atlas",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -36,6 +39,7 @@ static const struct
"Awarded for best custom item design",
"jeweled-chalice",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -45,6 +49,7 @@ static const struct
"Awarded for 3D architecture prowess in agricultural buildings",
"barn/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -54,6 +59,7 @@ static const struct
"Awarded for 3D architecture prowess in craft buildings",
"sword-smithing/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -63,6 +69,7 @@ static const struct
"Awarded for 3D architecture prowess in industrial buildings",
"factory/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -72,6 +79,7 @@ static const struct
"Awarded for 3D architecture prowess in commercial buildings",
"hanging-sign/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -81,6 +89,7 @@ static const struct
"Awarded for 3D architecture prowess in basic residential buildings",
"house/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -90,6 +99,7 @@ static const struct
"Awarded for 3D architecture prowess in affluent residential buildings",
"family-house/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -99,6 +109,7 @@ static const struct
"Awarded for 3D architecture prowess in luxury residential buildings",
"spooky-house-custom/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -108,6 +119,7 @@ static const struct
"Awarded for 3D architecture prowess in military buildings",
"barracks/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -117,6 +129,7 @@ static const struct
"Awarded for 3D architecture prowess in cultural buildings",
"egyptian-sphinx/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -126,6 +139,7 @@ static const struct
"Awarded for 3D architecture prowess in stonecutter buildings",
"stone-block/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -135,6 +149,7 @@ static const struct
"Awarded for 3D architecture prowess in sawmill buildings",
"wood-beam/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -144,6 +159,7 @@ static const struct
"Awarded for 3D architecture prowess in kiln buildings",
"brick-pile/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -153,6 +169,7 @@ static const struct
"Awarded for 3D architecture prowess in smelter buildings",
"melting-metal/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -162,6 +179,7 @@ static const struct
"Awarded for 3D architecture prowess in workforce buildings",
"three-friends/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -171,6 +189,7 @@ static const struct
"Awarded for 3D architecture prowess in road buildings",
"tall-bridge/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -180,6 +199,7 @@ static const struct
"Awarded for 3D architecture prowess in research buildings",
"base-dome/ribbon-medal",
true,
NULL, NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -189,6 +209,7 @@ static const struct
"Max number of buildings",
"concrete-bag",
false,
NULL, NULL,
{4, 12, 30, 75, 150},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -198,6 +219,7 @@ static const struct
"Max number of building types",
"modern-city",
false,
NULL, NULL,
{3, 5, 8, 11, 16},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -207,6 +229,7 @@ static const struct
"Number of blocks in inventory",
"wooden-crate",
false,
NULL, NULL,
{100000ull, 250000ull, 750000ull, 5000000ull, 50000000ull},
{"100k", "250k", "750k", "5 million", "50 million"},
NULL
@ -216,6 +239,7 @@ static const struct
"Overall size of military buildings",
"guards",
false,
NULL, "soldier",
{200000ull, 500000ull, 2000000ull, 5000000ull, 15000000ull},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -225,6 +249,7 @@ static const struct
"Overall size of cultural buildings",
"book-cover",
false,
"cultured", NULL,
{200000ull, 500000ull, 2000000ull, 5000000ull, 15000000ull},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -234,6 +259,7 @@ static const struct
"Number of discoveries",
"potion-ball",
false,
NULL, NULL,
{1, 3, 8, 16, 25},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -243,6 +269,7 @@ static const struct
"Monetary balance",
"gold-stack",
false,
NULL, NULL,
{500 * COIN, 1500 * COIN, 5000 * COIN, 20000 * COIN, 100000 * COIN},
{"500", "1500", "5000", "20000", "100000" },
[](uint64_t score) { return cryptonote::print_money(score); }
@ -252,6 +279,7 @@ static const struct
"City level",
"village",
false,
NULL, NULL,
{3, 5, 7, 10, 13},
{cc::get_town_level_name(3), cc::get_town_level_name(5), cc::get_town_level_name(7), cc::get_town_level_name(10), cc::get_town_level_name(13)},
NULL
@ -261,6 +289,7 @@ static const struct
"Amount of food in inventory",
"granary",
false,
NULL, NULL,
{100000, 200000, 500000, 1000000, 2000000},
{"100k", "200k ", "500k", "1 million", "2 million"},
NULL
@ -270,6 +299,7 @@ static const struct
"Stature of one residential home",
"spooky-house-custom",
false,
NULL, NULL,
{1000000ull, 0x1000000000000 | 1500000ll, 0x1000000000000 | 3000000ll, 0x2000000000000 | 5000000ll, 0x2000000000000 | 15000000ull},
{"1 million (any type)", "1.5 million (affluent or luxury", "3 million (affluent or luxury", "5 million (luxury)", "15 million (luxury)"},
NULL
@ -279,6 +309,7 @@ static const struct
"Number of patents",
"files",
false,
NULL, NULL,
{5, 10, 15, 25, 50},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -288,6 +319,7 @@ static const struct
"Number of moose killed",
"deer-track",
false,
NULL, "hunter",
{100, 250, 500, 1000, 2000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -297,6 +329,7 @@ static const struct
"Number of bears killed",
"polar-bear",
false,
NULL, "hunter",
{20, 50, 100, 250, 1000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -306,6 +339,7 @@ static const struct
"Number of other players' buildings linked to one's road network",
"mesh-network",
false,
NULL, NULL,
{15, 40, 85, 150, 300},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -315,6 +349,7 @@ static const struct
"Amount and quality of owned gemstones",
"gems",
false,
NULL, NULL,
{4, 11, 28, 60, 115},
{"4 (amethyst: 1, sapphire: 3, emerald: 10, ruby: 25, diamond: 75)", NULL, NULL, NULL, NULL},
NULL
@ -324,6 +359,7 @@ static const struct
"Distance between a new building and the nearest other",
"horizon-road",
false,
NULL, NULL,
{500, 1250, 3000, 10000, 30000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -333,6 +369,7 @@ static const struct
"Date of construction of oldest building from the start of the game",
"conqueror",
false,
NULL, "forebear",
#define DAYS(x) std::numeric_limits<uint64_t>::max() - ((x) * 86400 / DIFFICULTY_TARGET_V2)
{DAYS(366), DAYS(100), DAYS(30), DAYS(10), DAYS(3)},
#undef DAYS
@ -344,6 +381,7 @@ static const struct
"Number of game ticks in a row a badge is gained",
"upgrade",
false,
"relentless", NULL,
{3, 5, 7, 9, 12},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -353,6 +391,7 @@ static const struct
"Number of others brought to the game",
"backup",
false,
"rallying", NULL,
{2, 8, 30, 100, 250},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -362,6 +401,7 @@ static const struct
"Number of fires put out",
"arson",
false,
NULL, NULL,
{3, 8, 20, 50, 150},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -371,6 +411,7 @@ static const struct
"Number of buildings demolished",
"wrecking-ball",
false,
NULL, NULL,
{3, 10, 25, 50, 100},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -380,6 +421,7 @@ static const struct
"Number of city levels lost from its highest point",
"ancient-ruins",
false,
NULL, NULL,
{1, 2, 3, 4, 5},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -389,6 +431,7 @@ static const struct
"Owns a non-road building above an elevation threshold",
"mountain-road",
false,
NULL, "mountaineer",
{3000, 3500, 3800, 3900, 4000},
{"3000 ft", "3500 ft", "3800 ft", "3900 ft", "4000 ft"},
[](uint64_t score) { return std::to_string(score) + " ft"; }
@ -398,6 +441,7 @@ static const struct
"Total field area planted with vegetables at any one time",
"peas",
false,
NULL, "farmer",
{5000, 15000, 50000, 200000, 1000000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -407,6 +451,7 @@ static const struct
"Total field area planted with grain at any one time",
"round-straw-bale",
false,
NULL, "farmer",
{5000, 15000, 50000, 200000, 1000000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -416,6 +461,7 @@ static const struct
"Number of different collectible coins owned",
"crown-coin",
false,
NULL, "numismatist",
{5, 10, 15, 25, 50},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -425,6 +471,7 @@ static const struct
"Oldest collectible coin owned (from the beginning of the game - excludes newbie coins)",
"crown-coin",
false,
NULL, NULL,
#define DAYS(x) std::numeric_limits<uint64_t>::max() - ((x) * 86400 / DIFFICULTY_TARGET_V2)
{DAYS(1500), DAYS(365), DAYS(100), DAYS(30), DAYS(5)},
#undef DAYS
@ -436,6 +483,7 @@ static const struct
"Number of collectible coins owned, regardless of type",
"crown-coin",
false,
NULL, NULL,
{10, 25, 75, 200, 500},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -445,6 +493,7 @@ static const struct
"Number of different custom items owned with at least 10 gold per item",
"open-treasure-chest",
false,
NULL, NULL,
{5, 10, 15, 25, 50},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -454,6 +503,7 @@ static const struct
"Number of game ticks a building was on fire before being doused still standing",
"dice-fire",
false,
NULL, NULL,
{5, 10, 15, 20, 25},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -463,6 +513,7 @@ static const struct
"Number of cities in which you have at least one building",
"huts-village",
false,
NULL, NULL,
{2, 3, 4, 5, 6},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -472,6 +523,7 @@ static const struct
"Maximum altitude difference over a single flag",
"peaks",
false,
NULL, NULL,
{200 * HEIGHT_UNITS_PER_BLOCK, 250 * HEIGHT_UNITS_PER_BLOCK, 300 * HEIGHT_UNITS_PER_BLOCK, 350 * HEIGHT_UNITS_PER_BLOCK, 400 * HEIGHT_UNITS_PER_BLOCK},
{"200 ft", "250 ft", "300 ft", "350 ft", "400 ft"},
[](uint64_t score) { return std::to_string(score / HEIGHT_UNITS_PER_BLOCK) + " ft"; }
@ -481,6 +533,7 @@ static const struct
"The road with the highest bridge potential",
"tall-bridge",
false,
NULL, NULL,
{500, 700, 800, 900, 1000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -490,6 +543,7 @@ static const struct
"Collect all the newbie coin variants",
"backpack",
false,
NULL, NULL,
{2, 3, 4, 5, 6},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -499,6 +553,7 @@ static const struct
"Number of buildings on a single island",
"island",
false,
NULL, NULL,
{1, 2, 3, 4, 5},
{"1 (the island must be enclosed in a single newly named rectangular area, all boundaries of which have to be wholly in water)", NULL, NULL, NULL, NULL},
NULL
@ -508,6 +563,7 @@ static const struct
"Number of places named",
"direction-sign",
false,
NULL, "mapmaker",
{5, 10, 15, 25, 50},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -517,6 +573,7 @@ static const struct
"Found and named different types of terrain features",
"treasure-map",
false,
NULL, NULL,
{2, 3, 5, 7, 10},
{"2 (open sea, sand bank, beach, peak, island, lake, plain, reef, peninsula, cove)", NULL, NULL, NULL, NULL},
NULL
@ -526,6 +583,7 @@ static const struct
"Number of rare fish species discovered",
"angler-fish",
false,
NULL, NULL,
{1, 3, 5, 8, 12},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -535,6 +593,7 @@ static const struct
"Number of textures added",
"paint-roller",
false,
NULL, "artist",
{1, 2, 4, 4, 5},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -544,6 +603,7 @@ static const struct
"Number of textures licenced",
"coinflip",
false,
NULL, NULL,
{2, 5, 10, 15, 25},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -553,6 +613,7 @@ static const struct
"Number of runestones carved",
"rune-stone",
false,
"erudite", NULL,
{5, 10, 20, 50, 100},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -562,6 +623,7 @@ static const struct
"Amount of gold smelted",
"melting-metal",
false,
NULL, NULL,
{10 * COIN, 50 * COIN, 250 * COIN, 1000 * COIN, 5000 * COIN},
{"10", "50", "250", "1000", "5000"},
[](uint64_t score) { return cryptonote::print_money(score); }
@ -571,6 +633,7 @@ static const struct
"Number of auctions created",
"hammer-drop",
false,
NULL, NULL,
{3, 10, 25, 75, 250},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -580,6 +643,7 @@ static const struct
"Number of pearls found",
"oyster-pearl",
false,
NULL, NULL,
{5, 10, 20, 50, 100},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -589,6 +653,7 @@ static const struct
"Amount of fish caught",
"boat-fishing",
false,
NULL, NULL,
{500000, 1000000, 2000000, 5000000, 20000000},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -598,6 +663,7 @@ static const struct
"Awarded to encyclopedia writers",
"book-pile",
true,
"erudite", NULL,
{0, 0, 0, 0, 0},
{"", "", "", "", ""},
NULL
@ -607,6 +673,7 @@ static const struct
"Number of different quest items owned",
"open-treasure-chest",
false,
NULL, "hero",
{5, 10, 15, 25, 50},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -616,6 +683,7 @@ static const struct
"Number of epochs covered by coins owned",
"crown-coin/time-trap",
false,
NULL, NULL,
{3, 5, 7, 10, 15},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -625,6 +693,7 @@ static const struct
"Number of epochs covered by buildings owned",
"time-trap",
false,
NULL, NULL,
{3, 5, 7, 10, 15},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -634,6 +703,7 @@ static const struct
"Number of cons smelted which weren't mintable anymore (excluding newbie coins)",
"crown-coin/melting-metal",
false,
NULL, NULL,
{10, 25, 50, 100, 250},
{NULL, NULL, NULL, NULL, NULL},
NULL
@ -658,6 +728,10 @@ bool get_badge_data(const cryptonote::BlockchainDB *db, cc_badge_t badge, cc_bad
data.desc = predefined_badges_data[badge].desc;
data.icon = predefined_badges_data[badge].icon;
data.manual = predefined_badges_data[badge].manual;
if (predefined_badges_data[badge].title_adjective)
data.title_adjective = predefined_badges_data[badge].title_adjective;
if (predefined_badges_data[badge].title_noun)
data.title_noun = predefined_badges_data[badge].title_noun;
data.convert_score = predefined_badges_data[badge].convert_score;
data.thresholds.resize(NUM_BADGE_LEVELS);
for (int i = 0; i < NUM_BADGE_LEVELS; ++i)

View File

@ -112,6 +112,8 @@ struct cc_badge_data_t
std::string desc;
std::string icon;
bool manual;
std::string title_adjective;
std::string title_noun;
std::vector<std::pair<uint64_t, std::string>> thresholds;
std::string (*convert_score)(uint64_t score);
};

View File

@ -305,4 +305,9 @@ cc::cc_epoch_t BlockchainStateProxy::get_cc_epoch(uint64_t height)
return db.get_cc_epoch(height);
}
void BlockchainStateProxy::grant_unique_title(uint32_t id, const std::string title)
{
unique_titles.push_back(std::make_pair(id, title));
}
}

View File

@ -57,6 +57,7 @@ public:
virtual std::pair<uint8_t, uint64_t> get_badge_level(uint32_t id, uint32_t badge);
virtual void award_badge(uint32_t id, uint32_t badge, uint8_t dlevel, uint64_t dtimestamp);
virtual cc::cc_epoch_t get_cc_epoch(uint64_t height);
virtual void grant_unique_title(uint32_t id, const std::string title);
const std::map<std::pair<uint32_t, uint32_t>, int64_t> &get_balance_reserve_deltas() const { return balance_reserve_delta; }
const std::map<std::tuple<uint32_t, uint32_t, uint32_t>, int32_t> &get_item_balance_reserve_deltas() const { return item_balance_reserve_delta; }
@ -66,6 +67,7 @@ public:
const std::map<std::pair<uint32_t, std::string>, int64_t> &get_local_variable_deltas() const { return local_variable_delta; }
const std::map<std::pair<uint32_t, uint32_t>, std::pair<uint8_t, uint64_t>> &get_badge_deltas() const { return badge_delta; }
const std::set<uint32_t> get_new_background_scripts() const { return new_background_scripts; }
const std::vector<std::pair<uint32_t, std::string>> get_new_unique_titles() const { return unique_titles; }
private:
const cryptonote::BlockchainDB &db;
@ -77,6 +79,7 @@ private:
std::map<std::pair<uint32_t, std::string>, int64_t> local_variable_delta;
std::set<uint32_t> new_background_scripts;
std::map<std::pair<uint32_t, uint32_t>, std::pair<uint8_t, uint64_t>> badge_delta;
std::vector<std::pair<uint32_t, std::string>> unique_titles;
};
}

View File

@ -315,6 +315,10 @@ bool cc_command_handler_script_choice::execute(cryptonote::BlockchainDB &db, con
ad.badges[e.badge].second += e.timestamp_delta;
db.set_cc_account_badges(e.account, ad.badges);
}
for (const auto &e: effects.new_unique_titles)
{
db.grant_cc_account_unique_title(e.first, e.second);
}
if (cc::script::is_end_state(script, new_state))
{
@ -545,6 +549,10 @@ bool cc_command_handler_script_choice::revert(cryptonote::BlockchainDB &db, cons
ad.badges[e.badge].second -= e.timestamp_delta;
db.set_cc_account_badges(e.account, ad.badges);
}
for (const auto &e: effects.new_unique_titles)
{
db.rescind_cc_account_unique_title(e.first, e.second);
}
// the reserves increase from execute will have been recorded in effects,
// therefore already undone, we just have the actual balances to update

View File

@ -0,0 +1,135 @@
// 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_config.h"
#include "cc/cc.h"
#include "cc/cc_title.h"
#include "cc_command_handler_helpers.h"
#include "cc_command_handler_set_title.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "verify"
static bool is_present(uint32_t value, const std::vector<std::pair<uint32_t, std::string>> &values)
{
for (const auto &e: values)
if (value == e.first)
return true;
return false;
}
namespace cc
{
cc_command_handler_set_title cc_command_handler_set_title::instance;
void cc_command_handler_set_title::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_set_title::get_cost(const cryptonote::cc_command_t &cmd) const
{
return 0;
}
bool cc_command_handler_set_title::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const
{
const cryptonote::cc_command_set_title_t &set_title = boost::get<cryptonote::cc_command_set_title_t>(cmd);
cryptonote::cc_account_data_t ad;
CHECK_COMMAND_SET(db.get_cc_account_data(set_title.cc_account, ad), tvc, m_cc_invalid_account, "Account not found");
CHECK_COMMAND_SET(set_title.delta_adjective || set_title.delta_noun || set_title.delta_origin || set_title.delta_unique,
tvc, m_cc_invalid_previous_state, "set_title does not change anything");
const int32_t adjective = ad.title_adjective + set_title.delta_adjective;
const int32_t noun = ad.title_noun + set_title.delta_noun;
const int32_t origin = ad.title_origin + set_title.delta_origin;
const int32_t unique = ad.title_unique + set_title.delta_unique;
std::vector<std::pair<uint32_t, std::string>> adjectives, nouns, origins, uniques;
cc::get_available_title_components(db, set_title.cc_account, adjectives, nouns, origins, uniques);
CHECK_COMMAND_SET(adjective == -1 || is_present(adjective, adjectives), tvc, m_cc_not_allowed, "Title adjective not available to account");
CHECK_COMMAND_SET(noun == -1 || is_present(noun, nouns), tvc, m_cc_not_allowed, "Title noun not available to account");
CHECK_COMMAND_SET(origin == -1 || is_present(origin, origins), tvc, m_cc_not_allowed, "Title origin not available to account");
CHECK_COMMAND_SET(unique == -1 || (uint32_t)unique < ad.unique_titles.size(), tvc, m_cc_not_allowed, "Unique title not available to account");
const bool has_compound = adjective >= 0 || noun >= 0 || origin >= 0;
const bool has_unique = unique >= 0;
CHECK_COMMAND_SET(!(has_compound && has_unique), tvc, m_cc_not_allowed, "Title must be either compound or unique, but not both at once");
return true;
}
bool cc_command_handler_set_title::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const
{
const cryptonote::cc_command_set_title_t &set_title = boost::get<cryptonote::cc_command_set_title_t>(cmd);
cryptonote::cc_account_data_t ad;
CHECK_AND_ASSERT_MES(db.get_cc_account_data(set_title.cc_account, ad), false, "Account not found");
const int32_t new_adjective = ad.title_adjective + set_title.delta_adjective;
const int32_t new_noun = ad.title_noun + set_title.delta_noun;
const int32_t new_origin = ad.title_origin + set_title.delta_origin;
const int32_t new_unique = ad.title_unique + set_title.delta_unique;
const std::string adjective = cc::get_title_adjective(db, new_adjective);
const std::string noun = cc::get_title_noun(db, new_noun);
const std::string origin = cc::get_title_origin(db, new_origin);
const std::string unique = cc::get_title_unique(db, set_title.cc_account, new_unique);
const std::string title = cc::get_title(adjective, noun, origin, unique);
CHECK_AND_ASSERT_MES(db.set_cc_account_title(set_title.cc_account, new_adjective, new_noun, new_origin, new_unique, title), false, "Failed to set title");
events.add_full(cmd, set_title.cc_account, 0, 0, ITEM_NONE, 0, 0, tx_fee) << "Changed title to '" << title << "'";
return true;
}
bool cc_command_handler_set_title::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const
{
const cryptonote::cc_command_set_title_t &set_title = boost::get<cryptonote::cc_command_set_title_t>(cmd);
cryptonote::cc_account_data_t ad;
CHECK_AND_ASSERT_MES(db.get_cc_account_data(set_title.cc_account, ad), false, "Account not found");
const int32_t old_adjective = ad.title_adjective - set_title.delta_adjective;
const int32_t old_noun = ad.title_noun - set_title.delta_noun;
const int32_t old_origin = ad.title_origin - set_title.delta_origin;
const int32_t old_unique = ad.title_unique - set_title.delta_unique;
const std::string adjective = cc::get_title_adjective(db, old_adjective);
const std::string noun = cc::get_title_noun(db, old_noun);
const std::string origin = cc::get_title_origin(db, old_origin);
const std::string unique = cc::get_title_unique(db, set_title.cc_account, old_unique);
const std::string title = cc::get_title(adjective, noun, origin, unique);
CHECK_AND_ASSERT_MES(db.set_cc_account_title(set_title.cc_account, old_adjective, old_noun, old_origin, old_unique, title), false, "Failed to reset title");
return true;
}
}

View 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_set_title: 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, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const;
virtual bool execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const;
virtual bool revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const;
static cc_command_handler_set_title instance;
};
}

View File

@ -250,6 +250,10 @@ bool cc_command_handler_start_script::execute(cryptonote::BlockchainDB &db, cons
ad.badges[e.badge].second += e.timestamp_delta;
db.set_cc_account_badges(e.account, ad.badges);
}
for (const auto &e: effects.new_unique_titles)
{
db.grant_cc_account_unique_title(e.first, e.second);
}
if (cc::script::is_end_state(script, 0))
{
@ -473,6 +477,10 @@ bool cc_command_handler_start_script::revert(cryptonote::BlockchainDB &db, const
ad.badges[e.badge].second -= e.timestamp_delta;
db.set_cc_account_badges(e.account, ad.badges);
}
for (const auto &e: effects.new_unique_titles)
{
db.rescind_cc_account_unique_title(e.first, e.second);
}
const auto overrides = cc::script::get_script_overrides(script);
cc::runestone_t runestone;

View File

@ -304,6 +304,9 @@ static void print_action_string(const Action &a, std::string &source, const std:
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 2, "Expected two operands for action_create_item, got " << a.ops.size());
source += I + "create item \"" + get_operand_string(a.ops[0], op_unsigned) + " " + get_operand_string(a.ops[1], op_unsigned) + "\"\n";
break;
case action_award_title:
source += I + "award title \"" + escape(a.str) + "\"\n";
break;
}
}
@ -1774,6 +1777,13 @@ static bool execute(cryptonote::cc_command_t cmd, BlockchainStateProxy &proxy, g
events.add_full(cmd, owner, account, 0, value, value_extra, -(int64_t)(gold_needed + fee_bonus), 0) << "Created " << value_extra << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
}
break;
case action_award_title:
{
const std::string title = process_format_string(proxy, account, owner, city, seed, salt, action.str, action.ops);
proxy.grant_unique_title(account, title);
events.add_full(cmd, account, 0, 0, ITEM_NONE, 0, 0, 0) << "Awarded the title '" << title << "'";
}
break;
}
return true;
}
@ -1887,6 +1897,7 @@ void set_script_effects(const BlockchainStateProxy &proxy, script_effects_t &eff
const std::map<std::pair<uint32_t, uint32_t>, std::pair<uint8_t, uint64_t>> &badges = proxy.get_badge_deltas();
for (const auto &e: badges)
effects.badges.push_back({e.first.first, e.first.second, e.second.first, e.second.second});
effects.new_unique_titles = proxy.get_new_unique_titles();
}
static void reset_local_variables(BlockchainStateProxy &proxy, uint32_t account)

View File

@ -125,6 +125,7 @@ struct script_effects_t
std::vector<string_override_removal_t> string_override_removals;
std::vector<uint32_t> new_background_scripts;
std::vector<badge_delta_t> badges;
std::vector<std::pair<uint32_t, std::string>> new_unique_titles;
BEGIN_SERIALIZE_OBJECT()
FIELD(balances)
@ -138,6 +139,7 @@ struct script_effects_t
FIELD(string_override_removals)
FIELD(new_background_scripts)
FIELD(badges)
FIELD(new_unique_titles);
END_SERIALIZE()
};

232
src/cc/cc_title.cc Normal file
View File

@ -0,0 +1,232 @@
#include "blockchain_db/blockchain_db.h"
#include "cc_epoch.h"
#include "cc_badge.h"
#include "cc_title.h"
#define ADJECTIVE_BADGE_FLAG 0x1000
#define NOUN_BADGE_FLAG 0x1000
#define ORIGIN_COUNTRY_FLAG 0x2000
#define ORIGIN_CITY_FLAG 0x1000
static const char * const countries[] =
{
"Brittany",
"Cornwall",
"Danelaw",
"England",
"Finland",
"Flanders",
"Francia",
"Føroyar",
"Gőtland",
"Hjaltland",
"Iceland",
"Ireland",
"Jutland",
"Kievan Rus",
"Mercia",
"Normandy",
"Northumbria",
"Norway",
"Orkney",
"Pomerania",
"Saxony",
"Scotland",
"Shetland",
"Suðreyjar",
"Sutherland",
"Sweden",
"Wales",
"Wessex",
"York",
};
struct title_component_t
{
const char * const string;
bool (*allowed)(const cryptonote::BlockchainDB&, uint32_t);
};
static void push(std::vector<std::pair<uint32_t, std::string>> &v, const std::pair<uint32_t, std::string> &e)
{
for (const auto &ve: v)
if (ve.second == e.second)
return;
v.push_back(e);
}
namespace cc
{
#define TCIF(x) [](const cryptonote::BlockchainDB &db, uint32_t id) { x; }
static const title_component_t builtin_adjectives[] =
{
{ "ancient", TCIF( cryptonote::cc_account_data_t ad; if (!db.get_cc_account_data(id, ad)) return false; return cc::get_epoch_index(db.get_cc_epochs(), ad.creation_height) + 4 < db.get_cc_epoch(db.height() - 1).index; ) },
};
static const title_component_t builtin_nouns[] =
{
{ "newcomer", NULL },
{ "millionaire", TCIF( uint64_t b; return db.get_cc_account_balance(id, b) && b >= 1000000 * COIN; ) },
};
#undef TCIF
std::string get_title(const std::string &adjective, const std::string &noun, const std::string &origin, const std::string &unique)
{
std::string s;
if (!unique.empty())
{
s += unique;
return s;
}
if (!adjective.empty() || !noun.empty())
{
s += "the";
if (!adjective.empty())
{
s += " ";
s += adjective;
}
if (!noun.empty())
{
s += " ";
s += noun;
}
}
if (!origin.empty())
{
if (!s.empty())
s += " ";
s += "of ";
s += origin;
}
return s;
}
void get_available_title_components(const cryptonote::BlockchainDB &db, uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques)
{
cryptonote::cc_account_data_t ad;
CHECK_AND_ASSERT_THROW_MES(db.get_cc_account_data(id, ad), "Account not found");
adjectives.clear();
for (uint32_t i = 0; i < sizeof(builtin_adjectives) / sizeof(builtin_adjectives[0]); ++i)
if (builtin_adjectives[i].allowed == NULL || (*builtin_adjectives[i].allowed)(db, id))
push(adjectives, std::make_pair(i, builtin_adjectives[i].string));
nouns.clear();
for (uint32_t i = 0; i < sizeof(builtin_nouns) / sizeof(builtin_nouns[0]); ++i)
if (builtin_nouns[i].allowed == NULL || (*builtin_nouns[i].allowed)(db, id))
push(nouns, std::make_pair(i, builtin_nouns[i].string));
origins.clear();
db.for_all_cc_cities([&origins](const cryptonote::cc_city_data_t &cd){
push(origins, std::make_pair(ORIGIN_CITY_FLAG | cd.id, cd.name));
return true;
});
for (uint32_t i = 0; i < sizeof(countries) / sizeof(countries[0]); ++i)
push(origins, std::make_pair(i | ORIGIN_COUNTRY_FLAG, countries[i]));
uniques.clear();
for (uint32_t i = 0; i < ad.unique_titles.size(); ++i)
push(uniques, std::make_pair(i, ad.unique_titles[i]));
for (const auto &e: ad.badges)
{
if (e.first < cc::NUM_PREDEFINED_BADGES && e.second.first >= 5)
{
cc::cc_badge_data_t data;
if (cc::get_badge_data(&db, (cc_badge_t)e.first, data))
{
if (!data.title_adjective.empty())
push(adjectives, std::make_pair(ADJECTIVE_BADGE_FLAG | e.first, data.title_adjective));
if (!data.title_noun.empty())
push(nouns, std::make_pair(NOUN_BADGE_FLAG | e.first, data.title_noun));
}
}
}
}
std::string get_title_adjective(const cryptonote::BlockchainDB &db, int32_t idx)
{
if (idx < 0)
return "";
if (idx & ADJECTIVE_BADGE_FLAG)
{
cc::cc_badge_data_t data;
if (!cc::get_badge_data(&db, (cc::cc_badge_t)(idx & ~ADJECTIVE_BADGE_FLAG), data))
{
MERROR("Adjective badge not found: " << idx);
return "";
}
if (data.title_adjective.empty())
MERROR("Adjective badge has empty noun: " << idx);
return data.title_adjective;
}
if ((uint32_t)idx >= sizeof(builtin_adjectives) / sizeof(builtin_adjectives[0]))
return "";
return builtin_adjectives[idx].string;
}
std::string get_title_noun(const cryptonote::BlockchainDB &db, int32_t idx)
{
if (idx < 0)
return "";
if (idx & NOUN_BADGE_FLAG)
{
cc::cc_badge_data_t data;
if (!cc::get_badge_data(&db, (cc::cc_badge_t)(idx & ~NOUN_BADGE_FLAG), data))
{
MERROR("Noun badge not found: " << idx);
return "";
}
if (data.title_noun.empty())
MERROR("Noun badge has empty noun: " << idx);
return data.title_noun;
}
if ((uint32_t)idx >= sizeof(builtin_nouns) / sizeof(builtin_nouns[0]))
return "";
return builtin_nouns[idx].string;
}
std::string get_title_origin(const cryptonote::BlockchainDB &db, int32_t idx)
{
if (idx < 0)
return "";
if (idx & ORIGIN_CITY_FLAG)
{
cryptonote::cc_city_data_t cd;
if (!db.get_cc_city_data(idx & ~ORIGIN_CITY_FLAG, cd))
{
MERROR("Origin city not found: " << idx);
return "nowhere";
}
return cd.name;
}
if (idx & ORIGIN_COUNTRY_FLAG)
{
if ((uint32_t)(idx & ~ORIGIN_COUNTRY_FLAG) < sizeof(countries) / sizeof(countries[0]))
return countries[idx & ~ORIGIN_COUNTRY_FLAG];
}
MERROR("Bad origin idx: " << idx);
return "nowhere";
}
std::string get_title_unique(const cryptonote::BlockchainDB &db, uint32_t id, int32_t idx)
{
cryptonote::cc_account_data_t ad;
CHECK_AND_ASSERT_THROW_MES(db.get_cc_account_data(id, ad), "Account not found");
if (idx < 0 || (uint32_t)idx >= ad.unique_titles.size())
return "";
return ad.unique_titles[idx];
}
}

23
src/cc/cc_title.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <string>
namespace cryptonote
{
class BlockchainDB;
}
namespace cc
{
std::string get_title(const std::string &adjective, const std::string &noun, const std::string &origin, const std::string &unique);
void get_available_title_components(const cryptonote::BlockchainDB &db, uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques);
std::string get_title_adjective(const cryptonote::BlockchainDB &db, int32_t idx);
std::string get_title_noun(const cryptonote::BlockchainDB &db, int32_t idx);
std::string get_title_origin(const cryptonote::BlockchainDB &db, int32_t idx);
std::string get_title_unique(const cryptonote::BlockchainDB &db, uint32_t id, int32_t idx);
}

View File

@ -177,6 +177,7 @@ typedef enum ActionType
action_log,
action_call,
action_create_item,
action_award_title,
} ActionType;
static const struct
{
@ -201,7 +202,7 @@ static const struct
{ "start background script", action_start_background_script },
{ "log", action_log },
{ "call", action_call },
{ "create item", action_create_item },
{ "award title", action_award_title },
};
#ifdef __cplusplus

View File

@ -125,6 +125,7 @@ create { return CREATE; }
during { return DURING; }
fees { return FEES; }
epoch { return EPOCH; }
title { return TITLE; }
\+ { return ADD; }
- { return SUB; }

View File

@ -37,7 +37,7 @@ static script_partial_state_t *state = NULL;
%token <number> PERCENT PAY CONSUME TEMPERATURE_NUMBER TEMPERATURE RANDOM
%token <number> IMAGE UI CHOICES CHOICE NEXT SELECTED ENABLED ACTIONS PUBLIC IS BLOCKCHAIN BY OVERRIDES ID
%token <number> GEMSTONE BLOCK LABOUR COIN FOOD CUSTOM IF ELSE STORYLINE RESTRICTED START BACKGROUND LOG
%token <number> PROCEDURE CALL WITH ROLE FLAG CREATE DURING FEES EPOCH
%token <number> PROCEDURE CALL WITH ROLE FLAG CREATE DURING FEES EPOCH TITLE
%type <number> script script_contents script_content choice_contents choice_content
%type <number> name owner description icon precondition reserves state public storyline
@ -139,6 +139,7 @@ action: action_percent
| action_log
| action_call
| action_create_item
| action_award_title
;
action_percent: PERCENT operand action { set_partial_state_action_percent(state); }
@ -207,6 +208,9 @@ action_call: CALL STRING { set_partial_state_action(state, action_call, $2, 0);
action_create_item: CREATE ITEM operand operand { set_partial_state_action(state, action_create_item, NULL, 2); }
;
action_award_title: AWARD TITLE STRING { set_partial_state_action(state, action_award_title, $3, 0); }
;
action_none: NONE { set_partial_state_action(state, action_none, NULL, 0); }
;

View File

@ -109,6 +109,7 @@ const cc_command_basenonce_t *get_cc_command_basenonce(const cc_command_t &cmd)
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_service_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_set_title_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
@ -184,6 +185,7 @@ cc_command_basenonce_t *get_cc_command_basenonce(cc_command_t &cmd)
cc_command_basenonce_t *operator()(cryptonote::cc_command_service_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_set_title_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
@ -259,6 +261,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_service_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_set_title_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
@ -334,6 +337,7 @@ cc_command_base_t *get_cc_command_base(cc_command_t &cmd)
cc_command_base_t *operator()(cryptonote::cc_command_service_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_set_title_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
@ -409,6 +413,7 @@ bool is_cc_command_restricted(const cc_command_t &cmd)
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_title_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return false; }
@ -484,6 +489,7 @@ bool cc_command_has_signature(const cc_command_t &cmd)
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_title_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return true; }

View File

@ -1462,6 +1462,22 @@ namespace cryptonote
END_SERIALIZE()
};
struct cc_command_set_title_t: public cc_command_base_t
{
int32_t delta_adjective;
int32_t delta_noun;
int32_t delta_origin;
int32_t delta_unique;
BEGIN_SERIALIZE_OBJECT()
FIELDS(*static_cast<cc_command_base_t*>(this))
VARINT_FIELD_SIGNED(delta_adjective)
VARINT_FIELD_SIGNED(delta_noun)
VARINT_FIELD_SIGNED(delta_origin)
VARINT_FIELD_SIGNED(delta_unique)
END_SERIALIZE()
};
struct cc_command_game_update_t: public cc_command_basenonce_t
{
struct flag_t
@ -1868,7 +1884,8 @@ namespace cryptonote
cc_command_salt_food_t,
cc_command_retrieve_items_t,
cc_command_create_runestones_t,
cc_command_start_epoch_t
cc_command_start_epoch_t,
cc_command_set_title_t
> cc_command_t;
cc_command_basenonce_t *get_cc_command_basenonce(cc_command_t &cmd);
@ -2051,6 +2068,7 @@ CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_salt_food_t, (uint8_t)0x3f
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_retrieve_items_t, (uint8_t)0x40);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_create_runestones_t, (uint8_t)0x41);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_start_epoch_t, (uint8_t)0x42);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_set_title_t, (uint8_t)0x43);
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");
@ -2119,6 +2137,7 @@ CC_VARIANT_TAG(json_archive, cryptonote::cc_command_salt_food_t, (const char*)"s
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_retrieve_items_t, (const char*)"retrieve_items");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_create_runestones_t, (const char*)"create_runestones");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_start_epoch_t, (const char*)"start_epoch");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_set_title_t, (const char*)"set_title");
VARIANT_TAG(debug_archive, cryptonote::cc_command_none_t, "none");
VARIANT_TAG(debug_archive, cryptonote::cc_command_create_account_t, "create_account");
@ -2187,3 +2206,4 @@ VARIANT_TAG(debug_archive, cryptonote::cc_command_salt_food_t, "salt_food");
VARIANT_TAG(debug_archive, cryptonote::cc_command_retrieve_items_t, "retrieve_items");
VARIANT_TAG(debug_archive, cryptonote::cc_command_create_runestones_t, "create_runestones");
VARIANT_TAG(debug_archive, cryptonote::cc_command_start_epoch_t, "start_epoch");
VARIANT_TAG(debug_archive, cryptonote::cc_command_set_title_t, "set_title");

View File

@ -184,6 +184,7 @@ struct cc_snapshot
{
uint32_t id;
std::string name;
std::string title;
bool ignore;
bool autonomous;
std::vector<uint32_t> badges;
@ -194,6 +195,7 @@ struct cc_snapshot
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(id)
KV_SERIALIZE(name)
KV_SERIALIZE(title)
KV_SERIALIZE(ignore)
KV_SERIALIZE(autonomous)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(badges)
@ -205,6 +207,7 @@ struct cc_snapshot
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(id)
FIELD(name)
FIELD(title)
FIELD(ignore)
FIELD(autonomous)
FIELD(badges)

View File

@ -4057,6 +4057,9 @@ bool Blockchain::check_cc_cmd_signature(const transaction& tx) const
static bool is_command_allowed(const cryptonote::cc_command_t &cmd, uint8_t hf_version)
{
if (cmd.type() == typeid(cryptonote::cc_command_set_title_t) && hf_version < HF_VERSION_TOWNFORGE_TESTNET_UPDATE_3)
return false;
return true;
}

View File

@ -122,6 +122,7 @@ set(game_sources
ui-fight-fire.cc
ui-fish.cc
ui-file-selector.cc
ui-change-title.cc
ui-city-maps.cc
ui-go-to-vista.cc
ui-harvest.cc
@ -240,6 +241,7 @@ set(game_headers
ui-auctions.h
ui-building-settings.h
ui-carve-runestone.h
ui-change-title.h
ui-city-level.h
ui-configure-script.h
ui-console.h

View File

@ -118,7 +118,7 @@ void PlayerState::update(const std::shared_ptr<GameWallet> &wallet)
{
std::string pmspk, pmvpk;
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, description, ignored, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk);
w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignored, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk);
reserved_balance = 0;
for (const auto &e: reserve)
{
@ -735,7 +735,7 @@ bool GameState::process_dice_roll(const cryptonote::cc_command_dice_roll_t &cmd,
uint32_t bonus = 0;
if (cmd.account)
{
std::string public_key, pmspk, pmvpk;
std::string public_key, pmspk, pmvpk, title;
uint64_t balance;
std::map<uint32_t, uint32_t> item_balances, attributes;
std::vector<uint32_t> flags;
@ -751,7 +751,8 @@ bool GameState::process_dice_roll(const cryptonote::cc_command_dice_roll_t &cmd,
uint32_t prestige;
std::vector<uint32_t> textures_created, textures_licenced;
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
if (!w->get_cc_account_data(cmd.account, public_key, balance, item_balances, flags, badges, attributes, name, description, ignored, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
int32_t title_adjective, title_noun, title_origin, title_unique;
if (!w->get_cc_account_data(cmd.account, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignored, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
return true;
bonus = attributes[cmd.attribute];
}
@ -1269,6 +1270,14 @@ bool GameState::process_set_script_variables(const cryptonote::cc_command_set_sc
return true;
}
bool GameState::process_set_title(const cryptonote::cc_command_set_title_t &cmd, const std::shared_ptr<GameWallet> &w)
{
TRIGGER_TUTORIAL(cmd, "set-title");
player_names.erase(cmd.cc_account); // will be fetched again
// player auto updates at every block, nothing to do in playerState
return true;
}
bool GameState::process_add_tax_break_zone(const cryptonote::cc_command_add_tax_break_zone_t &cmd, const std::shared_ptr<GameWallet> &w)
{
if (cmd.city == cityState.id)
@ -1409,6 +1418,7 @@ bool GameState::process_command(const cryptonote::cc_command_t &cmd, const std::
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return self.process_service(cmd, w); }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return self.process_set_merchant_ship_items(cmd, w); }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return self.process_set_script_variables(cmd, w); }
bool operator()(const cryptonote::cc_command_set_title_t &cmd) const { return self.process_set_title(cmd, w); }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return self.process_add_tax_break_zone(cmd, w); }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return self.process_smelt(cmd, w); }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return self.process_sow(cmd, w); }
@ -1443,7 +1453,7 @@ void GameState::SendGameNotification(bool important, const String &s, const Stri
bool GameState::ignore_player(uint32_t id) const
{
const uint32_t type = cc_ignore ? cc_ignore->type : (uint32_t)tools::cc_ignore_t::recommendations;
std::map<uint32_t, std::tuple<std::string, bool, bool>>::const_iterator i;
std::map<uint32_t, std::tuple<std::string, std::string, bool, bool>>::const_iterator i;
switch (type)
{
default:
@ -1451,7 +1461,7 @@ bool GameState::ignore_player(uint32_t id) const
i = player_names.find(id);
if (i == player_names.end())
return false;
return std::get<1>(i->second);
return std::get<2>(i->second);
case tools::cc_ignore_t::nothing:
return false;
case tools::cc_ignore_t::custom:
@ -1464,7 +1474,7 @@ bool GameState::ignore_player(uint32_t id) const
return true;
i = player_names.find(id);
if (i != player_names.end())
return std::get<1>(i->second);
return std::get<2>(i->second);
return false;
}
return false;
@ -1563,7 +1573,7 @@ bool GameState::ignore_item(uint32_t id) const
return false;
}
std::string GameState::get_player_name(uint32_t id) const
std::string GameState::get_player_name(uint32_t id, bool with_title) const
{
auto i = player_names.find(id);
if (i == player_names.end())
@ -1575,7 +1585,12 @@ std::string GameState::get_player_name(uint32_t id) const
}
i = player_names.find(id);
if (i != player_names.end() && !ignore_player(id) && !std::get<0>(i->second).empty())
return std::get<0>(i->second);
{
std::string s = std::get<0>(i->second);
if (with_title && !std::get<1>(i->second).empty())
s += " " + std::get<1>(i->second);
return s;
}
return "Player " + std::to_string(id);
}
@ -1615,7 +1630,7 @@ bool GameState::is_autonomous_player(uint32_t id) const
}
i = player_names.find(id);
if (i != player_names.end())
return std::get<2>(i->second);
return std::get<3>(i->second);
return false;
}
@ -1902,7 +1917,7 @@ bool GameState::reset(const cryptonote::cc_snapshot *snapshot)
for (const auto &e: snapshot->player_data)
{
set_player_name(e.id, e.name, e.ignore, e.autonomous);
set_player_name(e.id, e.name, e.title, e.ignore, e.autonomous);
if (e.autonomous)
continue;
const auto score_level = cc::get_badge_score(e.badges);

View File

@ -20,6 +20,7 @@ URHO3D_EVENT(E_CRYPTOCITY_REQUEST_PLAYER_DATA, RequestPlayerData)
URHO3D_PARAM(P_PUBLIC_KEY, PublicKey);
URHO3D_PARAM(P_BALANCE, Balance);
URHO3D_PARAM(P_NAME, Name);
URHO3D_PARAM(P_TITLE, Title);
URHO3D_PARAM(P_DESCRIPTION, Description);
URHO3D_PARAM(P_ITEM_BALANCES, ItemBalances);
URHO3D_PARAM(P_FLAGS, Flags);
@ -163,6 +164,8 @@ struct PlayerState
uint32_t prestige;
std::vector<uint32_t> textures_created;
std::vector<uint32_t> textures_licenced;
int32_t title_adjective, title_noun, title_origin, title_unique;
std::string title;
PlayerState(): id(0), balance(0), wallet_balance(0), wallet_unlocked_balance(0), reserved_balance(0), name(""), has_wallet(false), ignored(false), inviting_account(0), num_invited(0), first_flag(0), script(0), script_state(0), script_city(0), script_owner(0), prestige(0) { }
void update(const std::shared_ptr<GameWallet> &w);
@ -182,7 +185,7 @@ public:
PlayerState playerState;
CityState cityState;
uint64_t subsidy;
std::map<uint32_t, std::tuple<std::string, bool, bool>> player_names;
std::map<uint32_t, std::tuple<std::string, std::string, bool, bool>> player_names;
std::map<uint32_t, cc::cc_custom_item_t> item_data;
std::map<uint32_t, std::tuple<std::string, std::string, std::string>> badge_names;
std::vector<cryptonote::city_t> cities;
@ -211,10 +214,10 @@ public:
void clear_dirty_flags() { dirty_flags.clear(); }
void add_dirty_flag(const std::shared_ptr<Flag> &flag, bool changed_on_chain);
bool reset(const cryptonote::cc_snapshot *snapshot = NULL);
void set_player_name(uint32_t id, const std::string &name, bool ignore, bool autonomous) { player_names[id] = std::make_tuple(name, ignore, autonomous); }
void set_player_name(uint32_t id, const std::string &name, const std::string &title, bool ignore, bool autonomous) { player_names[id] = std::make_tuple(name, title, ignore, autonomous); }
void set_item_data(uint32_t id, const cc::cc_custom_item_t &cid) { item_data[id] = cid; }
void set_badge_name_and_desc(uint32_t id, const std::string &name, const std::string &desc, const std::string &icon) { badge_names[id] = std::make_tuple(name, desc, icon); }
std::string get_player_name(uint32_t id) const;
std::string get_player_name(uint32_t id, bool with_title = false) const;
std::string get_player_name(const crypto::public_key &pkey) const;
uint32_t get_player_by_name(const std::string &name) const;
bool is_autonomous_player(uint32_t id) const;
@ -296,6 +299,7 @@ private:
bool process_service(const cryptonote::cc_command_service_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_set_merchant_ship_items(const cryptonote::cc_command_set_merchant_ship_items_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_set_script_variables(const cryptonote::cc_command_set_script_variables_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_set_title(const cryptonote::cc_command_set_title_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_add_tax_break_zone(const cryptonote::cc_command_add_tax_break_zone_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_smelt(const cryptonote::cc_command_smelt_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_sow(const cryptonote::cc_command_sow_t &cmd, const std::shared_ptr<GameWallet> &w);

View File

@ -193,6 +193,7 @@ std::string get_command_string(const GameState *game, const cryptonote::cc_comma
msg.push_back("'" + e.name + "' to " + std::to_string(e.new_value));
return "Setting script variables " + boost::join(msg, ", ");
}
std::string operator()(const cryptonote::cc_command_set_title_t &cmd) const { return "Changing title"; }
std::string operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return "Adding a tax break zone"; }
std::string operator()(const cryptonote::cc_command_smelt_t &cmd) const { return "Smelting " + std::to_string(cmd.amount) + " collectible coins"; }
std::string operator()(const cryptonote::cc_command_sow_t &cmd) const { return "Sowing " + std::string(cc::get_crop_name(cmd.crop)) + " in " + game_util::get_building_name(game, cmd.flag); }
@ -436,7 +437,7 @@ std::pair<std::string, crypto::hash> get_item_info(const GameState *game, const
ss << "Group: " << group << "\n";
}
ss << "Type: user defined\n";
ss << "Creator: " << game->get_player_name(creator) << "\n";
ss << "Creator: " << game->get_player_name(creator, true) << "\n";
ss << "Amount: " << amount << (can_create_more ? " (more can be created)" : " (fixed)") << "\n";
}
}

View File

@ -361,7 +361,7 @@ public:
uint32_t get_cc_account();
crypto::public_key get_cc_pkey();
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::map<uint32_t, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk);
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, int32_t &title_adjective, int32_t &title_noun, int32_t &title_origin, int32_t &title_unique, std::string &title, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk);
bool get_cc_account_reserve(uint32_t id, uint32_t account, uint64_t &balance, std::map<uint32_t, uint32_t> &items);
bool get_cc_custom_item_data(uint32_t id, std::string &name);
bool get_cc_custom_item_data(uint32_t id, uint64_t &creation_height, uint32_t &creator, uint64_t &amount, std::string &name, bool &is_group, bool &is_public, uint32_t &group, std::string &primary_description, std::string &secondary_description, bool &ignore, uint64_t &gold, std::vector<uint64_t> &user_data, crypto::hash &hash, bool &can_create_more, uint32_t &prestige_bonus, std::vector<uint32_t> &role_bonus);
@ -436,6 +436,7 @@ public:
void add_cc_vista(const std::string &vista, const std::string &label, const std::string &picture);
void delete_cc_vista(const std::string &vista);
const std::vector<std::tuple<std::string, std::string, std::string>> &get_cc_vistas();
bool get_cc_available_title_components(uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques);
std::shared_ptr<tools::wallet2> wallet() { boost::unique_lock<boost::mutex> lock(mutex); return internal_wallet; }
bool is_spectator() const { return spectator; }
@ -1662,6 +1663,13 @@ const std::vector<std::tuple<std::string, std::string, std::string>> &GameWallet
return w->get_cc_vistas();
}
bool GameWalletInternal::get_cc_available_title_components(uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques)
{
std::shared_ptr<tools::wallet2> w = wallet();
boost::unique_lock<boost::mutex> lock(mutex);
return w->get_cc_available_title_components(id, adjectives, nouns, origins, uniques);
}
bool GameWalletInternal::get_cc_accounts(std::vector<std::tuple<uint32_t, std::string, bool, bool>> &accounts)
{
std::shared_ptr<tools::wallet2> w = wallet();
@ -1710,11 +1718,11 @@ crypto::public_key GameWalletInternal::get_cc_pkey()
return pkey;
}
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk)
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, int32_t &title_adjective, int32_t &title_noun, int32_t &title_origin, int32_t &title_unique, std::string &title, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk)
{
std::shared_ptr<tools::wallet2> w = wallet();
boost::unique_lock<boost::mutex> lock(mutex);
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
return false;
return true;
}
@ -1728,7 +1736,7 @@ bool GameWalletInternal::get_cc_account_reserve(uint32_t id, uint32_t account, u
bool GameWalletInternal::get_cc_account_data(uint32_t id, std::string &name)
{
std::string public_key, pmspk, pmvpk;
std::string public_key, pmspk, pmvpk, title;
uint64_t balance;
std::map<uint32_t, uint32_t> item_balances;
std::vector<uint32_t> flags;
@ -1745,11 +1753,12 @@ bool GameWalletInternal::get_cc_account_data(uint32_t id, std::string &name)
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
uint32_t prestige;
std::vector<uint32_t> textures_created, textures_licenced;
int32_t title_adjective, title_noun, title_origin, title_unique;
std::shared_ptr<tools::wallet2> w = wallet();
boost::unique_lock<boost::mutex> lock(mutex);
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
if (!w->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
return false;
return true;
}
@ -2666,6 +2675,7 @@ void GameWalletInternal::on_reorg(uint64_t height)
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_set_title_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_start_epoch_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_start_script_t &cmd) const { return false; }
@ -3046,6 +3056,11 @@ const std::vector<std::tuple<std::string, std::string, std::string>> &GameWallet
return internal->get_cc_vistas();
}
bool GameWallet::get_cc_available_title_components(uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques)
{
return internal->get_cc_available_title_components(id, adjectives, nouns, origins, uniques);
}
uint32_t GameWallet::get_cc_account()
{
return internal->get_cc_account();
@ -3086,9 +3101,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::map<uint32_t, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk)
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, int32_t &title_adjective, int32_t &title_noun, int32_t &title_origin, int32_t &title_unique, std::string &title, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk)
{
return internal->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk);
return internal->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk);
}
bool GameWallet::get_cc_account_reserve(uint32_t id, uint32_t account, uint64_t &balance, std::map<uint32_t, uint32_t> &items)

View File

@ -77,7 +77,7 @@ public:
uint32_t get_cc_account();
crypto::public_key get_cc_pkey();
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::map<uint32_t, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk);
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, int32_t &title_adjective, int32_t &title_noun, int32_t &title_origin, int32_t &title_unique, std::string &title, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk);
bool get_cc_account_reserve(uint32_t id, uint32_t account, uint64_t &balance, std::map<uint32_t, uint32_t> &items);
bool get_cc_custom_item_data(uint32_t id, std::string &name);
bool get_cc_custom_item_data(uint32_t id, uint64_t &creation_height, uint32_t &creator, uint64_t &amount, std::string &name, bool &is_group, bool &is_public, uint32_t &group, std::string &primary_description, std::string &secondary_description, bool &ignore, uint64_t &gold, std::vector<uint64_t> &user_data, crypto::hash &hash, bool &can_create_more, uint32_t &prestige_bonus, std::vector<uint32_t> &role_bonus);
@ -145,6 +145,7 @@ public:
void add_cc_vista(const std::string &vista, const std::string &label, const std::string &picture);
void delete_cc_vista(const std::string &vista);
const std::vector<std::tuple<std::string, std::string, std::string>> &get_cc_vistas();
bool get_cc_available_title_components(uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques);
const std::vector<cc::cc_message_t> get_cc_messages();
size_t get_num_unread_cc_messages();

View File

@ -587,6 +587,7 @@ public:
void HandlePlaceModel(StringHash eventType, VariantMap& eventData);
void HandleBlockBatchStart(StringHash eventType, VariantMap& eventData);
void HandleBlockBatchStop(StringHash eventType, VariantMap& eventData);
void HandleChangeTitle(StringHash eventType, VariantMap& eventData);
void SetCameraType(TBID type);
void MoveCamera(float timeStep);
@ -1752,6 +1753,7 @@ void CryptoCityUrho3D::SetupUI()
SubscribeToEvent(ui, E_CRYPTOCITY_MESSAGES_READ, URHO3D_HANDLER(CryptoCityUrho3D, HandleMessagesRead));
SubscribeToEvent(ui, E_CRYPTOCITY_GET_ONLINE_PLAYERS, URHO3D_HANDLER(CryptoCityUrho3D, HandleGetOnlinePlayers));
SubscribeToEvent(ui, E_CRYPTOCITY_START_NEW_EPOCH, URHO3D_HANDLER(CryptoCityUrho3D, HandleStartNewEpoch));
SubscribeToEvent(ui, E_CRYPTOCITY_CHANGE_TITLE, URHO3D_HANDLER(CryptoCityUrho3D, HandleChangeTitle));
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_SCRIPT_DATA, URHO3D_HANDLER(CryptoCityUrho3D, HandleRequestScriptData));
@ -2033,7 +2035,7 @@ void CryptoCityUrho3D::UpdateTargetting()
CloseBuildingTooltip();
std::string text =
game_util::get_building_name(&gameState, hover_flag) + "\n" +
gameState.get_player_name(hover_flag->owner) + "\n" +
gameState.get_player_name(hover_flag->owner, true) + "\n" +
cc::get_role_name(hover_flag->role);
const auto it = flags_for_sale.find(hover_flag->id);
if (it != flags_for_sale.end())
@ -2288,7 +2290,7 @@ void CryptoCityUrho3D::UpdateTargetting()
const Controls::Input input = Controls::Get().Get(Controls::ACTION_OBSERVE);
if (gameState.ignore_player(whisperer))
message = "...";
std::string msg = "Whisper from " + gameState.get_player_name(whisperer) + ":\n\n" + message;
std::string msg = "Whisper from " + gameState.get_player_name(whisperer, true) + ":\n\n" + message;
if (input != Controls::INPUT_NONE)
msg += "\n\nPress " + std::string(Controls::Get().GetInputName(input)) + " to observe";
whisper_tooltip->SetText(msg.c_str());
@ -3895,7 +3897,7 @@ void CryptoCityUrho3D::HandleMessageReceived(StringHash eventType, VariantMap& e
const uint32_t sender = message->sender;
if (gameState.ignore_player(sender))
return;
const std::string player_name = gameState.get_player_name(message->sender);
const std::string player_name = gameState.get_player_name(message->sender, true);
const std::string msg = "Mew message from " + player_name + ":\n" + message->subject;
ui->AddToastNotification(msg.c_str());
}
@ -4282,6 +4284,21 @@ void CryptoCityUrho3D::HandleStartNewEpoch(StringHash eventType, VariantMap& eve
ui->AddToastNotification(("Starting epoch '" + cmd.name + "'").c_str());
}
void CryptoCityUrho3D::HandleChangeTitle(StringHash eventType, VariantMap& eventData)
{
UnsetFocus();
cryptonote::cc_command_set_title_t cmd;
cmd.cc_account = wallet->get_cc_account();
cmd.delta_adjective = eventData[ChangeTitle::P_ADJECTIVE].GetInt() - gameState.playerState.title_adjective;
cmd.delta_noun = eventData[ChangeTitle::P_NOUN].GetInt() - gameState.playerState.title_noun;
cmd.delta_origin = eventData[ChangeTitle::P_ORIGIN].GetInt() - gameState.playerState.title_origin;
cmd.delta_unique = eventData[ChangeTitle::P_UNIQUE].GetInt() - gameState.playerState.title_unique;
if (SendCommand(cmd))
ui->AddToastNotification("Changing title");
}
void CryptoCityUrho3D::HandlePlaceModel(StringHash eventType, VariantMap& eventData)
{
UnsetFocus();
@ -9272,7 +9289,7 @@ void CryptoCityUrho3D::NotifyGameUpdate(const cryptonote::block *b)
uint32_t player_id = std::get<0>(e.bids.back());
std::string price = game_util::print_money(std::get<1>(e.bids.back()));
game_util::reduce_amount_zeroes(price);
msg = gameState.get_player_name(player_id) + " won the " + e.title + " auction for " + price;
msg = gameState.get_player_name(player_id, true) + " won the " + e.title + " auction for " + price;
}
if (!msg.empty())
ui->AddToastNotification(msg.c_str(), "images/auction-hammer.png");
@ -10567,7 +10584,7 @@ void CryptoCityUrho3D::HandleRequestPlayerData(StringHash eventType, VariantMap&
id = wallet->lookup_account(pkey.CString());
}
std::string name, description;
std::string name, description, title;
std::string public_key, pmspk, pmvpk;
uint64_t balance;
std::map<uint32_t, uint32_t> item_balances;
@ -10584,13 +10601,15 @@ void CryptoCityUrho3D::HandleRequestPlayerData(StringHash eventType, VariantMap&
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
uint32_t prestige;
std::vector<uint32_t> textures_created, textures_licenced;
if (wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
int32_t title_adjective, title_noun, title_origin, title_unique;
if (wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
{
gameState.set_player_name(id, name, ignore, public_key == epee::string_tools::pod_to_hex(crypto::null_pkey));
gameState.set_player_name(id, name, title, ignore, public_key == epee::string_tools::pod_to_hex(crypto::null_pkey));
eventData[RequestPlayerData::P_ACCOUNT] = id;
eventData[RequestPlayerData::P_PUBLIC_KEY] = public_key.c_str();
eventData[RequestPlayerData::P_NAME] = gameState.get_player_name(id).c_str();
eventData[RequestPlayerData::P_TITLE] = title.c_str();
eventData[RequestPlayerData::P_DESCRIPTION] = description.c_str();
eventData[RequestPlayerData::P_BALANCE] = (unsigned long long)balance;
eventData[RequestPlayerData::P_PRESTIGE] = prestige;
@ -10980,7 +10999,7 @@ void CryptoCityUrho3D::HandleEventBadge(StringHash eventType, VariantMap& eventD
const std::vector<std::pair<uint32_t, uint8_t>> *v = (const std::vector<std::pair<uint32_t, uint8_t>>*)eventData[EventBadge::P_INSTANCES].GetVoidPtr();
for (const auto &e: *v)
{
std::string name, description;
std::string name, description, title;
std::string public_key, pmspk, pmvpk;
uint64_t balance;
std::map<uint32_t, uint32_t> item_balances;
@ -10997,7 +11016,8 @@ void CryptoCityUrho3D::HandleEventBadge(StringHash eventType, VariantMap& eventD
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
uint32_t prestige;
std::vector<uint32_t> textures_created, textures_licenced;
if (!wallet->get_cc_account_data(e.first, public_key, balance, item_balances, flags, badges, attributes, name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
int32_t title_adjective, title_noun, title_origin, title_unique;
if (!wallet->get_cc_account_data(e.first, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
{
new MessageBox(context_, "Failed to get account data for recipient");
return;

View File

@ -45,7 +45,7 @@ void RemoteAvatars::Add(uint32_t id, const Urho3D::Vector3 &pos, const Urho3D::V
if (i == data.end())
{
std::shared_ptr<Avatar> avatar(new Avatar(shared_model_name, node, collidable_root));
avatar->SetName(game->get_player_name(id));
avatar->SetName(game->get_player_name(id, true));
i = data.insert(std::make_pair(id, data_t{Urho3D::Vector3::ZERO, Urho3D::Vector3::ZERO, Urho3D::Vector3::ZERO, avatar})).first;
}
i->second.pos = pos;

258
src/game/ui-change-title.cc Normal file
View File

@ -0,0 +1,258 @@
#include <memory>
#include <Urho3D/Core/Context.h>
#include <Urho3D/UI/UI.h>
#include <Urho3D/UI/UIEvents.h>
#include <tb/tb_select.h>
#include <tb/tb_toggle_container.h>
#include <tb/tb_widgets_reader.h>
#include <tb/tb_font_renderer.h>
#include "cc/cc_title.h"
#include "game-wallet.h"
#include "game-state.h"
#include "ui-tb-message-box.h"
#include "caching-source-builder.h"
#include "ui-change-title.h"
using namespace Urho3D;
using namespace tb;
static std::string find_string(const std::vector<std::pair<uint32_t, std::string>> &list, int32_t id)
{
if (id < 0)
return "";
for (const auto &e: list)
if ((uint32_t)id == e.first)
return e.second;
return "";
}
UIChangeTitleDialog::UIChangeTitleDialog(Context *ctx, const GameState *game):
UITBWindow(ctx, "cc/change-title.tb.txt"),
game(game)
{
currentTitleWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("current-title"));
newTitleWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("new-title"));
adjectivesWidget = GetWidgetByIDAndType<TBSelectDropdown>(TBIDC("adjectives"));
nounsWidget = GetWidgetByIDAndType<TBSelectDropdown>(TBIDC("nouns"));
originsWidget = GetWidgetByIDAndType<TBSelectDropdown>(TBIDC("origins"));
uniquesWidget = GetWidgetByIDAndType<TBSelectDropdown>(TBIDC("uniques"));
compoundContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("toggle-style-compound"));
uniqueContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("toggle-style-unique"));
adjectivesWidget->SetSource(&adjectives_source);
nounsWidget->SetSource(&nouns_source);
originsWidget->SetSource(&origins_source);
uniquesWidget->SetSource(&uniques_source);
ResizeToFitContent(RESIZE_FIT_PREFERRED);
SubscribeToEvent(this, E_TB_WIDGET_EVENT, URHO3D_HANDLER(UIChangeTitleDialog, HandleTBMessage));
SubscribeToEvent(this, E_TB_WINDOW_CLOSED, URHO3D_HANDLER(UIChangeTitleDialog, HandleClose));
}
UIChangeTitleDialog::~UIChangeTitleDialog()
{
adjectivesWidget->SetSource(NULL);
nounsWidget->SetSource(NULL);
originsWidget->SetSource(NULL);
uniquesWidget->SetSource(NULL);
}
void UIChangeTitleDialog::UpdateLists(const std::shared_ptr<GameWallet> &w)
{
if (!w->get_cc_available_title_components(game->playerState.id, adjectives, nouns, origins, uniques))
return;
const bool has_compound = game->playerState.title_adjective >= 0 || game->playerState.title_noun >= 0 || game->playerState.title_origin >= 0;
const bool has_unique = game->playerState.title_unique >= 0;
if (has_compound && has_unique)
new MessageBox(context_, "Inconsistent title, recovering");
if (has_unique)
style = style_unique;
else
style = style_compound;
struct
{
const int32_t &current;
TBSelectDropdown *widget;
TBGenericStringItemSource &source;
const std::vector<std::pair<uint32_t, std::string>> &list;
} data[4] =
{
{ game->playerState.title_adjective, adjectivesWidget, adjectives_source, adjectives },
{ game->playerState.title_noun, nounsWidget, nouns_source, nouns },
{ game->playerState.title_origin, originsWidget, origins_source, origins },
{ game->playerState.title_unique, uniquesWidget, uniques_source, uniques },
};
for (int i = 0; i < 4; ++i)
{
int32_t select_item = data[i].current;
int sel = data[i].widget->GetValue();
if (sel >= 0 && sel < data[i].source.GetNumItems())
{
const tb::TBGenericStringItem *item = data[i].source.GetItem(sel);
select_item = item->tag.GetInt();
}
sel = -1;
{
CachingSourceBuilder<TBGenericStringItem> builder(data[i].source);
TBGenericStringItem *item = new TBGenericStringItem("");
item->tag.SetInt(-1);
if (select_item == -1)
sel = 0;
builder.AddItem(item);
for (const auto &e: data[i].list)
{
TBGenericStringItem *item = new TBGenericStringItem(e.second.c_str());
item->tag.SetInt(e.first);
if (e.first == (uint32_t)select_item)
sel = builder.GetNumItems();
builder.AddItem(item);
}
}
if (sel >= 0)
data[i].widget->SetValue(sel);
}
}
void UIChangeTitleDialog::Update(const std::shared_ptr<GameWallet> &w)
{
if (game->top_hash != last_refresh_stop_hash)
{
UpdateLists(w);
const std::string adjective = find_string(adjectives, game->playerState.title_adjective);
const std::string noun = find_string(nouns, game->playerState.title_noun);
const std::string origin = find_string(origins, game->playerState.title_origin);
const std::string unique = find_string(uniques, game->playerState.title_unique);
const std::string title = cc::get_title(adjective, noun, origin, unique);
const std::string name_and_title = game->get_player_name(game->playerState.id) + (title.empty() ? "" : (" " + title));
currentTitleWidget->SetText(name_and_title.c_str());
compoundContainer->SetValue(style == style_compound);
uniqueContainer->SetValue(style == style_unique);
ResizeToFitContent(RESIZE_FIT_CURRENT_OR_NEEDED);
last_refresh_stop_hash = game->top_hash;
}
}
void UIChangeTitleDialog::HandleSetTitleStyle(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData)
{
TBWidgetEvent *ev = (TBWidgetEvent*)eventData[TBWidgetEventNamespace::P_WIDGET_EVENT].GetVoidPtr();
if (!ev->target->GetValue())
return;
if (ev->target->data.GetInt())
{
// compound
style = style_unique;
}
else
{
// unique
style = style_compound;
}
compoundContainer->SetValue(style == style_compound);
uniqueContainer->SetValue(style == style_unique);
UpdateNewTitle();
}
void UIChangeTitleDialog::HandleTitleChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData)
{
UpdateNewTitle();
}
void UIChangeTitleDialog::UpdateNewTitle()
{
std::string title;
if (style == style_compound)
{
const std::string adjective = adjectivesWidget->GetValue() >= 0 ? adjectives_source.GetItem(adjectivesWidget->GetValue())->str.CStr() : "";
const std::string noun = nounsWidget->GetValue() >= 0 ? nouns_source.GetItem(nounsWidget->GetValue())->str.CStr() : "";
const std::string origin = originsWidget->GetValue() >= 0 ? origins_source.GetItem(originsWidget->GetValue())->str.CStr() : "";
title = cc::get_title(adjective, noun, origin, "");
}
else
{
const std::string unique = uniquesWidget->GetValue() >= 0 ? uniques_source.GetItem(uniquesWidget->GetValue())->str.CStr() : "";
title = cc::get_title("", "", "", unique);
}
const std::string name_and_title = game->get_player_name(game->playerState.id) + (title.empty() ? "" : (" " + title));;
newTitleWidget->SetText(name_and_title.c_str());
ResizeToFitContent(RESIZE_FIT_CURRENT_OR_NEEDED);
}
void UIChangeTitleDialog::HandleCancel(StringHash eventType, VariantMap& eventData)
{
VariantMap& newEventData = GetEventDataMap();
SendEvent(E_CHANGE_TITLE_CANCELLED, newEventData);
// Self destruct
Close();
}
void UIChangeTitleDialog::HandleOK(StringHash eventType, VariantMap& eventData)
{
const int32_t adjective = adjectivesWidget->GetValue() >= 0 ? adjectives_source.GetItem(adjectivesWidget->GetValue())->tag.GetInt() : -1;
const int32_t noun = nounsWidget->GetValue() >= 0 ? nouns_source.GetItem(nounsWidget->GetValue())->tag.GetInt() : -1;
const int32_t origin = originsWidget->GetValue() >= 0 ? origins_source.GetItem(originsWidget->GetValue())->tag.GetInt() : -1;
const int32_t unique = uniquesWidget->GetValue() >= 0 ? uniques_source.GetItem(uniquesWidget->GetValue())->tag.GetInt() : -1;
VariantMap& newEventData = GetEventDataMap();
newEventData[ChangeTitleOkayed::P_ADJECTIVE] = adjective;
newEventData[ChangeTitleOkayed::P_NOUN] = noun;
newEventData[ChangeTitleOkayed::P_ORIGIN] = origin;
newEventData[ChangeTitleOkayed::P_UNIQUE] = unique;
SendEvent(E_CHANGE_TITLE_OKAYED, newEventData);
// Self destruct
Close();
}
void UIChangeTitleDialog::CancelUI()
{
VariantMap& newEventData = GetEventDataMap();
SendEvent(E_CHANGE_TITLE_CANCELLED, newEventData);
// Self destruct
Close();
}
void UIChangeTitleDialog::HandleTBMessage(StringHash eventType, VariantMap& eventData)
{
#define CONNECT(name, function) do { if (ev->target->GetID() == TBIDC(name)) function(eventType, eventData); } while(0)
using namespace TBWidgetEventNamespace;
TBWidgetEvent *ev = (TBWidgetEvent*)eventData[P_WIDGET_EVENT].GetVoidPtr();
if (ev->type == EVENT_TYPE_CLICK)
{
CONNECT("ok", HandleOK);
CONNECT("cancel", HandleCancel);
}
else if (ev->type == EVENT_TYPE_CHANGED)
{
CONNECT("adjectives", HandleTitleChanged);
CONNECT("nouns", HandleTitleChanged);
CONNECT("origins", HandleTitleChanged);
CONNECT("uniques", HandleTitleChanged);
CONNECT("style-compound", HandleSetTitleStyle);
CONNECT("style-unique", HandleSetTitleStyle);
}
#undef CONNECT
}
void UIChangeTitleDialog::HandleClose(StringHash eventType, VariantMap& eventData)
{
VariantMap& newEventData = GetEventDataMap();
SendEvent(E_CHANGE_TITLE_CANCELLED, newEventData);
// Self destruct
Close();
}

View File

@ -0,0 +1,84 @@
#ifndef UI_CHANGE_TITLE_H
#define UI_CHANGE_TITLE_H
#include <Urho3D/Core/Object.h>
#include <Urho3D/Container/Str.h>
#include <Urho3D/Container/Ptr.h>
#include <Urho3D/Math/StringHash.h>
#include <tb/tb_select_item.h>
#include "ui-tb-window.h"
namespace Urho3D
{
class Context;
}
namespace tb
{
class TBSelectDropdown;
class TBToggleContainer;
class TBLayout;
class TBTextField;
}
class GameWallet;
class GameState;
URHO3D_EVENT(E_CHANGE_TITLE_OKAYED, ChangeTitleOkayed) { URHO3D_PARAM(P_ADJECTIVE, Adjective); URHO3D_PARAM(P_NOUN, Noun); URHO3D_PARAM(P_ORIGIN, Origin); URHO3D_PARAM(P_UNIQUE, Unique); }
URHO3D_EVENT(E_CHANGE_TITLE_CANCELLED, ChangeTitleCancelled) {}
class UIChangeTitleDialog: public UITBWindow
{
public:
UIChangeTitleDialog(Urho3D::Context *ctx, const GameState *game = NULL);
virtual ~UIChangeTitleDialog() override;
void Update(const std::shared_ptr<GameWallet> &w);
void CancelUI();
private:
enum style_t
{
style_compound,
style_unique
};
private:
void HandleSetTitleStyle(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleTitleChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleOK(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleCancel(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleTBMessage(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleClose(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void UpdateLists(const std::shared_ptr<GameWallet> &w);
void UpdateNewTitle();
private:
const GameState *game;
style_t style;
std::vector<std::pair<uint32_t, std::string>> adjectives, nouns, origins, uniques;
tb::TBTextField *currentTitleWidget;
tb::TBTextField *newTitleWidget;
tb::TBGenericStringItemSource adjectives_source;
tb::TBSelectDropdown *adjectivesWidget;
tb::TBGenericStringItemSource nouns_source;
tb::TBSelectDropdown *nounsWidget;
tb::TBGenericStringItemSource origins_source;
tb::TBSelectDropdown *originsWidget;
tb::TBGenericStringItemSource uniques_source;
tb::TBSelectDropdown *uniquesWidget;
tb::TBToggleContainer *compoundContainer;
tb::TBToggleContainer *uniqueContainer;
std::string last_refresh_stop_hash;
};
#endif

View File

@ -188,7 +188,7 @@ void UICityLevelDialog::Update()
std::string mayor = "unknown";
for (const auto &e: game->cities)
if (e.city_id == game->cityState.id)
mayor = game->get_player_name(e.mayor);
mayor = game->get_player_name(e.mayor, true);
cityMayorWidget->SetText(mayor.c_str());
cityLevelNameWidget->SetText(level_name);
cityLevelWidget->SetText(std::to_string(level).c_str());

View File

@ -35,7 +35,7 @@ UIItemsDialog::OwnershipWidget::OwnershipWidget(UIItemsDialog::OwnershipItem *it
g_widgets_reader->LoadFile(GetContentRoot(), "cc/player-info-ownership-row.tb.txt");
TBTextField *name = GetWidgetByIDAndType<TBTextField>(TBIDC("name"));
name->SetText(item->game->get_player_name(item->account).c_str());
name->SetText(item->game->get_player_name(item->account, true).c_str());
TBTextField *amount = GetWidgetByIDAndType<TBTextField>(TBIDC("amount"));
amount->SetText(std::to_string(item->amount).c_str());
}

View File

@ -36,7 +36,7 @@ UIMessagesDialog::MessageWidget::MessageWidget(UIMessagesDialog::MessageItem *it
const cc::cc_message_t &message = item->message;
TBTextField *tf = GetWidgetByIDAndType<TBTextField>(TBIDC("from"));
tf->SetText(message.sender == 0 ? "<unknown>" : item->dialog->game->get_player_name(message.sender).c_str());
tf->SetText(message.sender == 0 ? "<unknown>" : item->dialog->game->get_player_name(message.sender, true).c_str());
tf = GetWidgetByIDAndType<TBTextField>(TBIDC("subject"));
std::string subject = (message.reply ? "Re: " : "") + message.subject;
@ -88,7 +88,7 @@ bool UIMessagesDialog::MessageSource::Filter(int index, const TBStr &filter)
return true;
if (stristr(message.message.c_str(), filter.CStr()))
return true;
if (message.sender && stristr(item->dialog->game->get_player_name(message.sender).c_str(), filter.CStr()))
if (message.sender && stristr(item->dialog->game->get_player_name(message.sender, true).c_str(), filter.CStr()))
return true;
return false;

View File

@ -71,7 +71,7 @@ void UINewAccountDialog::FillData(const GameState *game)
if (is_treasury)
continue;
const std::string player_name = game->get_player_name(e.first);
const std::string player_name = game->get_player_name(e.first, true);
TBGenericStringItem *item = new TBGenericStringItem(player_name);
item->tag.SetInt(e.first);
builder.AddItem(item);

View File

@ -106,7 +106,7 @@ void UINewMessageDialog::UpdateRequirements()
void UINewMessageDialog::HandleSelectRecipient(StringHash eventType, VariantMap& eventData)
{
selectAccountDialog = new UISelectAccountDialog(context_, game, [this](uint32_t id, const std::string &name, bool ignore, bool autonomous) {
selectAccountDialog = new UISelectAccountDialog(context_, game, false, [this](uint32_t id, const std::string &name, bool ignore, bool autonomous) {
if (id == GAME_ACCOUNT)
return false;
if (id == game->playerState.id)
@ -203,8 +203,8 @@ void UINewMessageDialog::HandleSend(StringHash eventType, VariantMap& eventData)
for (const auto &e: game->player_names)
{
const uint32_t id = e.first;
const bool ignore = std::get<1>(e.second);
const bool autonomous = std::get<2>(e.second);
const bool ignore = std::get<2>(e.second);
const bool autonomous = std::get<3>(e.second);
if (id == GAME_ACCOUNT || id == game->playerState.id || ignore || autonomous)
continue;

View File

@ -27,6 +27,7 @@
#include "cc/cc_discoveries.h"
#include "cc/cc_collectible_coin.h"
#include "cc/cc_calendar.h"
#include "cc/cc_title.h"
#include "wallet/wallet2.h"
#include "game/game-state.h"
#include "game/game-wallet.h"
@ -47,6 +48,7 @@
#include "ui-mint.h"
#include "ui-smelt.h"
#include "ui-new-message.h"
#include "ui-change-title.h"
#include "ui-tb-message-box.h"
#include "caching-source-builder.h"
#include "coin-icon.h"
@ -215,6 +217,7 @@ static std::string get_extra_command_info(const cryptonote::cc_command_t &cmd)
std::string operator()(const cryptonote::cc_command_service_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_set_title_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_smelt_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_sow_t &cmd) const { return ""; }
@ -1294,7 +1297,7 @@ UIPlayerInfoDialog::OwnershipWidget::OwnershipWidget(UIPlayerInfoDialog::Ownersh
g_widgets_reader->LoadFile(GetContentRoot(), "cc/player-info-ownership-row.tb.txt");
TBTextField *name = GetWidgetByIDAndType<TBTextField>(TBIDC("name"));
name->SetText(item->game->get_player_name(item->account).c_str());
name->SetText(item->game->get_player_name(item->account, true).c_str());
TBTextField *amount = GetWidgetByIDAndType<TBTextField>(TBIDC("amount"));
amount->SetText(std::to_string(item->amount).c_str());
}
@ -1454,6 +1457,7 @@ UIPlayerInfoDialog::UIPlayerInfoDialog(Context *ctx, const GameState *game, uint
mintDialog(nullptr),
smeltDialog(nullptr),
selectItemsDialog(nullptr),
changeTitleDialog(nullptr),
tooltip(nullptr),
tooltip_target(nullptr),
level(0),
@ -1471,6 +1475,7 @@ UIPlayerInfoDialog::UIPlayerInfoDialog(Context *ctx, const GameState *game, uint
{
tabContainerWidget = GetWidgetByIDAndType<TBTabContainer>(TBIDC("tab-container"));
balanceWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("balance"));
titleWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("title"));
nameWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("name"));
levelWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("level"));
mainPrestigeWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("prestige-main"));
@ -1592,6 +1597,10 @@ UIPlayerInfoDialog::UIPlayerInfoDialog(Context *ctx, const GameState *game, uint
ownershipContainer->SetValue(0);
viewOwnershipContainer->SetValue(0);
tb::TBFontDescription fd = g_font_manager->GetDefaultFontDescription();
fd.SetSize(fd.GetSize() * 2);
titleWidget->SetFontDescription(fd);
const TBRect rect = rareFishList->GetParent()->GetRect();
const int w = rect.w * 30 / 100;
LayoutParams lp;
@ -1688,7 +1697,7 @@ void UIPlayerInfoDialog::UpdateRareFishData(const std::shared_ptr<GameWallet> &w
void UIPlayerInfoDialog::FillData(const std::shared_ptr<GameWallet> &w, uint32_t player_id)
{
std::string description, pmspk, pmvpk;
std::string description, pmspk, pmvpk, player_title;
std::vector<uint32_t> flags;
std::map<uint32_t, std::pair<uint8_t, uint64_t>> badges;
std::map<uint32_t, uint32_t> attributes;
@ -1699,7 +1708,8 @@ void UIPlayerInfoDialog::FillData(const std::shared_ptr<GameWallet> &w, uint32_t
item_balances.clear();
std::vector<uint32_t> textures_created, textures_licenced;
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
if (!w->get_cc_account_data(player_id, public_key, balance, item_balances, flags, badges, attributes, player_name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
int32_t title_adjective, title_noun, title_origin, title_unique;
if (!w->get_cc_account_data(player_id, public_key, balance, item_balances, flags, badges, attributes, player_name, title_adjective, title_noun, title_origin, title_unique, player_title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk))
return;
CancelTooltip();
@ -1724,6 +1734,10 @@ void UIPlayerInfoDialog::FillData(const std::shared_ptr<GameWallet> &w, uint32_t
for (int i = 1; i <= 5; ++i)
numBadgesWidget[i - 1]->SetText(std::to_string(badge_count[i - 1]).c_str());
std::string name_and_title = player_name;
if (!player_title.empty())
name_and_title += " " + player_title;
titleWidget->SetText(name_and_title.c_str());
nameWidget->SetText(player_name.c_str());
if (!game->ignore_player(player_id))
playerProfileWidget->SetText(description.c_str());
@ -2656,6 +2670,8 @@ void UIPlayerInfoDialog::Update(const std::shared_ptr<GameWallet> &w)
savePlayerProfileWidget->SetState(WIDGET_STATE_DISABLED, true);
savePlayerProfileWidget->SetVisibility(can_edit ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
}
titleWidget->SetSkinBg(game->playerState.id == player_id ? TBIDC("title-link") : TBIDC("TBTextField"));
titleWidget->SetUnderline(game->playerState.id == player_id);
last_refresh_stop_hash = game->top_hash;
}
@ -2671,6 +2687,8 @@ void UIPlayerInfoDialog::Update(const std::shared_ptr<GameWallet> &w)
smeltDialog->Update(w);
if (selectItemsDialog)
selectItemsDialog->Update(w);
if (changeTitleDialog)
changeTitleDialog->Update(w);
giveGoldWidget->SetVisibility(game->playerState.id == player_id ? WIDGET_VISIBILITY_INVISIBLE : WIDGET_VISIBILITY_VISIBLE);
giveItemsWidget->SetVisibility(game->playerState.id == player_id ? WIDGET_VISIBILITY_INVISIBLE : WIDGET_VISIBILITY_VISIBLE);
@ -3313,7 +3331,7 @@ void UIPlayerInfoDialog::HandleRareFishChanged(StringHash eventType, VariantMap&
imageWidget->SetLayoutParams(lp);
imageWidget->SetVisibility(WIDGET_VISIBILITY_VISIBLE);
const std::string discoverer_name = game->get_player_name(rare_fish_data[item->fish].first);
const std::string discoverer_name = game->get_player_name(rare_fish_data[item->fish].first, true);
std::string s = std::string("The ") + rfd->name + " was discovered by " + discoverer_name;
std::vector<std::string> waters;
if (rfd->close_waters)
@ -3350,6 +3368,21 @@ void UIPlayerInfoDialog::HandleCurrentCityOnlyChanged(StringHash eventType, Vari
last_refresh_stop_hash = "";
}
void UIPlayerInfoDialog::HandleChangeTitle(StringHash eventType, VariantMap& eventData)
{
if (player_id != game->playerState.id)
return;
if (changeTitleDialog)
{
new MessageBox(context_, "Dialog is already active");
return;
}
changeTitleDialog = new UIChangeTitleDialog(context_, game);
SubscribeToEvent(changeTitleDialog, E_CHANGE_TITLE_OKAYED, [this](StringHash eventType, VariantMap &eventData){ SendEvent(eventType, eventData); changeTitleDialog = NULL; });
SubscribeToEvent(changeTitleDialog, E_CHANGE_TITLE_CANCELLED, [this](StringHash eventType, VariantMap &eventData){ changeTitleDialog = NULL; });
}
void UIPlayerInfoDialog::HandleTBMessage(StringHash eventType, VariantMap& eventData)
{
#define CONNECT(name, function) do { if (target.Get() && target.Get()->GetID() == TBIDC(name)) function(eventType, eventData); } while(0)
@ -3378,6 +3411,7 @@ void UIPlayerInfoDialog::HandleTBMessage(StringHash eventType, VariantMap& event
CONNECT("export-history", HandleExportHistory);
CONNECT("view-owners", HandleViewOwners);
CONNECT("view-history-details", HandleViewHistoryDetails);
CONNECT("title", HandleChangeTitle);
HeaderButton *hb = target.Get() ? TBSafeCast<HeaderButton>(target.Get()) : NULL;
if (hb)

View File

@ -44,6 +44,7 @@ class BadgeWidget;
class UITradeDialog;
class UIMintDialog;
class UISmeltDialog;
class UIChangeTitleDialog;
URHO3D_EVENT(E_PLAYER_INFO_CLOSED, PlayerInfoClosed) {}
URHO3D_EVENT(E_PLAYER_INFO_FLAG_SELECTED, PlayerInfoFlagSelected) { URHO3D_PARAM(P_FLAG, Flag); }
@ -111,6 +112,7 @@ private:
void HandleViewHistoryDetails(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleRareFishChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleCurrentCityOnlyChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleChangeTitle(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void InitColumnsList();
void HideRareFishInfo();
@ -420,6 +422,7 @@ private:
const GameState *game;
tb::TBTabContainer *tabContainerWidget;
tb::TBTextField *balanceWidget;
tb::TBTextField *titleWidget;
tb::TBTextField *nameWidget;
tb::TBTextField *levelWidget;
tb::TBTextField *mainPrestigeWidget;
@ -451,6 +454,7 @@ private:
tb::TBToggleContainer *ownershipContainer;
tb::TBToggleContainer *viewOwnershipContainer;
tb::TBSelectList *ownershipWidget;
tb::TBButton *changeTitleButton;
uint32_t player_id;
std::string last_refresh_stop_hash;
@ -470,6 +474,7 @@ private:
UIMintDialog *mintDialog;
UISmeltDialog *smeltDialog;
UISelectItemsDialog *selectItemsDialog;
UIChangeTitleDialog *changeTitleDialog;
UITooltip *tooltip;
TooltipWidget *tooltip_target;

View File

@ -65,7 +65,7 @@ UIResearchDialog::DiscoveryWidget::DiscoveryWidget(UIResearchDialog::DiscoveryIt
if (boost::ends_with(years, ".0"))
years[strlen(years) - 2] = 0;
const std::string days = std::to_string(discovery_age / (86400 / DIFFICULTY_TARGET_V2));
status = "Discovered " + std::string(years) + " in-game years (" + days + " days) ago by " + item->dialog->game->get_player_name(d.discoverer);
status = "Discovered " + std::string(years) + " in-game years (" + days + " days) ago by " + item->dialog->game->get_player_name(d.discoverer, true);
color = TBColor(128, 230, 204, 255);
}
break;

View File

@ -15,14 +15,14 @@
using namespace Urho3D;
using namespace tb;
UISelectAccountDialog::UISelectAccountDialog(Context *ctx, const GameState *game, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter):
UISelectAccountDialog::UISelectAccountDialog(Context *ctx, const GameState *game, bool with_title, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter):
UITBWindow(ctx, "cc/select-account.tb.txt")
{
accountsWidget = GetWidgetByIDAndType<TBSelectList>(TBIDC("accounts"));
filterWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("filter"));
accountsWidget->SetSource(&account_source);
FillData(game, filter);
FillData(game, with_title, filter);
SubscribeToEvent(this, E_TB_WIDGET_EVENT, URHO3D_HANDLER(UISelectAccountDialog, HandleTBMessage));
SubscribeToEvent(this, E_TB_WINDOW_CLOSED, URHO3D_HANDLER(UISelectAccountDialog, HandleClose));
@ -37,13 +37,13 @@ void UISelectAccountDialog::Update(const GameState *gameState)
{
}
void UISelectAccountDialog::FillData(const GameState *game, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter)
void UISelectAccountDialog::FillData(const GameState *game, bool with_title, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter)
{
CachingSourceBuilder<TBGenericStringItem> builder(account_source);
for (const auto &e: game->player_names)
{
const std::string player_name = game->get_player_name(e.first);
const std::string player_name = game->get_player_name(e.first, with_title);
if (filter && !filter(e.first, player_name, game->ignore_player(e.first), game->is_autonomous_player(e.first)))
continue;
TBGenericStringItem *item = new TBGenericStringItem(player_name);

View File

@ -27,7 +27,7 @@ URHO3D_EVENT(E_SELECT_ACCOUNT_CANCELLED, SelectAccountCancelled) {}
class UISelectAccountDialog: public UITBWindow
{
public:
UISelectAccountDialog(Urho3D::Context *ctx, const GameState *game, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter = NULL);
UISelectAccountDialog(Urho3D::Context *ctx, const GameState *game, bool with_title = true, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter = NULL);
virtual ~UISelectAccountDialog() override;
void Update(const GameState *gameState);
@ -40,7 +40,7 @@ private:
void HandleClose(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleFilterChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void FillData(const GameState *game, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter);
void FillData(const GameState *game, bool with_title, const std::function<bool(uint32_t, const std::string&, bool, bool)> &filter);
private:
tb::TBSelectList *accountsWidget;

View File

@ -346,7 +346,7 @@ std::pair<std::string, crypto::hash> UITradeDialog::GetFlagDetails(const std::sh
}
ss << boost::format("%ux%u %s land in %s\n")
% (flag->x1 - flag->x0 + 1) % (flag->y1 - flag->y0 + 1) % cc::get_role_name(flag->role) % game->get_city_name(flag->city);
ss << "Owner: " << game->get_player_name(flag->owner) << "\n";
ss << "Owner: " << game->get_player_name(flag->owner, true) << "\n";
ss << "Repair: " << cc::print_repair_percentage(flag->repair) << "\n";
return std::make_pair(ss.str(), crypto::null_hash);
}
@ -364,7 +364,7 @@ std::pair<std::string, crypto::hash> UITradeDialog::GetCityDetails(const std::sh
{
if (e.city_id == id)
{
ss << "Mayor: " << game->get_player_name(e.mayor) << "\n";
ss << "Mayor: " << game->get_player_name(e.mayor, true) << "\n";
ss << "Treasury: " << game_util::print_money(e.treasury_balance) << "\n";
ss << "Level: " << cc::get_town_level_name(e.level);
found = true;

View File

@ -41,7 +41,7 @@ UITravelToCityDialog::CityWidget::CityWidget(CityItem *item, CitySource *source,
levelWidget->SetText(cc::get_town_level_name(item->city.level));
TBTextField *mayorWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("mayor"));
mayorWidget->SetText(item->dialog->game->get_player_name(item->city.mayor));
mayorWidget->SetText(item->dialog->game->get_player_name(item->city.mayor, true));
std::vector<std::string> special_event_names;
for (uint32_t special_event: item->city.special_events)

View File

@ -113,6 +113,7 @@
#include "ui-messages.h"
#include "ui-encyclopedia.h"
#include "ui-select-account.h"
#include "ui-change-title.h"
#include "ui-urho3d.h"
#define WALLET_BALANCE_TEXT_SCALE .8f
@ -3012,7 +3013,7 @@ void UIUrho3D::HandleShowOnlinePlayers(Urho3D::StringHash eventType, Urho3D::Var
return;
}
showOnlinePlayersDialog = new UISelectAccountDialog(context_, gameState, [this, &players](uint32_t id, const std::string &name, bool ignore, bool autonomous) {
showOnlinePlayersDialog = new UISelectAccountDialog(context_, gameState, true, [this, &players](uint32_t id, const std::string &name, bool ignore, bool autonomous) {
if (autonomous)
return false;
if (id == gameState->playerState.id)
@ -4443,6 +4444,9 @@ void UIUrho3D::ShowPlayerInfo(uint32_t player_id)
SubscribeToEvent(playerInfoDialog, E_CRYPTOCITY_SEND_MESSAGE, [this](StringHash eventType, VariantMap& eventData) {
SendEvent(E_CRYPTOCITY_SEND_MESSAGE, eventData);
});
SubscribeToEvent(playerInfoDialog, E_CHANGE_TITLE_OKAYED, [this](StringHash eventType, VariantMap& eventData) {
SendEvent(E_CRYPTOCITY_CHANGE_TITLE, eventData);
});
if (player_id == 0)
playerInfoDialog->SelectAccount();
SendTutorialTrigger("screen-player-info");

View File

@ -297,6 +297,7 @@ URHO3D_EVENT(E_CRYPTOCITY_RTAS, RTAS) { URHO3D_PARAM(P_ENABLE, Enable); URHO3D_P
URHO3D_EVENT(E_CRYPTOCITY_MESSAGES_READ, MessagesRead) { }
URHO3D_EVENT(E_CRYPTOCITY_GET_ONLINE_PLAYERS, GetOnlinePlayers) { URHO3D_PARAM(P_ENABLED, Enabled); URHO3D_PARAM(P_PLAYERS, Players); }
URHO3D_EVENT(E_CRYPTOCITY_START_NEW_EPOCH, StartNewEpoch) { URHO3D_PARAM(P_NAME, Name); }
URHO3D_EVENT(E_CRYPTOCITY_CHANGE_TITLE, ChangeTitle) { URHO3D_PARAM(P_ADJECTIVE, Adjective); URHO3D_PARAM(P_NOUN, Noun); URHO3D_PARAM(P_ORIGIN, Origin); URHO3D_PARAM(P_UNIQUE, Unique); }
class UIUrho3D: public Urho3D::UIElement
{

View File

@ -81,6 +81,7 @@ using namespace epee;
#include "cc/cc_merchant_ship.h"
#include "cc/cc_city_specialization.h"
#include "cc/cc_epoch.h"
#include "cc/cc_title.h"
#include "version.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
@ -4017,6 +4018,7 @@ namespace cryptonote
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_cc_get_account(const COMMAND_RPC_CC_GET_ACCOUNT::request& req, COMMAND_RPC_CC_GET_ACCOUNT::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
try
{
cryptonote::cc_account_data_t data;
@ -4029,7 +4031,7 @@ namespace cryptonote
error_resp.message = "Invalid hex data";
return false;
}
if (!m_core.get_blockchain_storage().get_db().get_as_cc_account(bd, data))
if (!db.get_as_cc_account(bd, data))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Account could not be parsed";
@ -4038,7 +4040,7 @@ namespace cryptonote
}
else
{
if (!m_core.get_blockchain_storage().get_db().get_cc_account_data(req.id, data))
if (!db.get_cc_account_data(req.id, data))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Account not found";
@ -4047,6 +4049,11 @@ namespace cryptonote
}
res.balance = data.balance;
res.name = std::move(data.name);
res.title_adjective = data.title_adjective;
res.title_noun = data.title_noun;
res.title_origin = data.title_origin;
res.title_unique = data.title_unique;
res.title = std::move(data.title);
res.description = std::move(data.description);
res.ignore = data.ignore;
res.moose_killed = data.moose_killed;
@ -4098,6 +4105,7 @@ namespace cryptonote
}
res.textures_created = std::move(data.textures_created);
res.textures_licenced = std::move(data.textures_licenced);
res.unique_titles = std::move(data.unique_titles);
for (const auto &e: data.reserve)
{
@ -4508,7 +4516,7 @@ namespace cryptonote
weekly_level_increase = new_level - old_level;
}
const bool autonomous = data.public_key == crypto::null_pkey;
snapshot.player_data.push_back({account_id, std::move(data.name), data.ignore, autonomous, std::move(badges), weekly_level_increase, data.prestige, data.balance});
snapshot.player_data.push_back({account_id, std::move(data.name), std::move(data.title), data.ignore, autonomous, std::move(badges), weekly_level_increase, data.prestige, data.balance});
--n_accounts;
}
++account_id;
@ -5226,7 +5234,7 @@ namespace cryptonote
if (req.id.empty())
{
if (!db.for_all_cc_event_badges([&res](const cc::cc_badge_data_t &bd) {
res.badges.push_back({bd.id, bd.name, bd.desc, bd.icon, bd.manual, {}});
res.badges.push_back({bd.id, bd.name, bd.desc, bd.icon, bd.manual, bd.title_adjective, bd.title_noun, {}});
if (bd.thresholds.size() != 0 && bd.thresholds.size() != NUM_BADGE_LEVELS)
return false;
if (!bd.thresholds.empty())
@ -5247,7 +5255,7 @@ namespace cryptonote
cc::cc_badge_data_t data;
if (!cc::get_badge_data(&db, (cc::cc_badge_t)id, data))
return false;
res.badges.push_back({id, std::move(data.name), std::move(data.desc), std::move(data.icon), data.manual, {}});
res.badges.push_back({id, std::move(data.name), std::move(data.desc), std::move(data.icon), data.manual, std::move(data.title_adjective), std::move(data.title_noun), {}});
if (data.thresholds.size() != 0 && data.thresholds.size() != NUM_BADGE_LEVELS)
return false;
if (!data.thresholds.empty())
@ -7050,6 +7058,40 @@ done:
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_cc_get_available_title_components(const COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS::request& req, COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
PERF_TIMER(on_cc_get_available_title_components);
BlockchainDB &db = m_core.get_blockchain_storage().get_db();
try
{
std::vector<std::pair<uint32_t, std::string>> adjectives, nouns, origins, uniques;
cc::get_available_title_components(db, req.account, adjectives, nouns, origins, uniques);
res.adjectives.reserve(adjectives.size());
for (auto &e: adjectives)
res.adjectives.push_back({e.first, e.second});
res.nouns.reserve(nouns.size());
for (auto &e: nouns)
res.nouns.push_back({e.first, e.second});
res.origins.reserve(origins.size());
for (auto &e: origins)
res.origins.push_back({e.first, e.second});
res.uniques.reserve(uniques.size());
for (auto &e: uniques)
res.uniques.push_back({e.first, e.second});
}
catch (const std::exception &e)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Error getting available title components";
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"

View File

@ -257,6 +257,7 @@ namespace cryptonote
MAP_JON_RPC_WE("cc_get_building_cost", on_cc_get_building_cost, COMMAND_RPC_CC_GET_BUILDING_COST)
MAP_JON_RPC_WE("cc_get_item_creation_fee", on_cc_get_item_creation_fee, COMMAND_RPC_CC_GET_ITEM_CREATION_FEE)
MAP_JON_RPC_WE("cc_get_epochs", on_cc_get_epochs, COMMAND_RPC_CC_GET_EPOCHS)
MAP_JON_RPC_WE("cc_get_available_title_components", on_cc_get_available_title_components, COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS)
END_JSON_RPC_MAP()
END_URI_MAP2()
@ -403,6 +404,7 @@ namespace cryptonote
bool on_cc_get_building_cost(const COMMAND_RPC_CC_GET_BUILDING_COST::request& req, COMMAND_RPC_CC_GET_BUILDING_COST::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_cc_get_item_creation_fee(const COMMAND_RPC_CC_GET_ITEM_CREATION_FEE::request& req, COMMAND_RPC_CC_GET_ITEM_CREATION_FEE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_cc_get_epochs(const COMMAND_RPC_CC_GET_EPOCHS::request& req, COMMAND_RPC_CC_GET_EPOCHS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_cc_get_available_title_components(const COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS::request& req, COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
//-----------------------
private:

View File

@ -3092,6 +3092,11 @@ namespace cryptonote
std::vector<badge_t> badges;
std::vector<attribute_t> attributes;
std::string name;
int32_t title_adjective;
int32_t title_noun;
int32_t title_origin;
int32_t title_unique;
std::string title;
std::string description;
bool ignore;
uint32_t moose_killed;
@ -3121,6 +3126,7 @@ namespace cryptonote
std::vector<background_script_state_t> background_script_states;
std::vector<uint32_t> textures_created;
std::vector<uint32_t> textures_licenced;
std::vector<std::string> unique_titles;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
@ -3134,6 +3140,11 @@ namespace cryptonote
KV_SERIALIZE(badges)
KV_SERIALIZE(attributes)
KV_SERIALIZE(name)
KV_SERIALIZE(title_adjective)
KV_SERIALIZE(title_noun)
KV_SERIALIZE(title_origin)
KV_SERIALIZE(title_unique)
KV_SERIALIZE(title)
KV_SERIALIZE(description)
KV_SERIALIZE(ignore)
KV_SERIALIZE(moose_killed)
@ -3163,6 +3174,7 @@ namespace cryptonote
KV_SERIALIZE(background_script_states)
KV_SERIALIZE(textures_created)
KV_SERIALIZE(textures_licenced)
KV_SERIALIZE(unique_titles)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
@ -4261,6 +4273,8 @@ namespace cryptonote
std::string description;
std::string icon;
bool manual;
std::string title_adjective;
std::string title_noun;
std::vector<badge_threshold_t> thresholds;
BEGIN_KV_SERIALIZE_MAP()
@ -4269,6 +4283,8 @@ namespace cryptonote
KV_SERIALIZE(description)
KV_SERIALIZE(icon)
KV_SERIALIZE(manual)
KV_SERIALIZE(title_adjective)
KV_SERIALIZE(title_noun)
KV_SERIALIZE(thresholds)
END_KV_SERIALIZE_MAP()
};
@ -6274,4 +6290,48 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS
{
struct request_t
{
uint32_t account;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(account)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct component_t
{
uint32_t id;
std::string string;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(id)
KV_SERIALIZE(string)
END_KV_SERIALIZE_MAP()
};
struct response_t
{
std::vector<component_t> adjectives;
std::vector<component_t> nouns;
std::vector<component_t> origins;
std::vector<component_t> uniques;
std::string status;
bool untrusted;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(adjectives)
KV_SERIALIZE(nouns)
KV_SERIALIZE(origins)
KV_SERIALIZE(uniques)
KV_SERIALIZE(status)
KV_SERIALIZE(untrusted)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
}

View File

@ -2964,7 +2964,7 @@ bool simple_wallet::cc_status(const std::vector<std::string> &args_)
std::vector<uint32_t> flags;
std::map<uint32_t, std::pair<uint8_t, uint64_t>> badges;
std::map<uint32_t, uint32_t> attributes;
std::string name, description;
std::string name, description, title;
std::string public_key, pmspk, pmvpk;
bool ignore;
uint32_t inviting_account, num_invited, first_flag;
@ -2974,7 +2974,8 @@ bool simple_wallet::cc_status(const std::vector<std::string> &args_)
std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> background_script_states;
uint32_t prestige;
std::vector<uint32_t> textures_created, textures_licenced;
m_wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk);
int32_t title_adjective, title_noun, title_origin, title_unique;
m_wallet->get_cc_account_data(id, public_key, balance, item_balances, flags, badges, attributes, name, title_adjective, title_noun, title_origin, title_unique, title, description, ignore, inviting_account, num_invited, first_flag, script, script_state, script_city, script_owner, reserve, script_variables, script_local_variables, background_script_states, prestige, textures_created, textures_licenced, pmspk, pmvpk);
SCOPED_WALLET_UNLOCK();
crypto::secret_key skey;

View File

@ -1206,7 +1206,7 @@ private:
std::vector<cryptonote::public_node> get_public_nodes(bool white_only = true);
// CC
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk);
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, int32_t &title_adjective, int32_t &title_noun, int32_t &title_origin, int32_t &title_unique, std::string &title, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk);
bool get_cc_account_name(uint32_t id, std::string &name);
bool get_cc_account_public_key(uint32_t id, crypto::public_key &pkey);
bool get_cc_account_pm_keys(uint32_t id, crypto::public_key &pmspk, crypto::public_key &pmvpk);
@ -1265,6 +1265,8 @@ private:
bool replace_cc_script_blob(uint32_t script, const std::string &blob, const std::vector<std::string> &blobs);
bool get_cc_merchant_ship_available_items(std::vector<cc::merchant_ship_available_item_t> &items);
bool get_cc_merchant_ships(std::vector<std::tuple<uint32_t, uint32_t, uint64_t, uint32_t, uint32_t, uint64_t, std::string, std::string, uint32_t>> &ships);
bool get_cc_available_title_components(uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques);
void add_cc_vista(const std::string &vista, const std::string &label, const std::string &picture);
void delete_cc_vista(const std::string &vista);
const std::vector<std::tuple<std::string, std::string, std::string>> &get_cc_vistas() const;

View File

@ -102,7 +102,7 @@ bool wallet2::ensure_cc_account()
return lookup_cc_account(m_cc_account, m_cc_balance);
}
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk)
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, std::pair<uint8_t, uint64_t>> &badges, std::map<uint32_t, uint32_t> &attributes, std::string &name, int32_t &title_adjective, int32_t &title_noun, int32_t &title_origin, int32_t &title_unique, std::string &title, std::string &description, bool &ignore, uint32_t &inviting_account, uint32_t &num_invited, uint32_t &first_flag, uint32_t &script, uint32_t &script_state, uint32_t &script_city, uint32_t &script_owner, std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve, std::map<std::string, uint64_t> &script_variables, std::map<std::string, uint64_t> &script_local_variables, std::map<uint32_t, std::pair<uint32_t, std::map<std::string, uint64_t>>> &background_script_states, uint32_t &prestige, std::vector<uint32_t> &textures_created, std::vector<uint32_t> &textures_licenced, std::string &pmspk, std::string &pmvpk)
{
cryptonote::COMMAND_RPC_CC_GET_ACCOUNT::request req = AUTO_VAL_INIT(req);
cryptonote::COMMAND_RPC_CC_GET_ACCOUNT::response res;
@ -128,6 +128,11 @@ bool wallet2::get_cc_account_data(uint32_t id, std::string &public_key, uint64_t
for (const auto &e: res.attributes)
attributes[e.type] = e.value;
name = std::move(res.name);
title_adjective = res.title_adjective;
title_noun = res.title_noun;
title_origin = res.title_origin;
title_unique = res.title_unique;
title = std::move(res.title);
description = std::move(res.description);
ignore = res.ignore;
inviting_account = res.inviting_account;
@ -669,7 +674,7 @@ bool wallet2::get_cc_badge_data(const std::vector<uint32_t> &id, std::vector<cc:
std::vector<std::pair<uint64_t, std::string>> thresholds;
for (auto &e: e.thresholds)
thresholds.push_back(std::make_pair(e.value, std::move(e.text)));
data.push_back({e.id, std::move(e.name), std::move(e.description), std::move(e.icon), e.manual, std::move(thresholds)});
data.push_back({e.id, std::move(e.name), std::move(e.description), std::move(e.icon), e.manual, std::move(e.title_adjective), std::move(e.title_noun), std::move(thresholds)});
}
return true;
}
@ -1846,4 +1851,38 @@ const std::vector<std::tuple<std::string, std::string, std::string>> &wallet2::g
return m_cc_vistas;
}
bool wallet2::get_cc_available_title_components(uint32_t id, std::vector<std::pair<uint32_t, std::string>> &adjectives, std::vector<std::pair<uint32_t, std::string>> &nouns, std::vector<std::pair<uint32_t, std::string>> &origins, std::vector<std::pair<uint32_t, std::string>> &uniques)
{
cryptonote::COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS::request req = AUTO_VAL_INIT(req);
cryptonote::COMMAND_RPC_CC_GET_AVAILABLE_TITLE_COMPONENTS::response res;
req.account = id;
m_daemon_rpc_mutex.lock();
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_available_title_components", req, res);
m_daemon_rpc_mutex.unlock();
if (!r || res.status != CORE_RPC_STATUS_OK)
return false;
adjectives.clear();
nouns.clear();
origins.clear();
uniques.clear();
adjectives.reserve(res.adjectives.size());
for (auto &e: res.adjectives)
adjectives.push_back({e.id, e.string});
nouns.reserve(res.nouns.size());
for (auto &e: res.nouns)
nouns.push_back({e.id, e.string});
origins.reserve(res.origins.size());
for (auto &e: res.origins)
origins.push_back({e.id, e.string});
uniques.reserve(res.uniques.size());
for (auto &e: res.uniques)
uniques.push_back({e.id, e.string});
return true;
}
}

View File

@ -7891,6 +7891,49 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_cc_set_title(const wallet_rpc::COMMAND_RPC_CC_SET_TITLE::request& req, wallet_rpc::COMMAND_RPC_CC_SET_TITLE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
LOG_PRINT_L3("on_cc_set_title 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_set_title_t cmd;
cmd.cc_account = m_wallet->get_cc_account();
cmd.delta_adjective = req.delta_adjective;
cmd.delta_noun = req.delta_noun;
cmd.delta_origin = req.delta_origin;
cmd.delta_unique = req.delta_unique;
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;
tools::wallet_rpc::key_image_list empty_key_images;
return fill_response(ptx_vector, false, dummy_tx_key, dummy_amount, res.fee, res.weight, 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, empty_key_images, 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

View File

@ -233,6 +233,7 @@ namespace tools
MAP_JON_RPC_WE("cc_retrieve_items", on_cc_retrieve_items, wallet_rpc::COMMAND_RPC_CC_RETRIEVE_ITEMS)
MAP_JON_RPC_WE("cc_create_runestones", on_cc_create_runestones, wallet_rpc::COMMAND_RPC_CC_CREATE_RUNESTONES)
MAP_JON_RPC_WE("cc_start_epoch", on_cc_start_epoch, wallet_rpc::COMMAND_RPC_CC_START_EPOCH)
MAP_JON_RPC_WE("cc_set_title", on_cc_set_title, wallet_rpc::COMMAND_RPC_CC_SET_TITLE)
END_JSON_RPC_MAP()
END_URI_MAP2()
@ -396,6 +397,7 @@ namespace tools
bool on_cc_retrieve_items(const wallet_rpc::COMMAND_RPC_CC_RETRIEVE_ITEMS::request& req, wallet_rpc::COMMAND_RPC_CC_RETRIEVE_ITEMS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_create_runestones(const wallet_rpc::COMMAND_RPC_CC_CREATE_RUNESTONES::request& req, wallet_rpc::COMMAND_RPC_CC_CREATE_RUNESTONES::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_start_epoch(const wallet_rpc::COMMAND_RPC_CC_START_EPOCH::request& req, wallet_rpc::COMMAND_RPC_CC_START_EPOCH::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_set_title(const wallet_rpc::COMMAND_RPC_CC_SET_TITLE::request& req, wallet_rpc::COMMAND_RPC_CC_SET_TITLE::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);

View File

@ -6728,5 +6728,58 @@ namespace wallet_rpc
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_CC_SET_TITLE
{
struct request_t
{
int32_t delta_adjective;
int32_t delta_noun;
int32_t delta_origin;
int32_t delta_unique;
uint32_t priority;
bool do_not_relay;
bool get_tx_keys;
bool get_tx_hex;
bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(delta_adjective)
KV_SERIALIZE(delta_noun)
KV_SERIALIZE(delta_origin)
KV_SERIALIZE(delta_unique)
KV_SERIALIZE(priority)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_keys, 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;
uint64_t weight;
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(weight)
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;
};
}
}

View File

@ -273,6 +273,7 @@ class CCTest():
self.test_cc_transfers()
self.check_gold_consistency()
self.check_event_balances()
self.test_titles()
self.test_messages()
self.check_gold_consistency()
self.test_buy_land()
@ -6045,6 +6046,64 @@ script {
self.wallet[2].rescan_blockchain()
self.deposits -= 100000000
def test_titles(self):
daemon = self.daemon
print("Testing titles")
res = self.wallet[2].cc_get_info()
account2_id = res.account_id
# the default is no title
res = daemon.cc_get_account(account2_id)
assert res.title == ""
# there should be some small default set of title compoments
res = daemon.cc_get_available_title_components(account2_id)
adjectives = res.adjectives if 'adjectives' in res else []
nouns = res.nouns if 'nouns' in res else []
origins = res.origins if 'origins' in res else []
uniques = res.uniques if 'uniques' in res else []
assert len(adjectives) > 0 or len(nouns) > 0
# at least the starting city is a valid origin, but we have no uniques yet
assert len(origins) > 0
assert len([x for x in origins if x.string == "Helsengaard"]) == 1
assert len(uniques) == 0
# we can't set invalid components
self.assert_exception(lambda: self.wallet[2].cc_set_title(666, 0, 0, 0))
self.assert_exception(lambda: self.wallet[2].cc_set_title(-666, 0, 0, 0))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 666, 0, 0))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, -666, 0, 0))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 0, 666, 0))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 0, -666, 0))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 0, 0, 666))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 0, 0, -666))
# can't set a unique, there are none
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 0, 0, 1))
self.assert_exception(lambda: self.wallet[2].cc_set_title(0, 0, 0, -1))
# we can set an origin though
origin_id = [x for x in origins if x.string == "Helsengaard"][0].id
res = daemon.cc_get_account(account2_id)
res = self.wallet[2].cc_set_title(0, 0, origin_id - res.title_origin, 0)
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
res = daemon.cc_get_account(account2_id)
assert res.title.endswith('of Helsengaard')
# we can add one of the small set above
adjective = adjectives[0] if len(adjectives) > 0 else None
noun = nouns[0] if len(nouns) > 0 else None
res = daemon.cc_get_account(account2_id)
res = self.wallet[2].cc_set_title((adjective.id - res.title_adjective) if adjective else 0, (noun.id - res.title_noun) if noun else 0, 0, 0)
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
res = daemon.cc_get_account(account2_id)
assert not adjective or adjective.string in res.title
assert not noun or noun.string in res.title
assert res.title.endswith('of Helsengaard')
def test_script_variables(self):
daemon = self.daemon
@ -9776,6 +9835,57 @@ script {
res = daemon.cc_get_script(script_id)
assert res.blob != other_blob
print('Testing awarding a title from a script')
script = """
script {
name "title"
state "0" {
choice { text "done" actions { award title \"the One\" } }
}
}
"""
res = self.wallet[3].cc_create_script(source = script)
expected_balances[3] -= res.fee
res = self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
res = daemon.cc_get_scripts(all = True)
assert len(res.scripts) > 1
script_id = res.scripts[-1].index
res = self.wallet[1].cc_start_script(script_id, city = 0, owner = GAME_ACCOUNT)
expected_balances[1] -= res.fee
res = self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
res = daemon.cc_get_account(account1_id)
assert res.script == script_id
assert res.script_city == 0
assert res.script_owner == GAME_ACCOUNT
assert res.script_state == 0
res = self.wallet[1].cc_script_choice(script_id, state = 0, city = 0, owner = GAME_ACCOUNT, choice = 0)
expected_balances[1] -= res.fee
res = self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
# the script has ended
res = daemon.cc_get_account(account1_id)
assert res.script == 0
# the player now has a title
res = daemon.cc_get_account(account1_id)
assert len(res.unique_titles) == 1
assert res.unique_titles[0] == "the One"
# and we can use it
res = self.wallet[1].cc_set_title(0, 0, 0, 1)
expected_balances[1] -= res.fee
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
res = daemon.cc_get_account(account1_id)
assert res.title.endswith('the One')
# check balances
for i in range(4):
res = daemon.cc_get_account(account_id[i])
assert res.balance == expected_balances[i], "exp " + str(expected_balances[i]) + ', got ' + str(res.balance) + " for wallet " + str(i)
assert (res.item_balances if 'item_balances' in res else []) == expected_item_balances[i]
def test_background_scripts(self):
daemon = self.daemon

View File

@ -3069,6 +3069,8 @@ TEST(cc, type_tags)
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x41);
cmd = cryptonote::cc_command_start_epoch_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x42);
cmd = cryptonote::cc_command_set_title_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x43);
}
TEST(cc, staff)

View File

@ -1470,3 +1470,14 @@ class Daemon(object):
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_get_epochs)
def cc_get_available_title_components(self, account):
cc_get_available_title_components = {
'method': 'cc_get_available_title_components',
'params': {
'account': account,
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_get_available_title_components)

View File

@ -2410,3 +2410,17 @@ class Wallet(object):
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_start_epoch)
def cc_set_title(self, delta_adjective, delta_noun, delta_origin, delta_unique):
cc_set_title = {
'method': 'cc_set_title',
'params': {
'delta_adjective' : delta_adjective,
'delta_noun' : delta_noun,
'delta_origin' : delta_origin,
'delta_unique' : delta_unique,
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_set_title)