mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 04:54:18 +02:00
Add MoveSomewhere inventory action
Improve shift+click experience
This commit is contained in:
parent
bc55ef337c
commit
2c1fd29884
@ -493,6 +493,9 @@ public:
|
||||
bool mediaReceived()
|
||||
{ return m_media_downloader == NULL; }
|
||||
|
||||
u8 getProtoVersion()
|
||||
{ return m_proto_ver; }
|
||||
|
||||
float mediaReceiveProgress();
|
||||
|
||||
void afterContentReceived(IrrlichtDevice *device);
|
||||
|
@ -3384,31 +3384,42 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
||||
break;
|
||||
ItemStack stack_from = list_from->getItem(s.i);
|
||||
assert(shift_move_amount <= stack_from.count);
|
||||
|
||||
// find a place (or more than one) to add the new item
|
||||
u32 ilt_size = list_to->getSize();
|
||||
ItemStack leftover;
|
||||
for (u32 slot_to = 0; slot_to < ilt_size
|
||||
&& shift_move_amount > 0; slot_to++) {
|
||||
list_to->itemFits(slot_to, stack_from, &leftover);
|
||||
if (leftover.count < stack_from.count) {
|
||||
infostream << "Handing IACTION_MOVE to manager" << std::endl;
|
||||
IMoveAction *a = new IMoveAction();
|
||||
a->count = MYMIN(shift_move_amount,
|
||||
(u32) (stack_from.count - leftover.count));
|
||||
shift_move_amount -= a->count;
|
||||
a->from_inv = s.inventoryloc;
|
||||
a->from_list = s.listname;
|
||||
a->from_i = s.i;
|
||||
a->to_inv = to_inv_sp.inventoryloc;
|
||||
a->to_list = to_inv_sp.listname;
|
||||
a->to_i = slot_to;
|
||||
m_invmgr->inventoryAction(a);
|
||||
stack_from = leftover;
|
||||
if (m_client->getProtoVersion() >= 25) {
|
||||
infostream << "Handing IACTION_MOVE to manager" << std::endl;
|
||||
IMoveAction *a = new IMoveAction();
|
||||
a->count = shift_move_amount;
|
||||
a->from_inv = s.inventoryloc;
|
||||
a->from_list = s.listname;
|
||||
a->from_i = s.i;
|
||||
a->to_inv = to_inv_sp.inventoryloc;
|
||||
a->to_list = to_inv_sp.listname;
|
||||
a->move_somewhere = true;
|
||||
m_invmgr->inventoryAction(a);
|
||||
} else {
|
||||
// find a place (or more than one) to add the new item
|
||||
u32 ilt_size = list_to->getSize();
|
||||
ItemStack leftover;
|
||||
for (u32 slot_to = 0; slot_to < ilt_size
|
||||
&& shift_move_amount > 0; slot_to++) {
|
||||
list_to->itemFits(slot_to, stack_from, &leftover);
|
||||
if (leftover.count < stack_from.count) {
|
||||
infostream << "Handing IACTION_MOVE to manager" << std::endl;
|
||||
IMoveAction *a = new IMoveAction();
|
||||
a->count = MYMIN(shift_move_amount,
|
||||
(u32) (stack_from.count - leftover.count));
|
||||
shift_move_amount -= a->count;
|
||||
a->from_inv = s.inventoryloc;
|
||||
a->from_list = s.listname;
|
||||
a->from_i = s.i;
|
||||
a->to_inv = to_inv_sp.inventoryloc;
|
||||
a->to_list = to_inv_sp.listname;
|
||||
a->to_i = slot_to;
|
||||
m_invmgr->inventoryAction(a);
|
||||
stack_from = leftover;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
} else if (drop_amount > 0) {
|
||||
m_selected_content_guess = ItemStack(); // Clear
|
||||
|
||||
|
@ -782,10 +782,47 @@ ItemStack InventoryList::peekItem(u32 i, u32 peekcount) const
|
||||
return m_items[i].peekItem(peekcount);
|
||||
}
|
||||
|
||||
void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
|
||||
void InventoryList::moveItemSomewhere(u32 i, InventoryList *dest, u32 count)
|
||||
{
|
||||
// Take item from source list
|
||||
ItemStack item1;
|
||||
if (count == 0)
|
||||
item1 = changeItem(i, ItemStack());
|
||||
else
|
||||
item1 = takeItem(i, count);
|
||||
|
||||
if (item1.empty())
|
||||
return;
|
||||
|
||||
// Try to add the item to destination list
|
||||
u32 oldcount = item1.count;
|
||||
u32 dest_size = dest->getSize();
|
||||
// First try all the non-empty slots
|
||||
for (u32 dest_i = 0; dest_i < dest_size; dest_i++) {
|
||||
if (!m_items[dest_i].empty()) {
|
||||
item1 = dest->addItem(dest_i, item1);
|
||||
if (item1.empty()) return;
|
||||
}
|
||||
}
|
||||
|
||||
// Then try all the empty ones
|
||||
for (u32 dest_i = 0; dest_i < dest_size; dest_i++) {
|
||||
if (m_items[dest_i].empty()) {
|
||||
item1 = dest->addItem(dest_i, item1);
|
||||
if (item1.empty()) return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we reach this, the item was not fully added
|
||||
// Add the remaining part back to the source item
|
||||
addItem(i, item1);
|
||||
}
|
||||
|
||||
u32 InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i,
|
||||
u32 count, bool swap_if_needed)
|
||||
{
|
||||
if(this == dest && i == dest_i)
|
||||
return;
|
||||
return count;
|
||||
|
||||
// Take item from source list
|
||||
ItemStack item1;
|
||||
@ -795,7 +832,7 @@ void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
|
||||
item1 = takeItem(i, count);
|
||||
|
||||
if(item1.empty())
|
||||
return;
|
||||
return 0;
|
||||
|
||||
// Try to add the item to destination list
|
||||
u32 oldcount = item1.count;
|
||||
@ -813,8 +850,7 @@ void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
|
||||
|
||||
// If olditem is returned, nothing was added.
|
||||
// Swap the items
|
||||
if(nothing_added)
|
||||
{
|
||||
if (nothing_added && swap_if_needed) {
|
||||
// Take item from source list
|
||||
item1 = changeItem(i, ItemStack());
|
||||
// Adding was not possible, swap the items.
|
||||
@ -823,6 +859,7 @@ void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
|
||||
changeItem(i, item2);
|
||||
}
|
||||
}
|
||||
return (oldcount - item1.count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -244,7 +244,13 @@ public:
|
||||
|
||||
// Move an item to a different list (or a different stack in the same list)
|
||||
// count is the maximum number of items to move (0 for everything)
|
||||
void moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count = 0);
|
||||
// returns number of moved items
|
||||
u32 moveItem(u32 i, InventoryList *dest, u32 dest_i,
|
||||
u32 count = 0, bool swap_if_needed = true);
|
||||
|
||||
// like moveItem, but without a fixed destination index
|
||||
// also with optional rollback recording
|
||||
void moveItemSomewhere(u32 i, InventoryList *dest, u32 count);
|
||||
|
||||
private:
|
||||
std::vector<ItemStack> m_items;
|
||||
|
@ -121,16 +121,13 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
|
||||
|
||||
InventoryAction *a = NULL;
|
||||
|
||||
if(type == "Move")
|
||||
{
|
||||
a = new IMoveAction(is);
|
||||
}
|
||||
else if(type == "Drop")
|
||||
{
|
||||
if (type == "Move") {
|
||||
a = new IMoveAction(is, false);
|
||||
} else if (type == "MoveSomewhere") {
|
||||
a = new IMoveAction(is, true);
|
||||
} else if (type == "Drop") {
|
||||
a = new IDropAction(is);
|
||||
}
|
||||
else if(type == "Craft")
|
||||
{
|
||||
} else if(type == "Craft") {
|
||||
a = new ICraftAction(is);
|
||||
}
|
||||
|
||||
@ -141,9 +138,12 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
|
||||
IMoveAction
|
||||
*/
|
||||
|
||||
IMoveAction::IMoveAction(std::istream &is)
|
||||
IMoveAction::IMoveAction(std::istream &is, bool somewhere)
|
||||
{
|
||||
std::string ts;
|
||||
move_somewhere = somewhere;
|
||||
caused_by_move_somewhere = false;
|
||||
move_count = 0;
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
count = stoi(ts);
|
||||
@ -161,8 +161,10 @@ IMoveAction::IMoveAction(std::istream &is)
|
||||
|
||||
std::getline(is, to_list, ' ');
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
to_i = stoi(ts);
|
||||
if (!somewhere) {
|
||||
std::getline(is, ts, ' ');
|
||||
to_i = stoi(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef)
|
||||
@ -202,6 +204,48 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
||||
return;
|
||||
}
|
||||
|
||||
if (move_somewhere) {
|
||||
s16 old_to_i = to_i;
|
||||
u16 old_count = count;
|
||||
caused_by_move_somewhere = true;
|
||||
move_somewhere = false;
|
||||
|
||||
infostream << "IMoveAction::apply(): moving item somewhere"
|
||||
<< " msom=" << move_somewhere
|
||||
<< " count=" << count
|
||||
<< " from inv=\"" << from_inv.dump() << "\""
|
||||
<< " list=\"" << from_list << "\""
|
||||
<< " i=" << from_i
|
||||
<< " to inv=\"" << to_inv.dump() << "\""
|
||||
<< " list=\"" << to_list << "\""
|
||||
<< std::endl;
|
||||
|
||||
// Try to add the item to destination list
|
||||
s16 dest_size = list_to->getSize();
|
||||
// First try all the non-empty slots
|
||||
for (s16 dest_i = 0; dest_i < dest_size && count > 0; dest_i++) {
|
||||
if (!list_to->getItem(dest_i).empty()) {
|
||||
to_i = dest_i;
|
||||
apply(mgr, player, gamedef);
|
||||
count -= move_count;
|
||||
}
|
||||
}
|
||||
|
||||
// Then try all the empty ones
|
||||
for (s16 dest_i = 0; dest_i < dest_size && count > 0; dest_i++) {
|
||||
if (list_to->getItem(dest_i).empty()) {
|
||||
to_i = dest_i;
|
||||
apply(mgr, player, gamedef);
|
||||
count -= move_count;
|
||||
}
|
||||
}
|
||||
|
||||
to_i = old_to_i;
|
||||
count = old_count;
|
||||
caused_by_move_somewhere = false;
|
||||
move_somewhere = true;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
Do not handle rollback if both inventories are that of the same player
|
||||
*/
|
||||
@ -324,7 +368,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
||||
If something is wrong (source item is empty, destination is the
|
||||
same as source), nothing happens
|
||||
*/
|
||||
list_from->moveItem(from_i, list_to, to_i, count);
|
||||
move_count = list_from->moveItem(from_i,
|
||||
list_to, to_i, count, !caused_by_move_somewhere);
|
||||
|
||||
// If source is infinite, reset it's stack
|
||||
if(src_can_take_count == -1){
|
||||
@ -352,15 +397,17 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
||||
list_from->takeItem(from_i, count);
|
||||
}
|
||||
|
||||
infostream<<"IMoveAction::apply(): moved"
|
||||
<<" count="<<count
|
||||
<<" from inv=\""<<from_inv.dump()<<"\""
|
||||
<<" list=\""<<from_list<<"\""
|
||||
<<" i="<<from_i
|
||||
<<" to inv=\""<<to_inv.dump()<<"\""
|
||||
<<" list=\""<<to_list<<"\""
|
||||
<<" i="<<to_i
|
||||
<<std::endl;
|
||||
infostream << "IMoveAction::apply(): moved"
|
||||
<< " msom=" << move_somewhere
|
||||
<< " caused=" << caused_by_move_somewhere
|
||||
<< " count=" << count
|
||||
<< " from inv=\"" << from_inv.dump() << "\""
|
||||
<< " list=\"" << from_list << "\""
|
||||
<< " i=" << from_i
|
||||
<< " to inv=\"" << to_inv.dump() << "\""
|
||||
<< " list=\"" << to_list << "\""
|
||||
<< " i=" << to_i
|
||||
<< std::endl;
|
||||
|
||||
/*
|
||||
Record rollback information
|
||||
@ -480,7 +527,10 @@ void IMoveAction::clientApply(InventoryManager *mgr, IGameDef *gamedef)
|
||||
if(!list_from || !list_to)
|
||||
return;
|
||||
|
||||
list_from->moveItem(from_i, list_to, to_i, count);
|
||||
if (!move_somewhere)
|
||||
list_from->moveItem(from_i, list_to, to_i, count);
|
||||
else
|
||||
list_from->moveItemSomewhere(from_i, list_to, count);
|
||||
|
||||
mgr->setInventoryModified(from_inv);
|
||||
if(inv_from != inv_to)
|
||||
|
@ -143,15 +143,24 @@ struct IMoveAction : public InventoryAction
|
||||
InventoryLocation to_inv;
|
||||
std::string to_list;
|
||||
s16 to_i;
|
||||
bool move_somewhere;
|
||||
|
||||
// treat these as private
|
||||
// related to movement to somewhere
|
||||
bool caused_by_move_somewhere;
|
||||
u32 move_count;
|
||||
|
||||
IMoveAction()
|
||||
{
|
||||
count = 0;
|
||||
from_i = -1;
|
||||
to_i = -1;
|
||||
move_somewhere = false;
|
||||
caused_by_move_somewhere = false;
|
||||
move_count = 0;
|
||||
}
|
||||
|
||||
IMoveAction(std::istream &is);
|
||||
IMoveAction(std::istream &is, bool somewhere);
|
||||
|
||||
u16 getType() const
|
||||
{
|
||||
@ -160,14 +169,18 @@ struct IMoveAction : public InventoryAction
|
||||
|
||||
void serialize(std::ostream &os) const
|
||||
{
|
||||
os<<"Move ";
|
||||
os<<count<<" ";
|
||||
os<<from_inv.dump()<<" ";
|
||||
os<<from_list<<" ";
|
||||
os<<from_i<<" ";
|
||||
os<<to_inv.dump()<<" ";
|
||||
os<<to_list<<" ";
|
||||
os<<to_i;
|
||||
if (!move_somewhere)
|
||||
os << "Move ";
|
||||
else
|
||||
os << "MoveSomewhere ";
|
||||
os << count << " ";
|
||||
os << from_inv.dump() << " ";
|
||||
os << from_list << " ";
|
||||
os << from_i << " ";
|
||||
os << to_inv.dump() << " ";
|
||||
os << to_list;
|
||||
if (!move_somewhere)
|
||||
os << " " << to_i;
|
||||
}
|
||||
|
||||
void apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef);
|
||||
|
Loading…
Reference in New Issue
Block a user