add a new command to destroy owned items

This commit is contained in:
Crypto City 2020-04-04 19:02:44 +00:00
parent 31c0293151
commit 3891353d7e
22 changed files with 406 additions and 2 deletions

View File

@ -34,6 +34,7 @@ TBLayout: axis: y, distribution-position: "left top", distribution: "available"
TBButton: skin: "TBButton.column", text: "Research", id: "actions-research"
TBButton: skin: "TBButton.column", text: "New item" id: "actions-new-item"
TBButton: skin: "TBButton.column", text: "Dividend" id: "actions-dividend"
TBButton: skin: "TBButton.column", text: "Destroy items", id: "actions-destroy-items"
TBButton: skin: "TBButton.column", text: "Ignore" id: "actions-ignore"
TBButton: skin: "TBButton.column", text: "Leaderboards" id: "actions-leaderboards"
TBButton: skin: "TBButton.column", text: "Chat", id: "actions-chat"

View File

@ -1927,6 +1927,7 @@ public:
virtual void delete_cc_custom_item(uint32_t id) = 0;
virtual bool get_cc_custom_item_data(uint32_t id, cc::cc_custom_item_t &cid) const = 0;
virtual void set_cc_custom_item_ignore(uint32_t id, bool ignore) = 0;
virtual void set_cc_custom_item_amount(uint32_t id, uint32_t amount) = 0;
virtual bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const = 0;
virtual uint32_t allocate_new_cc_event_badge(const std::string &name, const std::string &desc) = 0;

View File

@ -7155,6 +7155,33 @@ void BlockchainLMDB::set_cc_custom_item_ignore(uint32_t id, bool ignore)
throw0(DB_ERROR(lmdb_error("Failed to add custom iten data to db transaction: ", result).c_str()));
}
void BlockchainLMDB::set_cc_custom_item_amount(uint32_t id, uint32_t amount)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_cursors *m_cursors = &m_wcursors;
CURSOR(cc_custom_items)
// find item id
MDB_val_set(k, id);
MDB_val v;
int result = mdb_cursor_get(m_cur_cc_custom_items, &k, &v, MDB_SET);
if (result)
throw0(DB_ERROR(lmdb_error("Item " + std::to_string(id) + " not found: ", result).c_str()));
if (v.mv_size < sizeof(mdb_cc_custom_item_data_t))
throw0(DB_ERROR("Unexpected custom item data size"));
mdb_cc_custom_item_data_t cid = *(const mdb_cc_custom_item_data_t*)v.mv_data;
cid.amount = amount;
v.mv_data = (void*)&cid;
v.mv_size = sizeof(cid);
result = mdb_cursor_put(m_cur_cc_custom_items, &k, &v, 0);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to add custom iten data to db transaction: ", result).c_str()));
}
bool BlockchainLMDB::for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);

View File

@ -548,6 +548,7 @@ private:
void delete_cc_custom_item(uint32_t id);
bool get_cc_custom_item_data(uint32_t id, cc::cc_custom_item_t &cid) const;
void set_cc_custom_item_ignore(uint32_t id, bool ignore);
void set_cc_custom_item_amount(uint32_t id, uint32_t amount);
bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const;
uint32_t allocate_new_cc_event_badge(const std::string &name, const std::string &desc);

View File

@ -243,6 +243,7 @@ public:
virtual void delete_cc_custom_item(uint32_t id) {}
virtual bool get_cc_custom_item_data(uint32_t id, cc::cc_custom_item_t &cid) const { return false; }
virtual void set_cc_custom_item_ignore(uint32_t id, bool ignore) {}
virtual void set_cc_custom_item_amount(uint32_t id, uint32_t amount) {}
virtual bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const { return true; }
virtual uint32_t allocate_new_cc_event_badge(const std::string &name, const std::string &desc) { return 0; }

View File

