forked from townforge/townforge
cc: reserves can be configured, and items types/count are operands
This commit is contained in:
parent
9eea9901f8
commit
a4e8d12f68
@ -27,7 +27,7 @@
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FLEX_TARGET(lexer tf-script.l ${CMAKE_CURRENT_BINARY_DIR}/tf-script-lexer.c COMPILE_FLAGS "-Ptfscript_ -i")
|
||||
BISON_TARGET(parser tf-script.y ${CMAKE_CURRENT_BINARY_DIR}/tf-script-parser.c COMPILE_FLAGS "-ptfscript_ -d")
|
||||
BISON_TARGET(parser tf-script.y ${CMAKE_CURRENT_BINARY_DIR}/tf-script-parser.c COMPILE_FLAGS "-ptfscript_ -d -v")
|
||||
ADD_FLEX_BISON_DEPENDENCY(lexer parser)
|
||||
|
||||
set(cc_sources
|
||||
|
@ -88,10 +88,11 @@ bool cc_command_handler_start_script::check(const cryptonote::BlockchainDB &db,
|
||||
CHECK_COMMAND_SET(cc::script::load_script_binary(sd.blob, script), tvc.m_cc_invalid_script, "Failed to load script");
|
||||
CHECK_COMMAND_SET(db.does_cc_city_exist(start_script.city), tvc.m_cc_invalid_city, "City does not exist");
|
||||
|
||||
const auto overrides = cc::script::get_script_overrides(script);
|
||||
cc::runestone_t runestone;
|
||||
if (start_script.flag)
|
||||
{
|
||||
cryptonote::cc_flag_data_t fd;
|
||||
cc::runestone_t runestone;
|
||||
CHECK_COMMAND_SET(db.get_cc_flag_data(start_script.flag, fd), tvc.m_cc_invalid_flag, "Invalid flag");
|
||||
CHECK_COMMAND_SET(db.get_cc_runestone(start_script.flag, start_script.x, start_script.y, start_script.h, runestone), tvc.m_cc_no_runestone, "No runestone found");
|
||||
CHECK_COMMAND_SET(runestone.script == start_script.script, tvc.m_cc_invalid_script, "Runestone script does not match the script to start");
|
||||
@ -110,7 +111,7 @@ bool cc_command_handler_start_script::check(const cryptonote::BlockchainDB &db,
|
||||
owner = GAME_ACCOUNT;
|
||||
}
|
||||
|
||||
CHECK_COMMAND_SET(cc::script::is_available(db, script, start_script.cc_account, owner, start_script.city), tvc.m_cc_invalid_script,
|
||||
CHECK_COMMAND_SET(cc::script::is_available(db, script, overrides, runestone.overrides, start_script.cc_account, owner, start_script.city), tvc.m_cc_invalid_script,
|
||||
"Script is not available to this account in this city");
|
||||
|
||||
return true;
|
||||
@ -141,10 +142,6 @@ bool cc_command_handler_start_script::execute(cryptonote::BlockchainDB &db, cons
|
||||
owner = GAME_ACCOUNT;
|
||||
}
|
||||
|
||||
cc::script::get_reserves(script, reserved_owner_balance, reserved_owner_items, reserved_player_balance, reserved_player_items);
|
||||
db.reserve_cc_account(owner, start_script.cc_account, reserved_owner_balance, reserved_owner_items);
|
||||
db.reserve_cc_account(start_script.cc_account, owner, reserved_player_balance, reserved_player_items);
|
||||
|
||||
const auto overrides = cc::script::get_script_overrides(script);
|
||||
|
||||
std::map<uint32_t, std::string> string_overrides;
|
||||
@ -153,9 +150,9 @@ bool cc_command_handler_start_script::execute(cryptonote::BlockchainDB &db, cons
|
||||
if (std::get<0>(e) == cc::script::override_string)
|
||||
string_overrides[std::get<1>(e)] = std::get<2>(e);
|
||||
}
|
||||
cc::runestone_t runestone;
|
||||
if (start_script.flag)
|
||||
{
|
||||
cc::runestone_t runestone;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_runestone(start_script.flag, start_script.x, start_script.y, start_script.h, runestone), false, "No runestone found");
|
||||
for (const auto &e: runestone.overrides)
|
||||
if (std::get<0>(e) == cc::script::override_string)
|
||||
@ -165,13 +162,19 @@ bool cc_command_handler_start_script::execute(cryptonote::BlockchainDB &db, cons
|
||||
{
|
||||
cc::script::resolve_reference(db, e.second); // ignore errors, we might have 32 byte text and not a ref
|
||||
}
|
||||
db.set_cc_account_script_state(start_script.cc_account, start_script.script, owner, 0, start_script.city, string_overrides);
|
||||
|
||||
for (const auto &e: overrides)
|
||||
{
|
||||
if (std::get<0>(e) == cc::script::override_local)
|
||||
db.set_cc_account_script_variable(start_script.cc_account, std::get<2>(e), std::get<1>(e), true);
|
||||
}
|
||||
for (const auto &e: runestone.overrides)
|
||||
if (std::get<0>(e) == cc::script::override_local)
|
||||
db.set_cc_account_script_variable(start_script.cc_account, std::get<2>(e), std::get<1>(e), true);
|
||||
|
||||
cc::script::get_reserves(db, script, overrides, runestone.overrides, reserved_owner_balance, reserved_owner_items, reserved_player_balance, reserved_player_items, start_script.cc_account, owner, start_script.city);
|
||||
db.reserve_cc_account(owner, start_script.cc_account, reserved_owner_balance, reserved_owner_items);
|
||||
db.reserve_cc_account(start_script.cc_account, owner, reserved_player_balance, reserved_player_items);
|
||||
|
||||
db.set_cc_account_script_state(start_script.cc_account, start_script.script, owner, 0, start_script.city, string_overrides);
|
||||
|
||||
cc::script::script_effects_t effects;
|
||||
try
|
||||
@ -339,7 +342,16 @@ bool cc_command_handler_start_script::revert(cryptonote::BlockchainDB &db, const
|
||||
db.set_cc_account_script_variable(start_script.cc_account, e.name, db.get_cc_account_script_variable(start_script.cc_account, e.name, true) - e.value_delta, true);
|
||||
}
|
||||
|
||||
cc::script::get_reserves(script, reserved_owner_balance, reserved_owner_items, reserved_player_balance, reserved_player_items);
|
||||
const auto overrides = cc::script::get_script_overrides(script);
|
||||
cc::runestone_t runestone;
|
||||
if (start_script.flag)
|
||||
{
|
||||
cryptonote::cc_flag_data_t fd;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_flag_data(start_script.flag, fd), false, "Invalid flag");
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_runestone(start_script.flag, start_script.x, start_script.y, start_script.h, runestone), false, "No runestone found");
|
||||
}
|
||||
|
||||
cc::script::get_reserves(db, script, overrides, runestone.overrides, reserved_owner_balance, reserved_owner_items, reserved_player_balance, reserved_player_items, start_script.cc_account, owner, start_script.city);
|
||||
db.unreserve_cc_account(owner, start_script.cc_account, reserved_owner_balance, reserved_owner_items);
|
||||
db.unreserve_cc_account(start_script.cc_account, owner, reserved_player_balance, reserved_player_items);
|
||||
db.set_cc_account_script_state(start_script.cc_account, 0, 0, 0, 0, {});
|
||||
|
@ -24,6 +24,31 @@
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "cc.script"
|
||||
|
||||
class BlockchainStateProxyWithOverrides: public cc::BlockchainStateProxy
|
||||
{
|
||||
public:
|
||||
BlockchainStateProxyWithOverrides(const cryptonote::BlockchainDB &db, uint32_t account, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &local_overrides): cc::BlockchainStateProxy(db)
|
||||
{
|
||||
for (const auto &e: overrides)
|
||||
if (std::get<0>(e) == cc::script::override_local)
|
||||
local_variables[std::make_pair(account, std::get<2>(e))] = std::get<1>(e);
|
||||
for (const auto &e: local_overrides)
|
||||
if (std::get<0>(e) == cc::script::override_local)
|
||||
local_variables[std::make_pair(account, std::get<2>(e))] = std::get<1>(e);
|
||||
}
|
||||
|
||||
virtual uint64_t get_local_variable(uint32_t id, const std::string &name) const
|
||||
{
|
||||
const auto i = local_variables.find(std::make_pair(id, name));
|
||||
if (i != local_variables.end())
|
||||
return i->second;
|
||||
return cc::BlockchainStateProxy::get_local_variable(id, name);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::pair<uint32_t, std::string>, uint64_t> local_variables;
|
||||
};
|
||||
|
||||
typedef boost::multiprecision::int128_t int128_t;
|
||||
|
||||
Script *tfscript_script = NULL;
|
||||
@ -180,28 +205,36 @@ static void print_action_string(const Action &a, std::string &source, const std:
|
||||
source += I + "}\n";
|
||||
break;
|
||||
case action_pay_gold:
|
||||
source += I + "pay gold " + get_operand_string(a.op, op_gold) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 1, "Expected one operand for action_pay_gold, got " << a.ops.size());
|
||||
source += I + "pay gold " + get_operand_string(a.ops[0], op_gold) + "\n";
|
||||
break;
|
||||
case action_award_gold:
|
||||
source += I + "award gold " + get_operand_string(a.op, op_gold) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 1, "Expected one operand for action_award_gold, got " << a.ops.size());
|
||||
source += I + "award gold " + get_operand_string(a.ops[0], op_gold) + "\n";
|
||||
break;
|
||||
case action_pay_item:
|
||||
source += I + "pay item " + std::to_string(a.key) + " " + get_operand_string(a.op, op_unsigned) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 2, "Expected two operands for action_pay_item, got " << a.ops.size());
|
||||
source += I + "pay item " + get_operand_string(a.ops[0], op_unsigned) + " " + get_operand_string(a.ops[1], op_unsigned) + "\n";
|
||||
break;
|
||||
case action_award_item:
|
||||
source += I + "award item " + std::to_string(a.key) + " " + get_operand_string(a.op, op_unsigned) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 2, "Expected two operands for action_award_item, got " << a.ops.size());
|
||||
source += I + "award item " + get_operand_string(a.ops[0], op_unsigned) + " " + get_operand_string(a.ops[1], op_unsigned) + "\n";
|
||||
break;
|
||||
case action_consume_item:
|
||||
source += I + "consume item " + std::to_string(a.key) + " " + get_operand_string(a.op, op_unsigned) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 2, "Expected two operands for action_consume_item, got " << a.ops.size());
|
||||
source += I + "consume item " + get_operand_string(a.ops[0], op_unsigned) + " " + get_operand_string(a.ops[1], op_unsigned) + "\n";
|
||||
break;
|
||||
case action_set_global_variable:
|
||||
source += I + "set global \"" + escape(a.str) + "\" " + get_operand_string(a.op, op_unsigned) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 1, "Expected one operand for action_set_global_variable, got " << a.ops.size());
|
||||
source += I + "set global \"" + escape(a.str) + "\" " + get_operand_string(a.ops[0], op_unsigned) + "\n";
|
||||
break;
|
||||
case action_set_local_variable:
|
||||
source += I + "set local \"" + escape(a.str) + "\" " + get_operand_string(a.op, op_unsigned) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 1, "Expected one operand for action_set_local_variable, got " << a.ops.size());
|
||||
source += I + "set local \"" + escape(a.str) + "\" " + get_operand_string(a.ops[0], op_unsigned) + "\n";
|
||||
break;
|
||||
case action_set_player_variable:
|
||||
source += I + "set player \"" + escape(a.str) + "\" " + get_operand_string(a.op, op_unsigned) + "\n";
|
||||
CHECK_AND_ASSERT_THROW_MES(a.ops.size() == 1, "Expected one operand for action_set_player_variable, got " << a.ops.size());
|
||||
source += I + "set player \"" + escape(a.str) + "\" " + get_operand_string(a.ops[0], op_unsigned) + "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -241,13 +274,13 @@ bool save_script_native(const ScriptHandle &s, std::string &source, uint32_t fla
|
||||
source += indent + "reserves {\n";
|
||||
for (const auto &e: script->player_reserves)
|
||||
{
|
||||
if (e.balance > 0) source += indent + indent + "player gold " + cryptonote::print_money(e.balance) + "\n";
|
||||
if (e.item_type != 0 && e.item_amount != 0) source += indent + indent + "player item " + std::to_string(e.item_type) + " " + std::to_string(e.item_amount) + "\n";
|
||||
if (e.is_gold) source += indent + indent + "player gold " + get_operand_string(e.amount, op_gold) + "\n";
|
||||
else source += indent + indent + "player item " + get_operand_string(e.type, op_unsigned) + " " + get_operand_string(e.amount, op_unsigned) + "\n";
|
||||
}
|
||||
for (const auto &e: script->owner_reserves)
|
||||
{
|
||||
if (e.balance > 0) source += indent + indent + "owner gold " + cryptonote::print_money(e.balance) + "\n";
|
||||
if (e.item_type != 0 && e.item_amount != 0) source += indent + indent + "owner item " + std::to_string(e.item_type) + " " + std::to_string(e.item_amount) + "\n";
|
||||
if (e.is_gold) source += indent + indent + "owner gold " + get_operand_string(e.amount, op_gold) + "\n";
|
||||
else source += indent + indent + "owner item " + get_operand_string(e.type, op_unsigned) + " " + get_operand_string(e.amount, op_unsigned) + "\n";
|
||||
}
|
||||
source += indent + "}\n";
|
||||
for (const auto &state: script->states)
|
||||
@ -821,11 +854,39 @@ static std::string get_expression_string(const Expression &c)
|
||||
return s;
|
||||
}
|
||||
|
||||
bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uint32_t account, uint32_t owner, uint32_t city, std::vector<std::pair<std::string, bool>> *requirements)
|
||||
static bool accumulate_reserves(BlockchainStateProxy &proxy, const std::vector<Reserve> &reserves, uint64_t &gold, std::map<uint32_t, uint32_t> &items, uint32_t account, uint32_t city, const crypto::hash &seed, uint64_t &salt)
|
||||
{
|
||||
const uint64_t height = proxy.height();
|
||||
gold = 0;
|
||||
items.clear();
|
||||
for (const auto &r: reserves)
|
||||
{
|
||||
if (r.is_gold)
|
||||
{
|
||||
const std::pair<uint64_t, bool> amount_value = get_attribute(proxy, r.amount, account, city, seed, salt);
|
||||
CHECK_AND_ASSERT_MES(!amount_value.second, false, "Gold value is signed");
|
||||
CHECK_AND_ASSERT_MES(gold <= std::numeric_limits<uint64_t>::max() - amount_value.first, false, "Overflow in reserves");
|
||||
gold += amount_value.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::pair<uint64_t, bool> type_value = get_attribute(proxy, r.type, account, city, seed, salt);
|
||||
CHECK_AND_ASSERT_MES(!type_value.second, false, "Item type value is signed");
|
||||
const std::pair<uint64_t, bool> amount_value = get_attribute(proxy, r.amount, account, city, seed, salt);
|
||||
CHECK_AND_ASSERT_MES(!amount_value.second, false, "Item amount value is signed");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(type_value.first, height), false, "Item " << type_value.first << " is not a valid item or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(items[type_value.first] <= std::numeric_limits<uint32_t>::max() - amount_value.first, false, "Overflow in reserves");
|
||||
items[type_value.first] += amount_value.first;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &default_overrides, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides, uint32_t account, uint32_t owner, uint32_t city, std::vector<std::pair<std::string, bool>> *requirements)
|
||||
{
|
||||
bool available = true;
|
||||
|
||||
BlockchainStateProxy proxy(db);
|
||||
BlockchainStateProxyWithOverrides proxy(db, account, default_overrides, overrides);
|
||||
const Script *script = s.script;
|
||||
const crypto::hash seed = db.get_cc_random_seed();
|
||||
uint64_t salt = (((uint64_t)account) << 32) | 0;
|
||||
@ -845,26 +906,9 @@ bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uin
|
||||
|
||||
uint64_t player_balance_reserve = 0, owner_balance_reserve = 0;
|
||||
std::map<uint32_t, uint32_t> player_item_reserve, owner_item_reserve;
|
||||
for (const auto &r: script->player_reserves)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(player_balance_reserve <= std::numeric_limits<uint64_t>::max() - r.balance, false, "Overflow in reserves");
|
||||
player_balance_reserve += r.balance;
|
||||
if (r.item_type != 0)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(player_item_reserve[r.item_type] <= std::numeric_limits<uint32_t>::max() - r.item_amount, false, "Overflow in reserves");
|
||||
player_item_reserve[r.item_type] += r.item_amount;
|
||||
}
|
||||
}
|
||||
for (const auto &r: script->owner_reserves)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(owner_balance_reserve <= std::numeric_limits<uint64_t>::max() - r.balance, false, "Overflow in reserves");
|
||||
owner_balance_reserve += r.balance;
|
||||
if (r.item_type != 0)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(owner_item_reserve[r.item_type] <= std::numeric_limits<uint32_t>::max() - r.item_amount, false, "Overflow in reserves");
|
||||
owner_item_reserve[r.item_type] += r.item_amount;
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(accumulate_reserves(proxy, script->player_reserves, player_balance_reserve, player_item_reserve, account, city, seed, salt), false, "Failed to accumulate player reserves");
|
||||
CHECK_AND_ASSERT_MES(accumulate_reserves(proxy, script->owner_reserves, owner_balance_reserve, owner_item_reserve, owner, city, seed, salt), false, "Failed to accumulate owner reserves");
|
||||
|
||||
bool met = false;
|
||||
cryptonote::cc_account_data_t ad{};
|
||||
if (account > 0)
|
||||
@ -874,7 +918,7 @@ bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uin
|
||||
}
|
||||
if (!met)
|
||||
available = false;
|
||||
if (requirements)
|
||||
if (requirements && player_balance_reserve > 0)
|
||||
requirements->push_back({"Reserve: " + cryptonote::print_money(player_balance_reserve) + " gold", met});
|
||||
for (const auto &e: player_item_reserve)
|
||||
{
|
||||
@ -882,7 +926,7 @@ bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uin
|
||||
met = i != ad.item_balances.end() && i->second >= e.second;
|
||||
if (!met)
|
||||
available = false;
|
||||
if (requirements)
|
||||
if (requirements && e.second > 0)
|
||||
{
|
||||
std::string s = "Reserve: " + std::to_string(e.second) + " " + cc::get_item_name(db, e.first);
|
||||
requirements->push_back({std::move(s), met});
|
||||
@ -896,7 +940,7 @@ bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uin
|
||||
}
|
||||
if (!met)
|
||||
available = false;
|
||||
if (requirements)
|
||||
if (requirements && owner_balance_reserve > 0)
|
||||
requirements->push_back({"Counterparty reserve: " + cryptonote::print_money(owner_balance_reserve) + " gold", met});
|
||||
for (const auto &e: owner_item_reserve)
|
||||
{
|
||||
@ -904,7 +948,7 @@ bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uin
|
||||
met = i != ad.item_balances.end() && i->second >= e.second;
|
||||
if (!met)
|
||||
available = false;
|
||||
if (requirements)
|
||||
if (requirements && e.second > 0)
|
||||
{
|
||||
std::string s = "Counterparty reserve: " + std::to_string(e.second) + " " + cc::get_item_name(db, e.first);
|
||||
requirements->push_back({std::move(s), met});
|
||||
@ -914,33 +958,14 @@ bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &s, uin
|
||||
return available;
|
||||
}
|
||||
|
||||
void get_reserves(const ScriptHandle &s, uint64_t &reserved_owner_balance, std::map<uint32_t, uint32_t> &reserved_owner_items, uint64_t &reserved_player_balance, std::map<uint32_t, uint32_t> &reserved_player_items)
|
||||
void get_reserves(const cryptonote::BlockchainDB &db, const ScriptHandle &s, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &default_overrides, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides, uint64_t &reserved_owner_balance, std::map<uint32_t, uint32_t> &reserved_owner_items, uint64_t &reserved_player_balance, std::map<uint32_t, uint32_t> &reserved_player_items, uint32_t account, uint32_t owner, uint32_t city)
|
||||
{
|
||||
reserved_owner_balance = 0;
|
||||
reserved_owner_items.clear();
|
||||
reserved_player_balance = 0;
|
||||
reserved_player_items.clear();
|
||||
BlockchainStateProxyWithOverrides proxy(db, account, default_overrides, overrides);
|
||||
const crypto::hash seed = proxy.get_cc_random_seed();
|
||||
uint64_t salt = (((uint64_t)account) << 32) | 0x30000000;
|
||||
|
||||
for (const auto &r: s.script->owner_reserves)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(reserved_owner_balance <= std::numeric_limits<uint64_t>::max() - r.balance, "Overflow in reserves");
|
||||
reserved_owner_balance += r.balance;
|
||||
if (r.item_type != 0)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(reserved_owner_items[r.item_type] <= std::numeric_limits<uint32_t>::max() - r.item_amount, "Overflow in reserves");
|
||||
reserved_owner_items[r.item_type] += r.item_amount;
|
||||
}
|
||||
}
|
||||
for (const auto &r: s.script->player_reserves)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(reserved_player_balance <= std::numeric_limits<uint64_t>::max() - r.balance, "Overflow in reserves");
|
||||
reserved_player_balance += r.balance;
|
||||
if (r.item_type != 0)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(reserved_player_items[r.item_type] <= std::numeric_limits<uint32_t>::max() - r.item_amount, "Overflow in reserves");
|
||||
reserved_player_items[r.item_type] += r.item_amount;
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_THROW_MES(accumulate_reserves(proxy, s.script->player_reserves, reserved_player_balance, reserved_player_items, account, city, seed, salt), "Failed to accumulate player reserves");
|
||||
CHECK_AND_ASSERT_THROW_MES(accumulate_reserves(proxy, s.script->owner_reserves, reserved_owner_balance, reserved_owner_items, owner, city, seed, salt), "Failed to accumulate owner reserves");
|
||||
}
|
||||
|
||||
bool get_state(BlockchainStateProxy &proxy, const ScriptHandle &s, uint32_t account, uint32_t current_state, uint32_t city, std::string &ui, std::string &text, std::string &image, std::vector<std::tuple<uint32_t, std::string, std::string>> &choices, std::string &choices_ui)
|
||||
@ -1000,8 +1025,10 @@ static bool execute(cryptonote::cc_command_t cmd, BlockchainStateProxy &proxy, g
|
||||
return true;
|
||||
|
||||
cryptonote::cc_account_data_t ad;
|
||||
const auto value_signed = action.op.type == op_none ? std::make_pair<uint64_t, bool>(0, false) : get_attribute(proxy, action.op, account, city, seed, salt);
|
||||
const auto value_signed = action.ops.empty() || action.ops[0].type == op_none ? std::make_pair<uint64_t, bool>(0, false) : get_attribute(proxy, action.ops[0], account, city, seed, salt);
|
||||
const uint64_t value = value_signed.first;
|
||||
const auto value_signed_extra = action.ops.size() <= 1 || action.ops[1].type == op_none ? std::make_pair<uint64_t, bool>(0, false) : get_attribute(proxy, action.ops[1], account, city, seed, salt);
|
||||
const uint64_t value_extra = value_signed_extra.first;
|
||||
switch (action.type)
|
||||
{
|
||||
case action_none:
|
||||
@ -1049,13 +1076,13 @@ static bool execute(cryptonote::cc_command_t cmd, BlockchainStateProxy &proxy, g
|
||||
events.add_full(cmd, owner, 0, ITEM_NONE, 0, value) << "Receives " << cryptonote::print_money(value) << " gold in '" << get_script_name(script) << "'";
|
||||
break;
|
||||
case action_pay_item:
|
||||
CHECK_AND_ASSERT_MES(action.key <= std::numeric_limits<uint32_t>::max(), false, "Key is out of range");
|
||||
CHECK_AND_ASSERT_MES(value <= std::numeric_limits<uint32_t>::max(), false, "Too many paid items");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(action.key, proxy.height()), false, "Item is not a valid item, or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_item_balance(account, owner, action.key, value), false, "Not enough item balance to pay for action");
|
||||
CHECK_AND_ASSERT_MES(proxy.increase_reserve_item_balance(owner, account, action.key, value), false, "Not enough item balance to pay for action");
|
||||
events.add_full(cmd, account, 0, action.key, value, 0) << "Gives " << action.key << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
events.add_full(cmd, owner, 0, action.key, value, 0) << "Receives " << action.key << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
CHECK_AND_ASSERT_MES(value <= std::numeric_limits<uint32_t>::max(), false, "Item type is out of range");
|
||||
CHECK_AND_ASSERT_MES(value_extra <= std::numeric_limits<uint32_t>::max(), false, "Too many paid items");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(value, proxy.height()), false, "Item " << value << " is not a valid item, or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_item_balance(account, owner, value, value_extra), false, "Not enough item balance to pay for action");
|
||||
CHECK_AND_ASSERT_MES(proxy.increase_reserve_item_balance(owner, account, value, value_extra), false, "Not enough item balance to pay for action");
|
||||
events.add_full(cmd, account, 0, value, value_extra, 0) << "Gives " << value_extra << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
events.add_full(cmd, owner, 0, value, value_extra, 0) << "Receives " << value_extra << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
break;
|
||||
case action_award_gold:
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_balance(owner, account, value), false, "Not enough balance to pay for action");
|
||||
@ -1064,21 +1091,21 @@ static bool execute(cryptonote::cc_command_t cmd, BlockchainStateProxy &proxy, g
|
||||
events.add_full(cmd, owner, 0, ITEM_NONE, 0, value) << "Awards " << cryptonote::print_money(value) << " gold in '" << get_script_name(script) << "'";
|
||||
break;
|
||||
case action_award_item:
|
||||
CHECK_AND_ASSERT_MES(action.key <= std::numeric_limits<uint32_t>::max(), false, "Key is out of range");
|
||||
CHECK_AND_ASSERT_MES(value <= std::numeric_limits<uint32_t>::max(), false, "Too many awarded items");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(action.key, proxy.height()), false, "Item is not a valid item, or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_item_balance(owner, account, action.key, value), false, "Item balance underflow");
|
||||
CHECK_AND_ASSERT_MES(proxy.increase_reserve_item_balance(account, owner, action.key, value), false, "Item balance overflow");
|
||||
events.add_full(cmd, account, 0, action.key, value, 0) << "Receives " << action.key << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
events.add_full(cmd, owner, 0, action.key, value, 0) << "Awards " << action.key << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
CHECK_AND_ASSERT_MES(value <= std::numeric_limits<uint32_t>::max(), false, "Item type is out of range");
|
||||
CHECK_AND_ASSERT_MES(value_extra <= std::numeric_limits<uint32_t>::max(), false, "Too many awarded items");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(value, proxy.height()), false, "Item " << value << " is not a valid item, or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_item_balance(owner, account, value, value_extra), false, "Item balance underflow");
|
||||
CHECK_AND_ASSERT_MES(proxy.increase_reserve_item_balance(account, owner, value, value_extra), false, "Item balance overflow");
|
||||
events.add_full(cmd, account, 0, value, value_extra, 0) << "Receives " << value_extra << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
events.add_full(cmd, owner, 0, value, value_extra, 0) << "Awards " << value_extra << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
break;
|
||||
case action_consume_item:
|
||||
CHECK_AND_ASSERT_MES(action.key <= std::numeric_limits<uint32_t>::max(), false, "Key is out of range");
|
||||
CHECK_AND_ASSERT_MES(value <= std::numeric_limits<uint32_t>::max(), false, "Too many consumed items");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(action.key, proxy.height()), false, "Item is not a valid item, or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_item_balance(account, owner, action.key, value), false, "Item balance underflow");
|
||||
proxy.decrease_item_count(action.key, value);
|
||||
events.add_full(cmd, account, 0, action.key, value, 0) << "Consumes " << action.key << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
CHECK_AND_ASSERT_MES(value <= std::numeric_limits<uint32_t>::max(), false, "Item type is out of range");
|
||||
CHECK_AND_ASSERT_MES(value_extra <= std::numeric_limits<uint32_t>::max(), false, "Too many consumed items");
|
||||
CHECK_AND_ASSERT_MES(cc::is_item_enabled(value, proxy.height()), false, "Item " << value << " is not a valid item, or is not enabled");
|
||||
CHECK_AND_ASSERT_MES(proxy.decrease_reserve_item_balance(account, owner, value, value_extra), false, "Item balance underflow");
|
||||
proxy.decrease_item_count(value, value_extra);
|
||||
events.add_full(cmd, account, 0, value, value_extra, 0) << "Consumes " << value_extra << " " << proxy.get_item_name(value) << " in '" << get_script_name(script) << "'";
|
||||
break;
|
||||
case action_set_global_variable:
|
||||
CHECK_AND_ASSERT_MES(!action.str.empty(), false, "Global variable has no name");
|
||||
|
@ -146,8 +146,8 @@ std::string get_script_desc(const ScriptHandle &script);
|
||||
std::string get_script_icon(const ScriptHandle &script);
|
||||
std::vector<std::tuple<uint8_t, uint32_t, std::string>> get_script_overrides(const ScriptHandle &script);
|
||||
bool is_script_public(const ScriptHandle &script);
|
||||
bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &script, uint32_t account, uint32_t owner, uint32_t city, std::vector<std::pair<std::string, bool>> *requirements = NULL);
|
||||
void get_reserves(const ScriptHandle &s, uint64_t &reserved_owner_balance, std::map<uint32_t, uint32_t> &reserved_owner_items, uint64_t &reserved_player_balance, std::map<uint32_t, uint32_t> &reserved_player_items);
|
||||
bool is_available(const cryptonote::BlockchainDB &db, const ScriptHandle &script, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &default_overrides, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides, uint32_t account, uint32_t owner, uint32_t city, std::vector<std::pair<std::string, bool>> *requirements = NULL);
|
||||
void get_reserves(const cryptonote::BlockchainDB &db, const ScriptHandle &s, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &default_overrides, const std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides, uint64_t &reserved_owner_balance, std::map<uint32_t, uint32_t> &reserved_owner_items, uint64_t &reserved_player_balance, std::map<uint32_t, uint32_t> &reserved_player_items, uint32_t account, uint32_t owner, uint32_t city);
|
||||
bool get_next_state(const ScriptHandle &s, uint32_t current_state, uint32_t choice, int32_t &new_state);
|
||||
bool get_state(BlockchainStateProxy &proxy, const ScriptHandle &s, uint32_t account, uint32_t current_state, uint32_t city, std::string &ui, std::string &text, std::string &image, std::vector<std::tuple<uint32_t, std::string, std::string>> &choices, std::string &choices_ui);
|
||||
|
||||
|
@ -212,16 +212,14 @@ struct WeightedAction;
|
||||
struct Action
|
||||
{
|
||||
uint32_t type{action_none};
|
||||
uint64_t key{0};
|
||||
std::string str;
|
||||
Operand op;
|
||||
std::vector<Operand> ops;
|
||||
std::vector<WeightedAction> actions;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VARINT_FIELD(type)
|
||||
VARINT_FIELD(key)
|
||||
FIELD(str)
|
||||
FIELD(op)
|
||||
FIELD(ops)
|
||||
FIELD(actions)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
@ -277,14 +275,14 @@ struct State
|
||||
|
||||
struct Reserve
|
||||
{
|
||||
uint64_t balance{0};
|
||||
uint32_t item_type{0};
|
||||
uint32_t item_amount{0};
|
||||
uint8_t is_gold;
|
||||
Operand type;
|
||||
Operand amount;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VARINT_FIELD(balance)
|
||||
VARINT_FIELD(item_type)
|
||||
VARINT_FIELD(item_amount)
|
||||
FIELD(is_gold)
|
||||
FIELD(type)
|
||||
FIELD(amount)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
@ -371,8 +369,8 @@ void set_partial_state_binary_compound_expression(script_partial_state_t *state,
|
||||
void set_partial_state_unary_expression(script_partial_state_t *state, FunctionType type);
|
||||
void set_partial_state_ternary(script_partial_state_t *state);
|
||||
void set_partial_state_precondition(script_partial_state_t *state, const char *text);
|
||||
void set_partial_state_gold_reserve(script_partial_state_t *state, bool player, uint64_t amount);
|
||||
void set_partial_state_item_reserve(script_partial_state_t *state, bool player, uint32_t item, uint32_t amount);
|
||||
void set_partial_state_gold_reserve(script_partial_state_t *state, bool player);
|
||||
void set_partial_state_item_reserve(script_partial_state_t *state, bool player);
|
||||
void set_partial_state_name(script_partial_state_t *state, const char *s);
|
||||
void set_partial_state_owner(script_partial_state_t *state, uint32_t owner);
|
||||
void set_partial_state_description(script_partial_state_t *state, const char *s);
|
||||
@ -380,7 +378,7 @@ void set_partial_state_icon(script_partial_state_t *state, const char *s);
|
||||
void set_partial_state_public(script_partial_state_t *state);
|
||||
void set_partial_state_override_string(script_partial_state_t *state, uint32_t n, const char *text);
|
||||
void set_partial_state_override_local(script_partial_state_t *state, const char *text, uint32_t n);
|
||||
void set_partial_state_action(script_partial_state_t *state, ActionType type, uint64_t key, const char *str, bool has_op);
|
||||
void set_partial_state_action(script_partial_state_t *state, ActionType type, const char *str, unsigned num_ops);
|
||||
void set_partial_state_action_pick_count_up(script_partial_state_t *state);
|
||||
void set_partial_state_action_set_weight(script_partial_state_t *state, uint32_t weight);
|
||||
void set_partial_state_action_pick(script_partial_state_t *state);
|
||||
|
@ -282,44 +282,55 @@ void set_partial_state_override_local(script_partial_state_t *state, const char
|
||||
state->script->overrides.push_back({cc::script::override_local, n, text});
|
||||
}
|
||||
|
||||
void set_partial_state_gold_reserve(script_partial_state_t *state, bool player, uint64_t amount)
|
||||
void set_partial_state_gold_reserve(script_partial_state_t *state, bool player)
|
||||
{
|
||||
MDEBUG((player ? "player" : "owner") << " gold reserve: " << amount);
|
||||
MDEBUG((player ? "player" : "owner") << " gold reserve");
|
||||
if (state->operands.size() < 1)
|
||||
{
|
||||
tfscript_error("Gold reserve needs at least one operand");
|
||||
return;
|
||||
}
|
||||
Reserve r;
|
||||
r.balance = amount;
|
||||
r.item_type = r.item_amount = 0;
|
||||
(player ? state->script->player_reserves : state->script->owner_reserves).push_back(r);
|
||||
r.is_gold = 1;
|
||||
r.amount = std::move(state->operands[state->operands.size() - 1]);
|
||||
state->operands.pop_back();
|
||||
(player ? state->script->player_reserves : state->script->owner_reserves).push_back(std::move(r));
|
||||
}
|
||||
|
||||
void set_partial_state_item_reserve(script_partial_state_t *state, bool player, uint32_t item, uint32_t amount)
|
||||
void set_partial_state_item_reserve(script_partial_state_t *state, bool player)
|
||||
{
|
||||
MDEBUG((player ? "player" : "owner") << " item reserve: " << amount);
|
||||
MDEBUG((player ? "player" : "owner") << " item reserve");
|
||||
if (state->operands.size() < 2)
|
||||
{
|
||||
tfscript_error("Item reserve needs at least two operands");
|
||||
return;
|
||||
}
|
||||
Reserve r;
|
||||
r.balance = 0;
|
||||
r.item_type = item;
|
||||
r.item_amount = amount;
|
||||
(player ? state->script->player_reserves : state->script->owner_reserves).push_back(r);
|
||||
r.is_gold = 0;
|
||||
r.type = std::move(state->operands[state->operands.size() - 2]);
|
||||
r.amount = std::move(state->operands[state->operands.size() - 1]);
|
||||
state->operands.pop_back();
|
||||
state->operands.pop_back();
|
||||
(player ? state->script->player_reserves : state->script->owner_reserves).push_back(std::move(r));
|
||||
}
|
||||
|
||||
void set_partial_state_action(script_partial_state_t *state, ActionType type, uint64_t key, const char *str, bool has_op)
|
||||
void set_partial_state_action(script_partial_state_t *state, ActionType type, const char *str, unsigned num_ops)
|
||||
{
|
||||
MDEBUG("action: " << get_action_name(type));
|
||||
state->actions.push_back({});
|
||||
Action &a = state->actions.back().action;
|
||||
a.type = type;
|
||||
a.key = key;
|
||||
if (str)
|
||||
a.str = str;
|
||||
if (has_op)
|
||||
if (state->operands.size() < num_ops)
|
||||
{
|
||||
if (state->operands.size() < 1)
|
||||
{
|
||||
tfscript_error("Action needs at least one operand");
|
||||
return;
|
||||
}
|
||||
a.op = std::move(state->operands.back());
|
||||
state->operands.pop_back();
|
||||
tfscript_error("Action needs more operands");
|
||||
return;
|
||||
}
|
||||
for (unsigned int i = 0; i < num_ops; ++i)
|
||||
a.ops.push_back(std::move(state->operands[state->operands.size() - num_ops + i]));
|
||||
for (unsigned int i = 0; i < num_ops; ++i)
|
||||
state->operands.pop_back();
|
||||
}
|
||||
|
||||
void set_partial_state_action_pick_count_up(script_partial_state_t *state)
|
||||
|
@ -119,28 +119,28 @@ action: action_percent
|
||||
action_percent: PERCENT UNSIGNED_NUMBER action { set_partial_state_action_percent(state, $2); }
|
||||
;
|
||||
|
||||
action_award_gold: AWARD GOLD operand { set_partial_state_action(state, action_award_gold, $3, NULL, true); }
|
||||
action_award_gold: AWARD GOLD operand { set_partial_state_action(state, action_award_gold, NULL, 1); }
|
||||
;
|
||||
|
||||
action_award_item: AWARD ITEM UNSIGNED_NUMBER operand { set_partial_state_action(state, action_award_item, $3, NULL, true); }
|
||||
action_award_item: AWARD ITEM operand operand { set_partial_state_action(state, action_award_item, NULL, 2); }
|
||||
;
|
||||
|
||||
action_pay_gold: PAY GOLD operand { set_partial_state_action(state, action_pay_gold, $3, NULL, true); }
|
||||
action_pay_gold: PAY GOLD operand { set_partial_state_action(state, action_pay_gold, NULL, 1); }
|
||||
;
|
||||
|
||||
action_pay_item: PAY ITEM UNSIGNED_NUMBER operand { set_partial_state_action(state, action_pay_item, $3, NULL, true); }
|
||||
action_pay_item: PAY ITEM operand operand { set_partial_state_action(state, action_pay_item, NULL, 2); }
|
||||
;
|
||||
|
||||
action_consume: CONSUME ITEM UNSIGNED_NUMBER operand { set_partial_state_action(state, action_consume_item, $3, NULL, true); }
|
||||
action_consume: CONSUME ITEM operand operand { set_partial_state_action(state, action_consume_item, NULL, 2); }
|
||||
;
|
||||
|
||||
action_set_player_variable: SET PLAYER STRING operand { set_partial_state_action(state, action_set_player_variable, 0, $3, true); }
|
||||
action_set_player_variable: SET PLAYER STRING operand { set_partial_state_action(state, action_set_player_variable, $3, 1); }
|
||||
;
|
||||
|
||||
action_set_global_variable: SET GLOBAL STRING operand { set_partial_state_action(state, action_set_global_variable, 0, $3, true); }
|
||||
action_set_global_variable: SET GLOBAL STRING operand { set_partial_state_action(state, action_set_global_variable, $3, 1); }
|
||||
;
|
||||
|
||||
action_set_local_variable: SET LOCAL STRING operand { set_partial_state_action(state, action_set_local_variable, 0, $3, true); }
|
||||
action_set_local_variable: SET LOCAL STRING operand { set_partial_state_action(state, action_set_local_variable, $3, 1); }
|
||||
;
|
||||
|
||||
action_pick: PICK '{' pick_actions '}' { set_partial_state_action_pick(state); }
|
||||
@ -153,7 +153,7 @@ pick_actions: pick_actions pick_action { set_partial_state_action_pick_count_up(
|
||||
pick_action: WEIGHT UNSIGNED_NUMBER action { set_partial_state_action_set_weight(state, $2); }
|
||||
;
|
||||
|
||||
action_none: NONE { set_partial_state_action(state, action_none, 0, NULL, false); }
|
||||
action_none: NONE { set_partial_state_action(state, action_none, NULL, 0); }
|
||||
;
|
||||
|
||||
reserves: RESERVES '{' reserves_contents '}'
|
||||
@ -163,10 +163,10 @@ reserves_contents: reserves_contents reserves_content
|
||||
| {}
|
||||
;
|
||||
|
||||
reserves_content: OWNER GOLD MONEY { set_partial_state_gold_reserve(state, false, $3); }
|
||||
| OWNER ITEM UNSIGNED_NUMBER UNSIGNED_NUMBER { set_partial_state_item_reserve(state, false, $3, $4); }
|
||||
| PLAYER GOLD MONEY { set_partial_state_gold_reserve(state, true, $3); }
|
||||
| PLAYER ITEM UNSIGNED_NUMBER UNSIGNED_NUMBER { set_partial_state_item_reserve(state, true, $3, $4); }
|
||||
reserves_content: OWNER GOLD operand { set_partial_state_gold_reserve(state, false); }
|
||||
| OWNER ITEM operand operand { set_partial_state_item_reserve(state, false); }
|
||||
| PLAYER GOLD operand { set_partial_state_gold_reserve(state, true); }
|
||||
| PLAYER ITEM operand operand { set_partial_state_item_reserve(state, true); }
|
||||
;
|
||||
|
||||
state: STATE STRING '{' state_contents '}' { set_partial_state_state(state, $2); }
|
||||
|
@ -352,7 +352,7 @@ public:
|
||||
bool get_invitation_status(const std::string &pkey, bool &used, bool &balance_ok) const;
|
||||
bool generate_invitation(uint64_t amount, uint64_t expiration, std::string &invitation) const;
|
||||
std::vector<uint64_t> get_item_count(const std::vector<uint32_t> &id) const;
|
||||
bool get_cc_scripts(uint32_t account, uint32_t city, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner) const;
|
||||
bool get_cc_scripts(uint32_t account, uint32_t city, uint32_t flag, uint8_t dx, uint8_t dy, uint16_t h, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner) const;
|
||||
bool get_cc_script(uint32_t script, std::string &name, std::string &icon, std::string &desc, std::string &blob) const;
|
||||
bool get_cc_script_state(uint32_t account, uint32_t script, uint32_t state, uint32_t city, std::string &script_name, std::string &ui, std::string &text, std::string &image, std::vector<std::tuple<uint32_t, std::string, std::string>> &choices, std::string &choices_ui, std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides) const;
|
||||
bool get_cc_global_variable(const std::string &name, uint64_t &value) const;
|
||||
@ -1232,9 +1232,9 @@ std::vector<uint64_t> GameWalletInternal::get_item_count(const std::vector<uint3
|
||||
return counts;
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_scripts(uint32_t account, uint32_t city, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner) const
|
||||
bool GameWalletInternal::get_cc_scripts(uint32_t account, uint32_t city, uint32_t flag, uint8_t dx, uint8_t dy, uint16_t h, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner) const
|
||||
{
|
||||
return w->get_cc_scripts(account, city, include_requirements, scripts, script, owner);
|
||||
return w->get_cc_scripts(account, city, flag, dx, dy, h, include_requirements, scripts, script, owner);
|
||||
}
|
||||
|
||||
bool GameWalletInternal::get_cc_script(uint32_t script, std::string &name, std::string &icon, std::string &desc, std::string &blob) const
|
||||
@ -1963,7 +1963,12 @@ std::vector<uint64_t> GameWallet::get_item_count(const std::vector<uint32_t> &id
|
||||
|
||||
bool GameWallet::get_cc_scripts(uint32_t account, uint32_t city, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner) const
|
||||
{
|
||||
return internal->get_cc_scripts(account, city, include_requirements, scripts, script, owner);
|
||||
return internal->get_cc_scripts(account, city, 0, 0, 0, 0, include_requirements, scripts, script, owner);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_scripts(uint32_t account, uint32_t city, uint32_t flag, uint8_t dx, uint8_t dy, uint16_t h, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner) const
|
||||
{
|
||||
return internal->get_cc_scripts(account, city, flag, dx, dy, h, true, scripts, script, owner);
|
||||
}
|
||||
|
||||
bool GameWallet::get_cc_script(uint32_t script, std::string &name, std::string &icon, std::string &desc, std::string &blob) const
|
||||
|
@ -99,6 +99,7 @@ public:
|
||||
bool get_invitation_status(const std::string &pkey, bool &used, bool &balance_ok) const;
|
||||
std::vector<uint64_t> get_item_count(const std::vector<uint32_t> &id) const;
|
||||
bool get_cc_scripts(uint32_t account, uint32_t city, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script = 0, uint32_t owner = 0) const;
|
||||
bool get_cc_scripts(uint32_t account, uint32_t city, uint32_t flag, uint8_t dx, uint8_t dy, uint16_t h, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script = 0, uint32_t owner = 0) const;
|
||||
bool get_cc_script(uint32_t script, std::string &name, std::string &icon, std::string &desc, std::string &blob) const;
|
||||
bool get_cc_script_state(uint32_t account, uint32_t script, uint32_t state, uint32_t city, std::string &script_name, std::string &ui, std::string &text, std::string &image, std::vector<std::tuple<uint32_t, std::string, std::string>> &choices, std::string &choices_ui, std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides) const;
|
||||
bool get_cc_global_variable(const std::string &name, uint64_t &value) const;
|
||||
|
@ -62,7 +62,7 @@ bool UIRunestoneMessageDialog::SetupScriptWidget(const std::shared_ptr<GameWalle
|
||||
return false;
|
||||
|
||||
std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> scripts;
|
||||
if (!w->get_cc_scripts(game->playerState.id, game->cityState.id, true, scripts, runestone.script, flag->owner))
|
||||
if (!w->get_cc_scripts(game->playerState.id, game->cityState.id, runestone.flag, runestone.x, runestone.y, runestone.h, scripts, runestone.script, flag->owner))
|
||||
return false;
|
||||
if (scripts.size() != 1)
|
||||
return false;
|
||||
|
@ -5077,7 +5077,20 @@ namespace cryptonote
|
||||
}
|
||||
std::vector<std::pair<std::string, bool>> reqs;
|
||||
const uint32_t owner = sd.is_public ? req.owner : sd.owner == 0 ? GAME_ACCOUNT : sd.owner;
|
||||
available = cc::script::is_available(db, script, req.account, owner, req.city, req.include_requirements ? &reqs : NULL);
|
||||
const std::vector<std::tuple<uint8_t, uint32_t, std::string>> overrides = cc::script::get_script_overrides(script);
|
||||
std::vector<std::tuple<uint8_t, uint32_t, std::string>> runestone_overrides;
|
||||
if (req.flag)
|
||||
{
|
||||
cc::runestone_t runestone;
|
||||
if (!db.get_cc_runestone(req.flag, req.dx, req.dy, req.h, runestone))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Error getting runestone";
|
||||
return false;
|
||||
}
|
||||
runestone_overrides = std::move(runestone.overrides);
|
||||
}
|
||||
available = cc::script::is_available(db, script, overrides, runestone_overrides, req.account, owner, req.city, req.include_requirements ? &reqs : NULL);
|
||||
requirements.reserve(reqs.size());
|
||||
for (const auto &e: reqs)
|
||||
requirements.push_back({e.first, e.second});
|
||||
|
@ -4320,6 +4320,10 @@ namespace cryptonote
|
||||
uint32_t account;
|
||||
uint32_t owner;
|
||||
uint32_t city;
|
||||
uint32_t flag;
|
||||
uint8_t dx;
|
||||
uint8_t dy;
|
||||
uint16_t h;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_OPT(first_script, (uint32_t)0)
|
||||
@ -4329,6 +4333,10 @@ namespace cryptonote
|
||||
KV_SERIALIZE_OPT(account, (uint32_t)0)
|
||||
KV_SERIALIZE_OPT(owner, (uint32_t)0)
|
||||
KV_SERIALIZE_OPT(city, (uint32_t)0)
|
||||
KV_SERIALIZE_OPT(flag, (uint32_t)0)
|
||||
KV_SERIALIZE_OPT(dx, (uint8_t)0)
|
||||
KV_SERIALIZE_OPT(dy, (uint8_t)0)
|
||||
KV_SERIALIZE_OPT(h, (uint16_t)0)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
@ -10,10 +10,13 @@
|
||||
#include "cc/cc_blockchain_state_proxy.h"
|
||||
#include "cc/cc_script.h"
|
||||
|
||||
#define PLAYER_ACCOUNT 1
|
||||
|
||||
class DummyDB: public cryptonote::BaseTestDB
|
||||
{
|
||||
public:
|
||||
DummyDB() {}
|
||||
virtual bool get_cc_account_data(uint32_t id, cryptonote::cc_account_data_t &ad) const override { ad = {}; ad.id = id; return true; }
|
||||
};
|
||||
|
||||
struct delta_t
|
||||
@ -160,8 +163,14 @@ static void explore_script(const cc::script::ScriptHandle &script, const std::ve
|
||||
{
|
||||
DummyDB db;
|
||||
TestStateProxy proxy(db);
|
||||
|
||||
const auto overrides = cc::script::get_script_overrides(script);
|
||||
for (const auto &e: overrides)
|
||||
if (std::get<0>(e) == cc::script::override_local)
|
||||
db.set_cc_account_script_variable(PLAYER_ACCOUNT, std::get<2>(e), std::get<1>(e), true);
|
||||
|
||||
cryptonote::cc_command_start_script_t start_script;
|
||||
start_script.cc_account = 0;
|
||||
start_script.cc_account = PLAYER_ACCOUNT;
|
||||
start_script.script = 0;
|
||||
start_script.city = 0;
|
||||
cc::game_events_t events;
|
||||
@ -200,7 +209,7 @@ static void explore_script(const cc::script::ScriptHandle &script, const std::ve
|
||||
DummyDB db;
|
||||
TestStateProxy proxy(db);
|
||||
cryptonote::cc_command_script_choice_t script_choice;
|
||||
script_choice.cc_account = 0;
|
||||
script_choice.cc_account = PLAYER_ACCOUNT;
|
||||
script_choice.script = 0;
|
||||
script_choice.state = state;
|
||||
script_choice.city = 0;
|
||||
@ -233,7 +242,9 @@ static void explore_script(const cc::script::ScriptHandle &script, const std::ve
|
||||
delta_map_t script_reserve;
|
||||
uint64_t reserved_owner_balance, reserved_player_balance;
|
||||
std::map<uint32_t, uint32_t> reserved_owner_items, reserved_player_items;
|
||||
cc::script::get_reserves(script, reserved_owner_balance, reserved_owner_items, reserved_player_balance, reserved_player_items);
|
||||
DummyDB db;
|
||||
const auto overrides = cc::script::get_script_overrides(script);
|
||||
cc::script::get_reserves(db, script, overrides, {}, reserved_owner_balance, reserved_owner_items, reserved_player_balance, reserved_player_items, PLAYER_ACCOUNT, owner, 0);
|
||||
script_reserve[0].balance = - reserved_player_balance;
|
||||
for (const auto &e: reserved_player_items)
|
||||
script_reserve[0].items[e.first] = (int32_t)-e.second;
|
||||
@ -310,13 +321,14 @@ int main(int argc, char **argv)
|
||||
{
|
||||
std::string ui, text, image, choices_ui;
|
||||
std::vector<std::tuple<uint32_t, std::string, std::string>> choices;
|
||||
if (!cc::script::get_state(proxy, script, 0, state, 0, ui, text, image, choices, choices_ui))
|
||||
if (!cc::script::get_state(proxy, script, PLAYER_ACCOUNT, state, 0, ui, text, image, choices, choices_ui))
|
||||
break;
|
||||
repr.push_back(std::make_tuple(ui, text, image, choices_ui, choices));
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, bool>> requirements;
|
||||
is_available(db, script, 0, cc::script::get_script_owner(script), 0, &requirements);
|
||||
const auto overrides = cc::script::get_script_overrides(script);
|
||||
is_available(db, script, overrides, {}, PLAYER_ACCOUNT, cc::script::get_script_owner(script), 0, &requirements);
|
||||
printf("%zu preconditions\n", requirements.size());
|
||||
for (size_t r = 0; r < requirements.size(); ++r)
|
||||
printf(" %s\n", requirements[r].first.c_str());
|
||||
|
@ -1087,7 +1087,7 @@ private:
|
||||
bool get_cc_invitation_status(const std::string &pkey, bool &used, bool &balance_ok);
|
||||
bool get_cc_item_count(const std::vector<uint32_t> &id, std::vector<uint64_t> &count);
|
||||
bool get_cc_nonces(uint32_t num_nonces, std::vector<uint64_t> &nonces);
|
||||
bool get_cc_scripts(uint32_t account, uint32_t city, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script = 0, uint32_t owner = 0);
|
||||
bool get_cc_scripts(uint32_t account, uint32_t city, uint32_t flag, uint8_t dx, uint8_t dy, uint16_t h, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script = 0, uint32_t owner = 0);
|
||||
bool get_cc_script_data(uint32_t script, std::string &name, std::string &icon, std::string &desc, std::string &blob);
|
||||
bool get_cc_script_state(uint32_t account, uint32_t script, uint32_t state, uint32_t city, std::string &script_name, std::string &ui, std::string &text, std::string &image, std::vector<std::tuple<uint32_t, std::string, std::string>> &choices, std::string &choices_ui, std::vector<std::tuple<uint8_t, uint32_t, std::string>> &overrides);
|
||||
bool get_cc_global_variable(const std::string &name, uint64_t &value);
|
||||
|
@ -768,7 +768,7 @@ bool wallet2::get_cc_nonces(uint32_t num_nonces, std::vector<uint64_t> &nonces)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet2::get_cc_scripts(uint32_t account, uint32_t city, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner)
|
||||
bool wallet2::get_cc_scripts(uint32_t account, uint32_t city, uint32_t flag, uint8_t dx, uint8_t dy, uint16_t h, bool include_requirements, std::vector<std::tuple<uint32_t, uint32_t, bool, std::string, std::string, std::string, bool, std::vector<std::pair<std::string, bool>>>> &scripts, uint32_t script, uint32_t owner)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_CC_GET_SCRIPTS::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_CC_GET_SCRIPTS::response res;
|
||||
@ -780,6 +780,10 @@ bool wallet2::get_cc_scripts(uint32_t account, uint32_t city, bool include_requi
|
||||
req.account = account;
|
||||
req.owner = owner;
|
||||
req.city = city;
|
||||
req.flag = flag;
|
||||
req.dx = dx;
|
||||
req.dy = dy;
|
||||
req.h = h;
|
||||
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = invoke_http_json_rpc("/json_rpc", "cc_get_scripts", req, res);
|
||||
|
Loading…
Reference in New Issue
Block a user