Skip to content

Commit 2c1fd29

Browse files
committedJun 23, 2015
Add MoveSomewhere inventory action
Improve shift+click experience
1 parent bc55ef3 commit 2c1fd29

File tree

6 files changed

+180
-60
lines changed

6 files changed

+180
-60
lines changed
 

‎src/client.h

+3
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,9 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
493493
bool mediaReceived()
494494
{ return m_media_downloader == NULL; }
495495

496+
u8 getProtoVersion()
497+
{ return m_proto_ver; }
498+
496499
float mediaReceiveProgress();
497500

498501
void afterContentReceived(IrrlichtDevice *device);

‎src/guiFormSpecMenu.cpp

+33-22
Original file line numberDiff line numberDiff line change
@@ -3384,31 +3384,42 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
33843384
break;
33853385
ItemStack stack_from = list_from->getItem(s.i);
33863386
assert(shift_move_amount <= stack_from.count);
3387-
3388-
// find a place (or more than one) to add the new item
3389-
u32 ilt_size = list_to->getSize();
3390-
ItemStack leftover;
3391-
for (u32 slot_to = 0; slot_to < ilt_size
3392-
&& shift_move_amount > 0; slot_to++) {
3393-
list_to->itemFits(slot_to, stack_from, &leftover);
3394-
if (leftover.count < stack_from.count) {
3395-
infostream << "Handing IACTION_MOVE to manager" << std::endl;
3396-
IMoveAction *a = new IMoveAction();
3397-
a->count = MYMIN(shift_move_amount,
3398-
(u32) (stack_from.count - leftover.count));
3399-
shift_move_amount -= a->count;
3400-
a->from_inv = s.inventoryloc;
3401-
a->from_list = s.listname;
3402-
a->from_i = s.i;
3403-
a->to_inv = to_inv_sp.inventoryloc;
3404-
a->to_list = to_inv_sp.listname;
3405-
a->to_i = slot_to;
3406-
m_invmgr->inventoryAction(a);
3407-
stack_from = leftover;
3387+
if (m_client->getProtoVersion() >= 25) {
3388+
infostream << "Handing IACTION_MOVE to manager" << std::endl;
3389+
IMoveAction *a = new IMoveAction();
3390+
a->count = shift_move_amount;
3391+
a->from_inv = s.inventoryloc;
3392+
a->from_list = s.listname;
3393+
a->from_i = s.i;
3394+
a->to_inv = to_inv_sp.inventoryloc;
3395+
a->to_list = to_inv_sp.listname;
3396+
a->move_somewhere = true;
3397+
m_invmgr->inventoryAction(a);
3398+
} else {
3399+
// find a place (or more than one) to add the new item
3400+
u32 ilt_size = list_to->getSize();
3401+
ItemStack leftover;
3402+
for (u32 slot_to = 0; slot_to < ilt_size
3403+
&& shift_move_amount > 0; slot_to++) {
3404+
list_to->itemFits(slot_to, stack_from, &leftover);
3405+
if (leftover.count < stack_from.count) {
3406+
infostream << "Handing IACTION_MOVE to manager" << std::endl;
3407+
IMoveAction *a = new IMoveAction();
3408+
a->count = MYMIN(shift_move_amount,
3409+
(u32) (stack_from.count - leftover.count));
3410+
shift_move_amount -= a->count;
3411+
a->from_inv = s.inventoryloc;
3412+
a->from_list = s.listname;
3413+
a->from_i = s.i;
3414+
a->to_inv = to_inv_sp.inventoryloc;
3415+
a->to_list = to_inv_sp.listname;
3416+
a->to_i = slot_to;
3417+
m_invmgr->inventoryAction(a);
3418+
stack_from = leftover;
3419+
}
34083420
}
34093421
}
34103422
} while (0);
3411-
34123423
} else if (drop_amount > 0) {
34133424
m_selected_content_guess = ItemStack(); // Clear
34143425

‎src/inventory.cpp

+42-5
Original file line numberDiff line numberDiff line change
@@ -782,11 +782,48 @@ ItemStack InventoryList::peekItem(u32 i, u32 peekcount) const
782782
return m_items[i].peekItem(peekcount);
783783
}
784784