@ -35,6 +35,7 @@ set(cc_sources
cc_command_handler_chat.cpp
cc_command_handler_create_account.cpp
cc_command_handler_demolish.cpp
cc_command_handler_destroy_items.cpp
cc_command_handler_dividend.cpp
cc_command_handler_event_badge.cpp
cc_command_handler_found_city.cpp
@ -72,6 +73,7 @@ set(cc_headers
cc_command_handler_chat.h
cc_command_handler_create_account.h
cc_command_handler_demolish.h
cc_command_handler_destroy_items.h
cc_command_handler_dividend.h
cc_command_handler_event_badge.h
cc_command_handler_found_city.h

View File

@ -45,6 +45,7 @@
#include "cc_command_handler_chat.h"
#include "cc_command_handler_create_account.h"
#include "cc_command_handler_demolish.h"
#include "cc_command_handler_destroy_items.h"
#include "cc_command_handler_dividend.h"
#include "cc_command_handler_found_city.h"
#include "cc_command_handler_game_update.h"
@ -1705,6 +1706,7 @@ static cc_command_handler &get_cc_command(const cryptonote::cc_command_t &cmd)
cc_command_handler &operator()(const cryptonote::cc_command_chat_t &cmd) const { return cc_command_handler_chat::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_create_account_t &cmd) const { return cc_command_handler_create_account::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_demolish_t &cmd) const { return cc_command_handler_demolish::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_destroy_items_t &cmd) const { return cc_command_handler_destroy_items::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_dividend_t &cmd) const { return cc_command_handler_dividend::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_event_badge_t &cmd) const { return cc_command_handler_event_badge::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_found_city_t &cmd) const { return cc_command_handler_found_city::instance; }

View File

@ -0,0 +1,116 @@
// Copyright (c) 2019, Crypto City
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "blockchain_db/blockchain_db.h"
#include "cc/cc.h"
#include "cc/cc_custom_item.h"
#include "cc_command_handler_destroy_items.h"
namespace cc
{
cc_command_handler_destroy_items cc_command_handler_destroy_items::instance;
void cc_command_handler_destroy_items::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_destroy_items::get_cost(const cryptonote::cc_command_t &cmd) const
{
return 0;
}
bool cc_command_handler_destroy_items::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, cryptonote::tx_verification_context &tvc) const
{
const cryptonote::cc_command_destroy_items_t &destroy_items = boost::get<cryptonote::cc_command_destroy_items_t>(cmd);
const uint64_t blockchain_height = db.height();
CHECK_COMMAND_SET(destroy_items.item_id != 0 && destroy_items.item_id < NUM_ITEMS, tvc.m_cc_bad_item, "destroy_items refers to invalid item type");
CHECK_COMMAND_SET(cc::is_item_enabled(destroy_items.item_id, blockchain_height), tvc.m_cc_bad_item, "destroy_items refers to disabled item type");
CHECK_COMMAND_SET(destroy_items.amount > 0, tvc.m_cc_bad_amount, "destroy_items refers to 0 amount");
std::map<uint32_t, uint32_t> item_balances;
CHECK_AND_ASSERT_MES(db.get_cc_account_item_balances(destroy_items.cc_account, item_balances), false, "Failed to get owner item balances");
if (destroy_items.item_id >= ITEM_FIRST_USER && destroy_items.item_id <= ITEM_LAST_USER)
{
cc::cc_custom_item_t cid;
CHECK_AND_ASSERT_MES(db.get_cc_custom_item_data(destroy_items.item_id, cid), false, "Failed to get custom item data");
CHECK_COMMAND_SET(cid.amount >= destroy_items.amount, tvc.m_cc_bad_amount, "Amount is higher than exists");
}
CHECK_COMMAND_SET(item_balances[destroy_items.item_id] >= destroy_items.amount, tvc.m_cc_balance, "Destroying more items of type " << destroy_items.item_id << " than owned");
return true;
}
bool cc_command_handler_destroy_items::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const
{
const cryptonote::cc_command_destroy_items_t &destroy_items = boost::get<cryptonote::cc_command_destroy_items_t>(cmd);
std::map<uint32_t, uint32_t> item_balances;
CHECK_AND_ASSERT_MES(db.get_cc_account_item_balances(destroy_items.cc_account, item_balances), false, "Failed to get owner item balances");
CHECK_AND_ASSERT_MES(item_balances[destroy_items.item_id] >= destroy_items.amount, false, "Destroying more items of type " << destroy_items.item_id << " than owned");
item_balances[destroy_items.item_id] -= destroy_items.amount;
db.set_cc_account_item_balances(destroy_items.cc_account, item_balances);
if (destroy_items.item_id >= ITEM_FIRST_USER && destroy_items.item_id <= ITEM_LAST_USER)
{
cc::cc_custom_item_t cid;
CHECK_AND_ASSERT_MES(db.get_cc_custom_item_data(destroy_items.item_id, cid), false, "Failed to get custom item data");
CHECK_AND_ASSERT_MES(cid.amount >= destroy_items.amount, false, "Amount is higher than exists");
db.set_cc_custom_item_amount(destroy_items.item_id, cid.amount - destroy_items.amount);
}
return true;
}
bool cc_command_handler_destroy_items::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const
{
const cryptonote::cc_command_destroy_items_t &destroy_items = boost::get<cryptonote::cc_command_destroy_items_t>(cmd);
std::map<uint32_t, uint32_t> item_balances;
CHECK_AND_ASSERT_MES(db.get_cc_account_item_balances(destroy_items.cc_account, item_balances), false, "Failed to get owner item balances");
CHECK_AND_ASSERT_MES(item_balances[destroy_items.item_id] <= std::numeric_limits<uint32_t>::max() - destroy_items.amount, false, "Item balance would overflow");
item_balances[destroy_items.item_id] += destroy_items.amount;
db.set_cc_account_item_balances(destroy_items.cc_account, item_balances);
if (destroy_items.item_id >= ITEM_FIRST_USER && destroy_items.item_id <= ITEM_LAST_USER)
{
cc::cc_custom_item_t cid;
CHECK_AND_ASSERT_MES(db.get_cc_custom_item_data(destroy_items.item_id, cid), false, "Failed to get custom item data");
CHECK_AND_ASSERT_MES(cid.amount <= std::numeric_limits<uint32_t>::max() - destroy_items.amount, false, "Amount would overflow");
db.set_cc_custom_item_amount(destroy_items.item_id, cid.amount + destroy_items.amount);
}
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_destroy_items: public cc_command_handler
{
public:
virtual void get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const;
virtual uint64_t get_cost(const cryptonote::cc_command_t &cmd) const;
virtual bool check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, cryptonote::tx_verification_context &tvc) const;
virtual bool execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const;
virtual bool revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd) const;
static cc_command_handler_destroy_items instance;
};
}

