diff options
Diffstat (limited to 'src/rollback_interface.cpp')
-rw-r--r-- | src/rollback_interface.cpp | 385 |
1 files changed, 100 insertions, 285 deletions
diff --git a/src/rollback_interface.cpp b/src/rollback_interface.cpp index 808b07fed..c35ad5781 100644 --- a/src/rollback_interface.cpp +++ b/src/rollback_interface.cpp @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" + RollbackNode::RollbackNode(Map *map, v3s16 p, IGameDef *gamedef) { INodeDefManager *ndef = gamedef->ndef(); @@ -42,275 +43,89 @@ RollbackNode::RollbackNode(Map *map, v3s16 p, IGameDef *gamedef) param1 = n.param1; param2 = n.param2; NodeMetadata *metap = map->getNodeMetadata(p); - if(metap){ + if (metap) { std::ostringstream os(std::ios::binary); metap->serialize(os); 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; + 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; } + 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: { @@ -321,40 +136,39 @@ bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gam MapNode current_node = map->getNodeNoEx(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); // 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){ + if (n_old.meta.empty()) { + map->removeNodeMetadata(p); + } else { + NodeMetadata *meta = map->getNodeMetadata(p); + if (!meta) { meta = new NodeMetadata(gamedef); - if(!map->setNodeMetadata(p, meta)){ + if (!map->setNodeMetadata(p, meta)) { delete meta; - infostream<<"RollbackAction::applyRevert(): " - <<"setNodeMetadata failed at " - <<PP(p)<<" for "<<n_old.name<<std::endl; + 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); } - // NOTE: This same code is in scriptapi.cpp - // Inform other things that the metadata has changed + // Inform other things that the meta data has changed v3s16 blockpos = getContainerPos(p, MAP_BLOCKSIZE); MapEditEvent event; event.type = MEET_BLOCK_NODE_METADATA_CHANGED; @@ -362,12 +176,14 @@ bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gam map->dispatchEvent(&event); // Set the block to be saved MapBlock *block = map->getBlockNoCreateNoEx(blockpos); - if(block) + if (block) { block->raiseModified(MOD_STATE_WRITE_NEEDED, - "NodeMetaRef::reportMetadataChange"); - }catch(InvalidPositionException &e){ - infostream<<"RollbackAction::applyRevert(): " - <<"InvalidPositionException: "<<e.what()<<std::endl; + "NodeMetaRef::reportMetadataChange"); + } + } catch (InvalidPositionException &e) { + infostream << "RollbackAction::applyRevert(): " + << "InvalidPositionException: " << e.what() + << std::endl; return false; } // Success @@ -375,47 +191,46 @@ 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()); + std::string real_name = gamedef->idef()->getAlias(inventory_stack.name); 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; } // 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 != real_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; } |