785-
void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
785+
void InventoryList::moveItemSomewhere(u32 i, InventoryList *dest, u32 count)
786786
{
787-
if(this == dest && i == dest_i)
787+
// Take item from source list
788+
ItemStack item1;
789+
if (count == 0)
790+
item1 = changeItem(i, ItemStack());
791+
else
792+
item1 = takeItem(i, count);
793+
794+
if (item1.empty())
788795
return;
789796

797+
// Try to add the item to destination list
798+
u32 oldcount = item1.count;
Has conversations. Original line has conversations.
799+
u32 dest_size = dest->getSize();
800+
// First try all the non-empty slots
801+
for (u32 dest_i = 0; dest_i < dest_size; dest_i++) {
802+
if (!m_items[dest_i].empty()) {
803+
item1 = dest->addItem(dest_i, item1);
804+
if (item1.empty()) return;
805+
}
806+
}
807+
808+
// Then try all the empty ones
809+
for (u32 dest_i = 0; dest_i < dest_size; dest_i++) {
810+
if (m_items[dest_i].empty()) {
811+
item1 = dest->addItem(dest_i, item1);
812+
if (item1.empty()) return;
813+
}
814+
}
815+
816+
// If we reach this, the item was not fully added
817+
// Add the remaining part back to the source item
818+
addItem(i, item1);
819+
}
820+
821+
u32 InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i,
822+
u32 count, bool swap_if_needed)
823+
{
824+
if(this == dest && i == dest_i)
825+
return count;
826+
790827
// Take item from source list
791828
ItemStack item1;
792829
if(count == 0)
@@ -795,7 +832,7 @@ void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
795832
item1 = takeItem(i, count);
796833

797834
if(item1.empty())
798-
return;
835+
return 0;
799836

800837
// Try to add the item to destination list
801838
u32 oldcount = item1.count;
@@ -813,8 +850,7 @@ void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
813850

814851
// If olditem is returned, nothing was added.
815852
// Swap the items
816-
if(nothing_added)
817-
{
853+
if (nothing_added && swap_if_needed) {
818854
// Take item from source list
819855
item1 = changeItem(i, ItemStack());
820856
// Adding was not possible, swap the items.
@@ -823,6 +859,7 @@ void InventoryList::moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count)
823859
changeItem(i, item2);
824860
}
825861
}
862+
return (oldcount - item1.count);
826863
}
827864

828865
/*

‎src/inventory.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,13 @@ class InventoryList
244244

245245
// Move an item to a different list (or a different stack in the same list)
246246
// count is the maximum number of items to move (0 for everything)
247-
void moveItem(u32 i, InventoryList *dest, u32 dest_i, u32 count = 0);
247+
// returns number of moved items
248+
u32 moveItem(u32 i, InventoryList *dest, u32 dest_i,
249+
u32 count = 0, bool swap_if_needed = true);
250+
251+
// like moveItem, but without a fixed destination index
252+
// also with optional rollback recording
253+
void moveItemSomewhere(u32 i, InventoryList *dest, u32 count);
248254

249255
private:
250256
std::vector<ItemStack> m_items;

‎src/inventorymanager.cpp

+73-23
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,13 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
121121

122122
InventoryAction *a = NULL;
123123

124-
if(type == "Move")
125-
{
126-
a = new IMoveAction(is);
127-
}
128-
else if(type == "Drop")
129-
{
124+
if (type == "Move") {
125+
a = new IMoveAction(is, false);
126+
} else if (type == "MoveSomewhere") {
127+
a = new IMoveAction(is, true);
128+
} else if (type == "Drop") {
130129
a = new IDropAction(is);
131-
}
132-
else if(type == "Craft")
133-
{
130+
} else if(type == "Craft") {
134131
a = new ICraftAction(is);
135132
}
136133

@@ -141,9 +138,12 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
141138
IMoveAction
142139
*/
143140

144-
IMoveAction::IMoveAction(std::istream &is)
141+
IMoveAction::IMoveAction(std::istream &is, bool somewhere)
145142
{
146143
std::string ts;
144+
move_somewhere = somewhere;
145+
caused_by_move_somewhere = false;
146+
move_count = 0;
147147

148148
std::getline(is, ts, ' ');
149149
count = stoi(ts);
@@ -161,8 +161,10 @@ IMoveAction::IMoveAction(std::istream &is)
161161

162162
std::getline(is, to_list, ' ');
163163

164-
std::getline(is, ts, ' ');
165-
to_i = stoi(ts);
164+
if (!somewhere) {
165+
std::getline(is, ts, ' ');
166+
to_i = stoi(ts);
167+
}
166168
}
167169

168170
void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef)
@@ -202,6 +204,48 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
202204
return;
203205
}
204206