View File

@ -53,6 +53,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_chat_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_create_account_t &cmd) const { return NULL; }
const cc_command_base_t *operator()(const cryptonote::cc_command_demolish_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_destroy_items_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_dividend_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_event_badge_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_found_city_t &cmd) const { return &cmd; }
@ -84,6 +85,7 @@ cc_command_base_t *get_cc_command_base(cc_command_t &cmd)
cc_command_base_t *operator()(cryptonote::cc_command_chat_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_create_account_t &cmd) const { return NULL; }
cc_command_base_t *operator()(cryptonote::cc_command_demolish_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_destroy_items_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_dividend_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_event_badge_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_found_city_t &cmd) const { return &cmd; }

View File

@ -510,6 +510,18 @@ namespace cryptonote
END_SERIALIZE()
};
struct cc_command_destroy_items_t: public cc_command_base_t
{
uint32_t item_id;
uint32_t amount;
BEGIN_SERIALIZE_OBJECT()
FIELDS(*static_cast<cc_command_base_t*>(this))
VARINT_FIELD(item_id)
VARINT_FIELD(amount)
END_SERIALIZE()
};
struct cc_command_game_update_t
{
struct flag_t
@ -706,7 +718,8 @@ namespace cryptonote
cc_command_dividend_t,
cc_command_ignore_t,
cc_command_event_badge_t,
cc_command_resize_flag_t
cc_command_resize_flag_t,
cc_command_destroy_items_t
> cc_command_t;
cc_command_base_t *get_cc_command_base(cc_command_t &cmd);
@ -820,6 +833,7 @@ CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_dividend_t, (uint8_t)0x13)
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_ignore_t, (uint8_t)0x14);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_event_badge_t, (uint8_t)0x15);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_resize_flag_t, (uint8_t)0x16);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_destroy_items_t, (uint8_t)0x17);
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");
@ -844,6 +858,7 @@ CC_VARIANT_TAG(json_archive, cryptonote::cc_command_dividend_t, (const char*)"di
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_ignore_t, (const char*)"ignore");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_event_badge_t, (const char*)"event_badge");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_resize_flag_t, (const char*)"resize_flag");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_destroy_items_t, (const char*)"destroy_items");
VARIANT_TAG(debug_archive, cryptonote::cc_command_none_t, "none");
VARIANT_TAG(debug_archive, cryptonote::cc_command_create_account_t, "create_account");
@ -868,3 +883,4 @@ VARIANT_TAG(debug_archive, cryptonote::cc_command_dividend_t, "dividend");
VARIANT_TAG(debug_archive, cryptonote::cc_command_ignore_t, "ignore");
VARIANT_TAG(debug_archive, cryptonote::cc_command_event_badge_t, "event_badge");
VARIANT_TAG(debug_archive, cryptonote::cc_command_resize_flag_t, "resize_flag");
VARIANT_TAG(debug_archive, cryptonote::cc_command_destroy_items_t, "destroy_items");

