@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
20
20
#include " inventory.h"
21
21
#include " serialization.h"
22
22
#include " debug.h"
23
+ #include < algorithm>
23
24
#include < sstream>
24
25
#include " log.h"
25
26
#include " itemdef.h"
@@ -382,27 +383,32 @@ void InventoryList::clearItems()
382
383
m_items.emplace_back ();
383
384
}
384
385
385
- // setDirty(true );
386
+ setModified ( );
386
387
}
387
388
388
389
void InventoryList::setSize (u32 newsize)
389
390
{
390
- if (newsize != m_items.size ())
391
- m_items.resize (newsize);
391
+ if (newsize == m_items.size ())
392
+ return ;
393
+
394
+ m_items.resize (newsize);
392
395
m_size = newsize;
396
+ setModified ();
393
397
}
394
398
395
399
void InventoryList::setWidth (u32 newwidth)
396
400
{
397
401
m_width = newwidth;
402
+ setModified ();
398
403
}
399
404
400
405
void InventoryList::setName (const std::string &name)
401
406
{
402
407
m_name = name;
408
+ setModified ();
403
409
}
404
410
405
- void InventoryList::serialize (std::ostream &os) const
411
+ void InventoryList::serialize (std::ostream &os, bool incremental ) const
406
412
{
407
413
// os.imbue(std::locale("C"));
408
414
@@ -415,6 +421,9 @@ void InventoryList::serialize(std::ostream &os) const
415
421
os<<" Item " ;
416
422
item.serialize (os);
417
423
}
424
+ // TODO: Implement this:
425
+ // if (!incremental || item.checkModified())
426
+ // os << "Keep";
418
427
os<<" \n " ;
419
428
}
420
429
@@ -424,8 +433,8 @@ void InventoryList::serialize(std::ostream &os) const
424
433
void InventoryList::deSerialize (std::istream &is)
425
434
{
426
435
// is.imbue(std::locale("C"));
436
+ setModified ();
427
437
428
- clearItems ();
429
438
u32 item_i = 0 ;
430
439
m_width = 0 ;
431
440
@@ -439,12 +448,12 @@ void InventoryList::deSerialize(std::istream &is)
439
448
std::string name;
440
449
std::getline (iss, name, ' ' );
441
450
442
- if (name == " EndInventoryList" )
443
- return ;
444
-
445
- // This is a temporary backwards compatibility fix
446
- if (name == " end" )
451
+ if (name == " EndInventoryList" || name == " end" ) {
452
+ // If partial incremental: Clear leftover items (should not happen!)
453
+ for (size_t i = item_i; i < m_items.size (); ++i)
454
+ m_items[i].clear ();
447
455
return ;
456
+ }
448
457
449
458
if (name == " Width" ) {
450
459
iss >> m_width;
@@ -464,6 +473,8 @@ void InventoryList::deSerialize(std::istream &is)
464
473
if (item_i > getSize () - 1 )
465
474
throw SerializationError (" too many items" );
466
475
m_items[item_i++].clear ();
476
+ } else if (name == " Keep" ) {
477
+ ++item_i; // Unmodified item
467
478
}
468
479
}
469
480
@@ -557,14 +568,15 @@ ItemStack InventoryList::changeItem(u32 i, const ItemStack &newitem)
557
568
558
569
ItemStack olditem = m_items[i];
559
570
m_items[i] = newitem;
560
- // setDirty(true );
571
+ setModified ( );
561
572
return olditem;
562
573
}
563
574
564
575
void InventoryList::deleteItem (u32 i)
565
576
{
566
577
assert (i < m_items.size ()); // Pre-condition
567
578
m_items[i].clear ();
579
+ setModified ();
568
580
}
569
581
570
582
ItemStack InventoryList::addItem (const ItemStack &newitem_)
@@ -612,8 +624,8 @@ ItemStack InventoryList::addItem(u32 i, const ItemStack &newitem)
612
624
return newitem;
613
625
614
626
ItemStack leftover = m_items[i].addItem (newitem, m_itemdef);
615
- // if (leftover != newitem)
616
- // setDirty(true );
627
+ if (leftover != newitem)
628
+ setModified ( );
617
629
return leftover;
618
630
}
619
631
@@ -682,8 +694,8 @@ ItemStack InventoryList::takeItem(u32 i, u32 takecount)
682
694
return ItemStack ();
683
695
684
696
ItemStack taken = m_items[i].takeItem (takecount);
685
- // if (!taken.empty())
686
- // setDirty(true );
697
+ if (!taken.empty ())
698
+ setModified ( );
687
699
return taken;
688
700
}
689
701
@@ -788,16 +800,6 @@ void Inventory::clear()
788
800
m_lists.clear ();
789
801
}
790
802
791
- void Inventory::clearContents ()
792
- {
793
- m_dirty = true ;
794
- for (InventoryList *list : m_lists) {
795
- for (u32 j=0 ; j<list->getSize (); j++) {
796
- list->deleteItem (j);
797
- }
798
- }
799
- }
800
-
801
803
Inventory::Inventory (IItemDefManager *itemdef)
802
804
{
803
805
m_dirty = false ;
@@ -807,7 +809,6 @@ Inventory::Inventory(IItemDefManager *itemdef)
807
809
Inventory::Inventory (const Inventory &other)
808
810
{
809
811
*this = other;
810
- m_dirty = false ;
811
812
}
812
813
813
814
Inventory & Inventory::operator = (const Inventory &other)
@@ -838,19 +839,24 @@ bool Inventory::operator == (const Inventory &other) const
838
839
return true ;
839
840
}
840
841
841
- void Inventory::serialize (std::ostream &os) const
842
+ void Inventory::serialize (std::ostream &os, bool incremental ) const
842
843
{
843
- for (InventoryList *list : m_lists) {
844
- os<<" List " <<list->getName ()<<" " <<list->getSize ()<<" \n " ;
845
- list->serialize (os);
844
+ for (const InventoryList *list : m_lists) {
845
+ if (!incremental || list->checkModified ()) {
846
+ os << " List " << list->getName () << " " << list->getSize () << " \n " ;
847
+ list->serialize (os, incremental);
848
+ } else {
849
+ os << " KeepList " << list->getName () << " \n " ;
850
+ }
846
851
}
847
852
848
853
os<<" EndInventory\n " ;
849
854
}
850
855
851
856
void Inventory::deSerialize (std::istream &is)
852
857
{
853
- clear ();
858
+ std::vector<InventoryList *> new_lists;
859
+ new_lists.reserve (m_lists.size ());
854
860
855
861
while (is.good ()) {
856
862
std::string line;
@@ -861,12 +867,20 @@ void Inventory::deSerialize(std::istream &is)
861
867
std::string name;
862
868
std::getline (iss, name, ' ' );
863
869
864
- if (name == " EndInventory" )
865
- return ;
870
+ if (name == " EndInventory" || name == " end" ) {
871
+ // Remove all lists that were not sent
872
+ for (auto &list : m_lists) {
873
+ if (std::find (new_lists.begin (), new_lists.end (), list) != new_lists.end ())
874
+ continue ;
866
875
867
- // This is a temporary backwards compatibility fix
868
- if (name == " end" )
876
+ delete list;
877
+ list = nullptr ;
878
+ m_dirty = true ;
879
+ }
880
+ m_lists.erase (std::remove (m_lists.begin (), m_lists.end (),
881
+ nullptr ), m_lists.end ());
869
882
return ;
883
+ }
870
884
871
885
if (name == " List" ) {
872
886
std::string listname;
@@ -875,15 +889,33 @@ void Inventory::deSerialize(std::istream &is)
875
889
std::getline (iss, listname, ' ' );
876
890
iss>>listsize;
877
891
878
- InventoryList *list = new InventoryList (listname, listsize, m_itemdef);
892
+ InventoryList *list = getList (listname);
893
+ bool create_new = !list;
894
+ if (create_new)
895
+ list = new InventoryList (listname, listsize, m_itemdef);
896
+ else
897
+ list->setSize (listsize);
879
898
list->deSerialize (is);
880
899
881
- m_lists.push_back (list);
882
- }
883
- else
884
- {
885
- throw SerializationError (" invalid inventory specifier: " + name);
900
+ new_lists.push_back (list);
901
+ if (create_new)
902
+ m_lists.push_back (list);
903
+
904
+ } else if (name == " KeepList" ) {
905
+ // Incrementally sent list
906
+ std::string listname;
907
+ std::getline (iss, listname, ' ' );
908
+
909
+ InventoryList *list = getList (listname);
910
+ if (list) {
911
+ new_lists.push_back (list);
912
+ } else {
913
+ errorstream << " Inventory::deSerialize(): Tried to keep list '" <<
914
+ listname << " ' which is non-existent." << std::endl;
915
+ }
886
916
}
917
+ // Any additional fields will throw errors when received by a client
918
+ // older than PROTOCOL_VERSION 38
887
919
}
888
920
889
921
// Contents given to deSerialize() were not terminated properly: throw error.
0 commit comments