Translated using Weblate (Italian)
[oweals/minetest.git] / src / rollback_interface.cpp
index 70a9e9457fe01e9a684cf4c66136cd8f8910e8df..c00206e984592a53f167ced313544b672dbbbcdc 100644 (file)
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/serialize.h"
 #include "util/string.h"
 #include "util/numeric.h"
+#include "util/basic_macros.h"
 #include "map.h"
 #include "gamedef.h"
 #include "nodedef.h"
@@ -32,336 +33,154 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "inventory.h"
 #include "mapblock.h"
 
-#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
 RollbackNode::RollbackNode(Map *map, v3s16 p, IGameDef *gamedef)
 {
-       INodeDefManager *ndef = gamedef->ndef();
-       MapNode n = map->getNodeNoEx(p);
+       const NodeDefManager *ndef = gamedef->ndef();
+       MapNode n = map->getNode(p);
        name = ndef->get(n).name;
        param1 = n.param1;
        param2 = n.param2;
        NodeMetadata *metap = map->getNodeMetadata(p);
-       if(metap){
+       if (metap) {
                std::ostringstream os(std::ios::binary);
-               metap->serialize(os);
+               metap->serialize(os, 1); // FIXME: version bump??
                meta = os.str();
        }
 }
 
+
 std::string RollbackAction::toString() const
 {
-       switch(type){
-       case TYPE_SET_NODE: {
-               std::ostringstream os(std::ios::binary);
-               os<<"[set_node";
-               os<<" ";
-               os<<"("<<itos(p.X)<<","<<itos(p.Y)<<","<<itos(p.Z)<<")";
-               os<<" ";
-               os<<serializeJsonString(n_old.name);
-               os<<" ";
-               os<<itos(n_old.param1);
-               os<<" ";
-               os<<itos(n_old.param2);
-               os<<" ";
-               os<<serializeJsonString(n_old.meta);
-               os<<" ";
-               os<<serializeJsonString(n_new.name);
-               os<<" ";
-               os<<itos(n_new.param1);
-               os<<" ";
-               os<<itos(n_new.param2);
-               os<<" ";
-               os<<serializeJsonString(n_new.meta);
-               os<<"]";
-               return os.str(); }
-       case TYPE_MODIFY_INVENTORY_STACK: {
-               std::ostringstream os(std::ios::binary);
-               os<<"[modify_inventory_stack";
-               os<<" ";
-               os<<serializeJsonString(inventory_location);
-               os<<" ";
-               os<<serializeJsonString(inventory_list);
-               os<<" ";
-               os<<inventory_index;
-               os<<" ";
-               os<<(inventory_add?"add":"remove");
-               os<<" ";
-               os<<serializeJsonString(inventory_stack);
-               os<<"]";
-               return os.str(); }
+       std::ostringstream os(std::ios::binary);
+       switch (type) {
+       case TYPE_SET_NODE:
+               os << "set_node " << PP(p);
+               os << ": (" << serializeJsonString(n_old.name);
+               os << ", " << itos(n_old.param1);
+               os << ", " << itos(n_old.param2);
+               os << ", " << serializeJsonString(n_old.meta);
+               os << ") -> (" << serializeJsonString(n_new.name);
+               os << ", " << itos(n_new.param1);
+               os << ", " << itos(n_new.param2);
+               os << ", " << serializeJsonString(n_new.meta);
+               os << ')';
+       case TYPE_MODIFY_INVENTORY_STACK:
+               os << "modify_inventory_stack (";
+               os << serializeJsonString(inventory_location);
+               os << ", " << serializeJsonString(inventory_list);
+               os << ", " << inventory_index;
+               os << ", " << (inventory_add ? "add" : "remove");
+               os << ", " << serializeJsonString(inventory_stack.getItemString());
+               os << ')';
        default:
-               return "none";
+               return "<unknown action>";
        }
+       return os.str();
 }
 
-void RollbackAction::fromStream(std::istream &is) throw(SerializationError)
-{
-       int c = is.get();
-       if(c != '['){
-               is.putback(c);
-               throw SerializationError("RollbackAction: starting [ not found");
-       }
-       
-       std::string id;
-       std::getline(is, id, ' ');
-       
-       if(id == "set_node")
-       {
-               c = is.get();
-               if(c != '('){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: starting ( not found");
-               }
-               // Position
-               std::string px_raw;
-               std::string py_raw;
-               std::string pz_raw;
-               std::getline(is, px_raw, ',');
-               std::getline(is, py_raw, ',');
-               std::getline(is, pz_raw, ')');
-               c = is.get();
-               if(c != ' '){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-p ' ' not found");
-               }
-               v3s16 loaded_p(stoi(px_raw), stoi(py_raw), stoi(pz_raw));
-               // Old node
-               std::string old_name;
-               try{
-                       old_name = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"old_name: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               c = is.get();
-               if(c != ' '){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-old_name ' ' not found");
-               }
-               std::string old_p1_raw;
-               std::string old_p2_raw;
-               std::getline(is, old_p1_raw, ' ');
-               std::getline(is, old_p2_raw, ' ');
-               int old_p1 = stoi(old_p1_raw);
-               int old_p2 = stoi(old_p2_raw);
-               std::string old_meta;
-               try{
-                       old_meta = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"old_meta: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               c = is.get();
-               if(c != ' '){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-old_meta ' ' not found");
-               }
-               // New node
-               std::string new_name;
-               try{
-                       new_name = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"new_name: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               c = is.get();
-               if(c != ' '){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-new_name ' ' not found");
-               }
-               std::string new_p1_raw;
-               std::string new_p2_raw;
-               std::getline(is, new_p1_raw, ' ');
-               std::getline(is, new_p2_raw, ' ');
-               int new_p1 = stoi(new_p1_raw);
-               int new_p2 = stoi(new_p2_raw);
-               std::string new_meta;
-               try{
-                       new_meta = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"new_meta: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               c = is.get();
-               if(c != ']'){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-new_meta ] not found");
-               }
-               // Set values
-               type = TYPE_SET_NODE;
-               p = loaded_p;
-               n_old.name = old_name;
-               n_old.param1 = old_p1;
-               n_old.param2 = old_p2;
-               n_old.meta = old_meta;
-               n_new.name = new_name;
-               n_new.param1 = new_p1;
-               n_new.param2 = new_p2;
-               n_new.meta = new_meta;
-       }
-       else if(id == "modify_inventory_stack")
-       {
-               // Location
-               std::string location;
-               try{
-                       location = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"location: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               c = is.get();
-               if(c != ' '){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-loc ' ' not found");
-               }
-               // List
-               std::string listname;
-               try{
-                       listname = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"listname: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               c = is.get();
-               if(c != ' '){
-                       is.putback(c);
-                       throw SerializationError("RollbackAction: after-list ' ' not found");
-               }
-               // Index
-               std::string index_raw;
-               std::getline(is, index_raw, ' ');
-               // add/remove
-               std::string addremove;
-               std::getline(is, addremove, ' ');
-               if(addremove != "add" && addremove != "remove"){
-                       throw SerializationError("RollbackAction: addremove is not add or remove");
-               }
-               // Itemstring
-               std::string stack;
-               try{
-                       stack = deSerializeJsonString(is);
-               }catch(SerializationError &e){
-                       errorstream<<"Serialization error in RollbackAction::fromStream(): "
-                                       <<"stack: "<<e.what()<<std::endl;
-                       throw e;
-               }
-               // Set values
-               type = TYPE_MODIFY_INVENTORY_STACK;
-               inventory_location = location;
-               inventory_list = listname;
-               inventory_index = stoi(index_raw);
-               inventory_add = (addremove == "add");
-               inventory_stack = stack;
-       }
-       else
-       {
-               throw SerializationError("RollbackAction: Unknown id");
-       }
-}
 
 bool RollbackAction::isImportant(IGameDef *gamedef) const
 {
-       switch(type){
-       case TYPE_SET_NODE: {
-               // If names differ, action is always important
-               if(n_old.name != n_new.name)
-                       return true;
-               // If metadata differs, action is always important
-               if(n_old.meta != n_new.meta)
-                       return true;
-               INodeDefManager *ndef = gamedef->ndef();
-               // Both are of the same name, so a single definition is needed
-               const ContentFeatures &def = ndef->get(n_old.name);
-               // If the type is flowing liquid, action is not important
-               if(def.liquid_type == LIQUID_FLOWING)
-                       return false;
-               // Otherwise action is important
-               return true; }
-       default:
+       if (type != TYPE_SET_NODE)
                return true;
-       }
+       // If names differ, action is always important
+       if(n_old.name != n_new.name)
+               return true;
+       // If metadata differs, action is always important
+       if(n_old.meta != n_new.meta)
+               return true;
+       const NodeDefManager *ndef = gamedef->ndef();
+       // Both are of the same name, so a single definition is needed
+       const ContentFeatures &def = ndef->get(n_old.name);
+       // If the type is flowing liquid, action is not important
+       if (def.liquid_type == LIQUID_FLOWING)
+               return false;
+       // Otherwise action is important
+       return true;
 }
 
+
 bool RollbackAction::getPosition(v3s16 *dst) const
 {
-       switch(type){
-       case RollbackAction::TYPE_SET_NODE:
-               if(dst) *dst = p;
+       switch (type) {
+       case TYPE_SET_NODE:
+               if (dst) *dst = p;
                return true;
-       case RollbackAction::TYPE_MODIFY_INVENTORY_STACK: {
+       case TYPE_MODIFY_INVENTORY_STACK: {
                InventoryLocation loc;
                loc.deSerialize(inventory_location);
-               if(loc.type != InventoryLocation::NODEMETA)
+               if (loc.type != InventoryLocation::NODEMETA) {
                        return false;
-               if(dst) *dst = loc.p;
+               }
+               if (dst) *dst = loc.p;
                return true; }
        default:
                return false;
        }
 }
 
+
 bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gamedef) const
 {
-       try{
-               switch(type){
+       try {
+               switch (type) {
                case TYPE_NOTHING:
                        return true;
                case TYPE_SET_NODE: {
-                       INodeDefManager *ndef = gamedef->ndef();
+                       const NodeDefManager *ndef = gamedef->ndef();
                        // Make sure position is loaded from disk
                        map->emergeBlock(getContainerPos(p, MAP_BLOCKSIZE), false);
                        // Check current node
-                       MapNode current_node = map->getNodeNoEx(p);
+                       MapNode current_node = map->getNode(p);
                        std::string current_name = ndef->get(current_node).name;
                        // If current node not the new node, it's bad
-                       if(current_name != n_new.name)
+                       if (current_name != n_new.name) {
                                return false;
-                       /*// If current node not the new node and not ignore, it's bad
-                       if(current_name != n_new.name && current_name != "ignore")
-                               return false;*/
+                       }
                        // Create rollback node
-                       MapNode n(ndef, n_old.name, n_old.param1, n_old.param2);
+                       content_t id = CONTENT_IGNORE;
+                       if (!ndef->getId(n_old.name, id)) {
+                               // The old node is not registered
+                               return false;
+                       }
+                       MapNode n(id, n_old.param1, n_old.param2);
                        // Set rollback node
-                       try{
-                               if(!map->addNodeWithEvent(p, n)){
-                                       infostream<<"RollbackAction::applyRevert(): "
-                                                       <<"AddNodeWithEvent failed at "
-                                                       <<PP(p)<<" for "<<n_old.name<<std::endl;
+                       try {
+                               if (!map->addNodeWithEvent(p, n)) {
+                                       infostream << "RollbackAction::applyRevert(): "
+                                               << "AddNodeWithEvent failed at "
+                                               << PP(p) << " for " << n_old.name
+                                               << std::endl;
                                        return false;
                                }
-                               NodeMetadata *meta = map->getNodeMetadata(p);
-                               if(n_old.meta != ""){
-                                       if(!meta){
-                                               meta = new NodeMetadata(gamedef);
-                                               map->setNodeMetadata(p, meta);
+                               if (n_old.meta.empty()) {
+                                       map->removeNodeMetadata(p);
+                               } else {
+                                       NodeMetadata *meta = map->getNodeMetadata(p);
+                                       if (!meta) {
+                                               meta = new NodeMetadata(gamedef->idef());
+                                               if (!map->setNodeMetadata(p, meta)) {
+                                                       delete meta;
+                                                       infostream << "RollbackAction::applyRevert(): "
+                                                               << "setNodeMetadata failed at "
+                                                               << PP(p) << " for " << n_old.name
+                                                               << std::endl;
+                                                       return false;
+                                               }
                                        }
                                        std::istringstream is(n_old.meta, std::ios::binary);
-                                       meta->deSerialize(is);
-                               } else {
-                                       map->removeNodeMetadata(p);
+                                       meta->deSerialize(is, 1); // FIXME: version bump??
                                }
-                               // NOTE: This same code is in scriptapi.cpp
-                               // Inform other things that the metadata has changed
-                               v3s16 blockpos = getContainerPos(p, MAP_BLOCKSIZE);
+                               // Inform other things that the meta data has changed
                                MapEditEvent event;
                                event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
-                               event.p = blockpos;
-                               map->dispatchEvent(&event);
-                               // Set the block to be saved
-                               MapBlock *block = map->getBlockNoCreateNoEx(blockpos);
-                               if(block)
-                                       block->raiseModified(MOD_STATE_WRITE_NEEDED,
-                                                       "NodeMetaRef::reportMetadataChange");
-                       }catch(InvalidPositionException &e){
-                               infostream<<"RollbackAction::applyRevert(): "
-                                               <<"InvalidPositionException: "<<e.what()<<std::endl;
+                               event.p = p;
+                               map->dispatchEvent(event);
+                       } catch (InvalidPositionException &e) {
+                               infostream << "RollbackAction::applyRevert(): "
+                                       << "InvalidPositionException: " << e.what()
+                                       << std::endl;
                                return false;
                        }
                        // Success
@@ -369,47 +188,48 @@ bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gam
                case TYPE_MODIFY_INVENTORY_STACK: {
                        InventoryLocation loc;
                        loc.deSerialize(inventory_location);
-                       ItemStack stack;
-                       stack.deSerialize(inventory_stack, gamedef->idef());
                        Inventory *inv = imgr->getInventory(loc);
-                       if(!inv){
-                               infostream<<"RollbackAction::applyRevert(): Could not get "
-                                               "inventory at "<<inventory_location<<std::endl;
+                       if (!inv) {
+                               infostream << "RollbackAction::applyRevert(): Could not get "
+                                       "inventory at " << inventory_location << std::endl;
                                return false;
                        }
                        InventoryList *list = inv->getList(inventory_list);
-                       if(!list){
-                               infostream<<"RollbackAction::applyRevert(): Could not get "
-                                               "inventory list \""<<inventory_list<<"\" in "
-                                               <<inventory_location<<std::endl;
+                       if (!list) {
+                               infostream << "RollbackAction::applyRevert(): Could not get "
+                                       "inventory list \"" << inventory_list << "\" in "
+                                       << inventory_location << std::endl;
                                return false;
                        }
-                       if(list->getSize() <= inventory_index){
-                               infostream<<"RollbackAction::applyRevert(): List index "
-                                               <<inventory_index<<" too large in "
-                                               <<"inventory list \""<<inventory_list<<"\" in "
-                                               <<inventory_location<<std::endl;
+                       if (list->getSize() <= inventory_index) {
+                               infostream << "RollbackAction::applyRevert(): List index "
+                                       << inventory_index << " too large in "
+                                       << "inventory list \"" << inventory_list << "\" in "
+                                       << inventory_location << std::endl;
+                               return false;
                        }
+
                        // If item was added, take away item, otherwise add removed item
-                       if(inventory_add){
+                       if (inventory_add) {
                                // Silently ignore different current item
-                               if(list->getItem(inventory_index).name != stack.name)
+                               if (list->getItem(inventory_index).name !=
+                                               gamedef->idef()->getAlias(inventory_stack.name))
                                        return false;
-                               list->takeItem(inventory_index, stack.count);
+                               list->takeItem(inventory_index, inventory_stack.count);
                        } else {
-                               list->addItem(inventory_index, stack);
+                               list->addItem(inventory_index, inventory_stack);
                        }
                        // Inventory was modified; send to clients
                        imgr->setInventoryModified(loc);
                        return true; }
                default:
-                       errorstream<<"RollbackAction::applyRevert(): type not handled"
-                                       <<std::endl;
+                       errorstream << "RollbackAction::applyRevert(): type not handled"
+                               << std::endl;
                        return false;
                }
-       }catch(SerializationError &e){
-               errorstream<<"RollbackAction::applyRevert(): n_old.name="<<n_old.name
-                               <<", SerializationError: "<<e.what()<<std::endl;
+       } catch(SerializationError &e) {
+               errorstream << "RollbackAction::applyRevert(): n_old.name=" << n_old.name
+                               << ", SerializationError: " << e.what() << std::endl;
        }
        return false;
 }