View File

@ -289,6 +289,11 @@ bool GameState::process_demolish(const cryptonote::cc_command_demolish_t &cmd, c
return true;
}
bool GameState::process_destroy_items(const cryptonote::cc_command_destroy_items_t &cmd, const std::shared_ptr<GameWallet> &w)
{
return true;
}
bool GameState::process_buy_items(const cryptonote::cc_command_buy_items_t &cmd, const std::shared_ptr<GameWallet> &w)
{
return true;
@ -459,6 +464,7 @@ bool GameState::process_command(const cryptonote::cc_command_t &cmd, const std::
bool operator()(const cryptonote::cc_command_chat_t &cmd) const { return self.process_chat(cmd, w); }
bool operator()(const cryptonote::cc_command_create_account_t &cmd) const { return self.process_create_account(cmd, w); }
bool operator()(const cryptonote::cc_command_demolish_t &cmd) const { return self.process_demolish(cmd, w); }
bool operator()(const cryptonote::cc_command_destroy_items_t &cmd) const { return self.process_destroy_items(cmd, w); }
bool operator()(const cryptonote::cc_command_dividend_t &cmd) const { return self.process_dividend(cmd, w); }
bool operator()(const cryptonote::cc_command_found_city_t &cmd) const { return self.process_found_city(cmd, w); }
bool operator()(const cryptonote::cc_command_game_update_t &cmd) const { return self.process_game_update(cmd, w); }

View File

@ -140,6 +140,7 @@ private:
bool process_chat(const cryptonote::cc_command_chat_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_create_account(const cryptonote::cc_command_create_account_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_demolish(const cryptonote::cc_command_demolish_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_destroy_items(const cryptonote::cc_command_destroy_items_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_dividend(const cryptonote::cc_command_dividend_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_found_city(const cryptonote::cc_command_found_city_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_game_update(const cryptonote::cc_command_game_update_t &cmd, const std::shared_ptr<GameWallet> &w);

View File

@ -158,6 +158,7 @@ public:
void HandleBuy(StringHash eventType, VariantMap& eventData);
void HandleSell(StringHash eventType, VariantMap& eventData);
void HandleAssignItems(StringHash eventType, VariantMap& eventData);
void HandleDestroyItems(StringHash eventType, VariantMap& eventData);
void HandleAddBlock(StringHash eventType, VariantMap& eventData);
void HandleRemoveBlock(StringHash eventType, VariantMap& eventData);
void HandleDemolish(StringHash eventType, VariantMap& eventData);
@ -723,6 +724,7 @@ void CryptoCityUrho3D::SetupUI()
SubscribeToEvent(ui, E_CRYPTOCITY_BUY, URHO3D_HANDLER(CryptoCityUrho3D, HandleBuy));
SubscribeToEvent(ui, E_CRYPTOCITY_SELL, URHO3D_HANDLER(CryptoCityUrho3D, HandleSell));
SubscribeToEvent(ui, E_CRYPTOCITY_ASSIGN_ITEMS, URHO3D_HANDLER(CryptoCityUrho3D, HandleAssignItems));
SubscribeToEvent(ui, E_CRYPTOCITY_DESTROY_ITEMS, URHO3D_HANDLER(CryptoCityUrho3D, HandleDestroyItems));
SubscribeToEvent(ui, E_CRYPTOCITY_ADD_BLOCK, URHO3D_HANDLER(CryptoCityUrho3D, HandleAddBlock));
SubscribeToEvent(ui, E_CRYPTOCITY_REMOVE_BLOCK, URHO3D_HANDLER(CryptoCityUrho3D, HandleRemoveBlock));
SubscribeToEvent(ui, E_CRYPTOCITY_DEMOLISH_FLAG, URHO3D_HANDLER(CryptoCityUrho3D, HandleDemolish));
@ -2054,7 +2056,7 @@ void CryptoCityUrho3D::HandleAssignItems(StringHash eventType, VariantMap& event
cryptonote::cc_command_assign_items_t cmd;
cmd.cc_account = wallet->get_cc_account();
cmd.flag = flag->id;
const std::vector<std::pair<uint32_t, uint32_t>> *v = (const std::vector<std::pair<uint32_t, uint32_t>>*)eventData[BuyItems::P_QUANTITIES].GetVoidPtr();
const std::vector<std::pair<uint32_t, uint32_t>> *v = (const std::vector<std::pair<uint32_t, uint32_t>>*)eventData[AssignItems::P_QUANTITIES].GetVoidPtr();
for (const auto &q: *v)
{
cryptonote::cc_command_assign_items_t::item_t e;
@ -2065,6 +2067,24 @@ void CryptoCityUrho3D::HandleAssignItems(StringHash eventType, VariantMap& event
wallet->send_command(cmd);
}
void CryptoCityUrho3D::HandleDestroyItems(StringHash eventType, VariantMap& eventData)
{
if (!wallet || !wallet->wallet())
{
new MessageBox(context_, "No wallet loaded - load a wallet to be able to destroy items");
return;
}
const std::vector<std::pair<uint32_t, uint32_t>> *v = (const std::vector<std::pair<uint32_t, uint32_t>>*)eventData[DestroyItems::P_QUANTITIES].GetVoidPtr();
for (const auto &q: *v)
{
cryptonote::cc_command_destroy_items_t cmd;
cmd.cc_account = wallet->get_cc_account();
cmd.item_id = q.first;
cmd.amount = q.second;
wallet->send_command(cmd);
}
}
void CryptoCityUrho3D::AddBlock(bool use_selection)
{
UnsetFocus();

View File

@ -276,6 +276,7 @@ void UIUrho3D::Update(uint32_t mouse_x, uint32_t mouse_y, uint32_t sx0, uint32_t
EnableWidget("actions-trade", hasAccount);
EnableWidget("actions-research", hasAccount);
EnableWidget("actions-assign-items", hasAccount && hasFlagSelected);
EnableWidget("actions-destroy-items", hasAccount);
EnableWidget("actions-approve-build", hasFlagSelected && building);
EnableWidget("actions-abandon-build", hasFlagSelected && building);
@ -953,6 +954,14 @@ void UIUrho3D::HandleAssignItems(StringHash eventType, VariantMap& eventData)
});
}
void UIUrho3D::HandleDestroyItems(StringHash eventType, VariantMap& eventData)
{
auto *d = new UISelectItemsDialog(context_, gameState, "Select items to destroy");
SubscribeToEvent(d, E_SELECT_ITEMS_OKAYED, [this](StringHash eventType, VariantMap& eventData) {
SendEvent(E_CRYPTOCITY_DESTROY_ITEMS, eventData);
});
}
void UIUrho3D::HandleMaterialSelected(StringHash eventType, VariantMap& eventData, bool player)
{
const TBSelectList *list = player ? playerMaterialList : flagItemTypeList;
@ -1316,6 +1325,7 @@ void UIUrho3D::HandleTBMessage(StringHash eventType, VariantMap& eventData)
CONNECT("actions-trade", HandleTrade);
CONNECT("actions-research", HandleResearch);
CONNECT("actions-assign-items", HandleAssignItems);
CONNECT("actions-destroy-items", HandleDestroyItems);
CONNECT("actions-demolish", HandleDemolish);
CONNECT("actions-undo", HandleUndo);
CONNECT("actions-redo", HandleRedo);

View File

@ -66,6 +66,7 @@ URHO3D_EVENT(E_CRYPTOCITY_BUY_ITEMS, BuyItems) { URHO3D_PARAM(P_QUANTITIES, Quan
URHO3D_EVENT(E_CRYPTOCITY_BUY, Buy) { URHO3D_PARAM(P_TYPE, Type); URHO3D_PARAM(P_ID, ID); URHO3D_PARAM(P_AMOUNT, Amount); URHO3D_PARAM(P_PRICE, Price); URHO3D_PARAM(P_ACCRUAL_START_HEIGHT, AccrualStartHeight); URHO3D_PARAM(P_ACCRUAL, Accrual); URHO3D_PARAM(P_ACCRUAL_PRICE_LIMIT, AccrualPriceLimit); URHO3D_PARAM(P_MATCHES, Matches); URHO3D_PARAM(P_COST, Cost); URHO3D_PARAM(P_EXPIRATION, Expiration); }
URHO3D_EVENT(E_CRYPTOCITY_SELL, Sell) { URHO3D_PARAM(P_TYPE, Type); URHO3D_PARAM(P_ID, ID); URHO3D_PARAM(P_AMOUNT, Amount); URHO3D_PARAM(P_PRICE, Price); URHO3D_PARAM(P_ACCRUAL_START_HEIGHT, AccrualStartHeight); URHO3D_PARAM(P_ACCRUAL, Accrual); URHO3D_PARAM(P_ACCRUAL_PRICE_LIMIT, AccrualPriceLimit); URHO3D_PARAM(P_MATCHES, Matches); URHO3D_PARAM(P_COST, Cost); URHO3D_PARAM(P_EXPIRATION, Expiration); }
URHO3D_EVENT(E_CRYPTOCITY_ASSIGN_ITEMS, AssignItems) { URHO3D_PARAM(P_QUANTITIES, Quantities); /* vector */ }
URHO3D_EVENT(E_CRYPTOCITY_DESTROY_ITEMS, DestroyItems) { URHO3D_PARAM(P_QUANTITIES, Quantities); /* vector */ }
URHO3D_EVENT(E_CRYPTOCITY_ADD_BLOCK, AddBlock) {}
URHO3D_EVENT(E_CRYPTOCITY_REMOVE_BLOCK, RemoveBlock) {}
URHO3D_EVENT(E_CRYPTOCITY_APPROVE_BUILD, ApproveBuild) {}
@ -151,6 +152,7 @@ private:
void HandleAbandonBuild(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleTrade(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleAssignItems(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleDestroyItems(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleMaterialSelected(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData, bool player);
void HandlePlayerMaterialSelected(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleFlagMaterialSelected(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);

View File

@ -5260,6 +5260,45 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_cc_destroy_items(const wallet_rpc::COMMAND_RPC_CC_DESTROY_ITEMS::request& req, wallet_rpc::COMMAND_RPC_CC_DESTROY_ITEMS::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
LOG_PRINT_L3("on_cc_destroy_items 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_destroy_items_t cmd;
cmd.cc_account = m_wallet->get_cc_account();
cmd.item_id = req.item_id;
cmd.amount = req.amount;
uint32_t priority = m_wallet->adjust_priority(req.priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_cc_transactions(cmd, priority);
if (ptx_vector.empty())
{
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
er.message = "No transaction created";
return false;
}
std::string dummy_tx_key;
uint64_t dummy_amount;
return fill_response(ptx_vector, false, dummy_tx_key, dummy_amount, res.fee, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
}
catch (const std::exception& e)
{
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
return false;
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
}
class t_daemon

View File

@ -178,6 +178,7 @@ namespace tools
MAP_JON_RPC_WE("cc_ignore", on_cc_ignore, wallet_rpc::COMMAND_RPC_CC_IGNORE)
MAP_JON_RPC_WE("cc_event_badge", on_cc_event_badge, wallet_rpc::COMMAND_RPC_CC_EVENT_BADGE)
MAP_JON_RPC_WE("cc_resize_flag", on_cc_resize_flag, wallet_rpc::COMMAND_RPC_CC_RESIZE_FLAG)
MAP_JON_RPC_WE("cc_destroy_items", on_cc_destroy_items, wallet_rpc::COMMAND_RPC_CC_DESTROY_ITEMS)
END_JSON_RPC_MAP()
END_URI_MAP2()
@ -286,6 +287,7 @@ namespace tools
bool on_cc_ignore(const wallet_rpc::COMMAND_RPC_CC_IGNORE::request& req, wallet_rpc::COMMAND_RPC_CC_IGNORE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_event_badge(const wallet_rpc::COMMAND_RPC_CC_EVENT_BADGE::request& req, wallet_rpc::COMMAND_RPC_CC_EVENT_BADGE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_resize_flag(const wallet_rpc::COMMAND_RPC_CC_RESIZE_FLAG::request& req, wallet_rpc::COMMAND_RPC_CC_RESIZE_FLAG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_destroy_items(const wallet_rpc::COMMAND_RPC_CC_DESTROY_ITEMS::request& req, wallet_rpc::COMMAND_RPC_CC_DESTROY_ITEMS::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

@ -3800,5 +3800,50 @@ namespace wallet_rpc
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_CC_DESTROY_ITEMS
{
struct request_t
{
uint32_t item_id;
uint32_t amount;
uint32_t priority;
bool do_not_relay;
bool get_tx_hex;
bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(item_id)
KV_SERIALIZE(amount)
KV_SERIALIZE_OPT(priority, (uint32_t)0)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
KV_SERIALIZE_OPT(get_tx_metadata, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct response_t
{
std::string tx_hash;
uint64_t fee;
std::string tx_blob;
std::string tx_metadata;
std::string multisig_txset;
std::string unsigned_txset;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
KV_SERIALIZE(fee)
KV_SERIALIZE(tx_blob)
KV_SERIALIZE(tx_metadata)
KV_SERIALIZE(multisig_txset)
KV_SERIALIZE(unsigned_txset)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
}
}

View File

@ -1765,6 +1765,11 @@ class CCTest():
from_timestamp = e.timestamp
self.test_revert_cmd(daemon, lambda self: self.wallet[3].cc_event_badge(4096, "", "", [{"account_id": 4, "from_level": 2, "to_level": 3, "from_timestamp": from_timestamp}]))
# destroy items
res = daemon.cc_get_custom_items()
item_id = res.items_[-1].id
self.test_revert_cmd(daemon, lambda self: self.wallet[3].cc_destroy_items(item_id, 2))
def test_distance_from_generator(self):
daemon = Daemon()
@ -2083,6 +2088,38 @@ class CCTest():
assert res.balance == expected_balances[i]
assert (res.item_balances if 'item_balances' in res else []) == expected_item_balances[i]
# testing destruction
res = self.wallet[2].cc_destroy_items(ITEM_FIRST_USER + existing_items + 1, 3)
expected_balances[2] -= res.fee
res = self.wallet[2].cc_destroy_items(ITEM_WOOD, 2)
expected_balances[2] -= res.fee
self.generate_blocks('CC1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 2)
expected_item_balances[2] = self.add_item(expected_item_balances[2], ITEM_FIRST_USER + existing_items + 1, -3)
expected_item_balances[2] = self.add_item(expected_item_balances[2], ITEM_WOOD, -2)
# check total amount
res = daemon.cc_get_custom_items()
items = [x for x in res.items_ if x['id'] == ITEM_FIRST_USER + existing_items + 1]
assert len(items) == 1
assert items[0].amount == 30 - 3
# these can't
ok = False
try: self.wallet[2].cc_destroy_items(ITEM_FIRST_USER + existing_items + 100, 1)
except: ok = True
assert ok
ok = False
try: self.wallet[2].cc_destroy_items(ITEM_FIRST_USER + existing_items + 1, 3000000)
except: ok = True
assert ok
# check balances
for i in range(3):
res = daemon.cc_get_account(account_id[i])
assert res.balance == expected_balances[i]
assert (res.item_balances if 'item_balances' in res else []) == expected_item_balances[i]
def test_badges(self):
daemon = Daemon()

View File

@ -754,6 +754,13 @@ public:
state.items[id].ignore = ignore;
}
void set_cc_custom_item_amount(uint32_t id, uint32_t amount)
{
if (!state.items[id].in_use)
return;
state.items[id].amount = amount;
}
bool for_all_cc_custom_items(std::function<bool(const cc::cc_custom_item_t &cid)> f) const
{
for (size_t i = 0; i < state.items.size(); ++i)
@ -2486,6 +2493,8 @@ TEST(cc, type_tags)
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x15);
cmd = cryptonote::cc_command_resize_flag_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x16);
cmd = cryptonote::cc_command_destroy_items_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x17);
}
TEST(cc, staff)

View File

@ -1488,3 +1488,19 @@ class Wallet(object):
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_resize_flag)
def cc_destroy_items(self, item_id, amount, priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
cc_destroy_items = {
'method': 'cc_destroy_items',
'params': {
'item_id': item_id,
'amount': amount,
'priority': priority,
'do_not_relay': do_not_relay,
'get_tx_hex': get_tx_hex,
'get_tx_metadata': get_tx_metadata,
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_destroy_items)