207+
if (move_somewhere) {
208+
s16 old_to_i = to_i;
209+
u16 old_count = count;
210+
caused_by_move_somewhere = true;
211+
move_somewhere = false;
212+
213+
infostream << "IMoveAction::apply(): moving item somewhere"
214+
<< " msom=" << move_somewhere
215+
<< " count=" << count
216+
<< " from inv=\"" << from_inv.dump() << "\""
217+
<< " list=\"" << from_list << "\""
218+
<< " i=" << from_i
219+
<< " to inv=\"" << to_inv.dump() << "\""
220+
<< " list=\"" << to_list << "\""
221+
<< std::endl;
222+
223+
// Try to add the item to destination list
224+
s16 dest_size = list_to->getSize();
225+
// First try all the non-empty slots
226+
for (s16 dest_i = 0; dest_i < dest_size && count > 0; dest_i++) {
227+
if (!list_to->getItem(dest_i).empty()) {
228+
to_i = dest_i;
229+
apply(mgr, player, gamedef);
230+
count -= move_count;
231+
}
232+
}
233+
234+
// Then try all the empty ones
235+
for (s16 dest_i = 0; dest_i < dest_size && count > 0; dest_i++) {
236+
if (list_to->getItem(dest_i).empty()) {
237+
to_i = dest_i;
238+
apply(mgr, player, gamedef);
239+
count -= move_count;
240+
}
241+
}
242+
243+
to_i = old_to_i;
244+
count = old_count;
245+
caused_by_move_somewhere = false;
246+
move_somewhere = true;
247+
return;
248+
}
205249
/*
206250
Do not handle rollback if both inventories are that of the same player
207251
*/
@@ -324,7 +368,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
324368
If something is wrong (source item is empty, destination is the
325369
same as source), nothing happens
326370
*/
327-
list_from->moveItem(from_i, list_to, to_i, count);
371+
move_count = list_from->moveItem(from_i,
372+
list_to, to_i, count, !caused_by_move_somewhere);
328373

329374
// If source is infinite, reset it's stack
330375
if(src_can_take_count == -1){
@@ -352,15 +397,17 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
352397
list_from->takeItem(from_i, count);
353398
}
354399

355-
infostream<<"IMoveAction::apply(): moved"
356-
<<" count="<<count
357-
<<" from inv=\""<<from_inv.dump()<<"\""
358-
<<" list=\""<<from_list<<"\""
359-
<<" i="<<from_i
360-
<<" to inv=\""<<to_inv.dump()<<"\""
361-
<<" list=\""<<to_list<<"\""
362-
<<" i="<<to_i
363-
<<std::endl;
400+
infostream << "IMoveAction::apply(): moved"
401+
<< " msom=" << move_somewhere
402+
<< " caused=" << caused_by_move_somewhere
403+
<< " count=" << count
404+
<< " from inv=\"" << from_inv.dump() << "\""
405+
<< " list=\"" << from_list << "\""
406+
<< " i=" << from_i
407+
<< " to inv=\"" << to_inv.dump() << "\""
408+
<< " list=\"" << to_list << "\""
409+
<< " i=" << to_i
410+
<< std::endl;
364411

365412
/*
366413
Record rollback information
@@ -480,7 +527,10 @@ void IMoveAction::clientApply(InventoryManager *mgr, IGameDef *gamedef)
480527
if(!list_from || !list_to)
481528
return;
482529

483-
list_from->moveItem(from_i, list_to, to_i, count);
530+
if (!move_somewhere)
531+
list_from->moveItem(from_i, list_to, to_i, count);
532+
else
533+
list_from->moveItemSomewhere(from_i, list_to, count);
484534

485535
mgr->setInventoryModified(from_inv);
486536
if(inv_from != inv_to)

‎src/inventorymanager.h

+22-9
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,24 @@ struct IMoveAction : public InventoryAction
143143
InventoryLocation to_inv;
144144
std::string to_list;
145145
s16 to_i;
146+
bool move_somewhere;
147+
148+
// treat these as private
149+
// related to movement to somewhere
150+
bool caused_by_move_somewhere;
151+
u32 move_count;
146152

147153
IMoveAction()
148154
{
149155
count = 0;
150156
from_i = -1;
151157
to_i = -1;
158+
move_somewhere = false;
159+
caused_by_move_somewhere = false;
160+
move_count = 0;
152161
}
153162

154-
IMoveAction(std::istream &is);
163+
IMoveAction(std::istream &is, bool somewhere);
155164

156165
u16 getType() const
157166
{
@@ -160,14 +169,18 @@ struct IMoveAction : public InventoryAction
160169

161170
void serialize(std::ostream &os) const
162171
{
163-
os<<"Move ";
164-
os<<count<<" ";
165-
os<<from_inv.dump()<<" ";
166-
os<<from_list<<" ";
167-
os<<from_i<<" ";
168-
os<<to_inv.dump()<<" ";
169-
os<<to_list<<" ";
170-
os<<to_i;
172+
if (!move_somewhere)
173+
os << "Move ";
174+
else
175+
os << "MoveSomewhere ";
176+
os << count << " ";
177+
os << from_inv.dump() << " ";
178+
os << from_list << " ";
179+
os << from_i << " ";
180+
os << to_inv.dump() << " ";
181+
os << to_list;
182+
if (!move_somewhere)
183+
os << " " << to_i;
171184
}
172185

173186
void apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef);

0 commit comments

Comments
 (0)
Please sign in to comment.