bool PlayerDatabaseSQLite3::loadPlayer(RemotePlayer *player, PlayerSAO *sao) { verifyDatabase(); str_to_sqlite(m_stmt_player_load, 1, player->getName()); if (sqlite3_step(m_stmt_player_load) != SQLITE_ROW) { sqlite3_reset(m_stmt_player_load); return false; } sao->setPitch(sqlite_to_float(m_stmt_player_load, 0)); sao->setYaw(sqlite_to_float(m_stmt_player_load, 1)); sao->setBasePosition(sqlite_to_v3f(m_stmt_player_load, 2)); sao->setHPRaw((s16) MYMIN(sqlite_to_int(m_stmt_player_load, 5), S16_MAX)); sao->setBreath((u16) MYMIN(sqlite_to_int(m_stmt_player_load, 6), U16_MAX), false); sqlite3_reset(m_stmt_player_load); // Load inventory str_to_sqlite(m_stmt_player_load_inventory, 1, player->getName()); while (sqlite3_step(m_stmt_player_load_inventory) == SQLITE_ROW) { InventoryList *invList = player->inventory.addList( sqlite_to_string(m_stmt_player_load_inventory, 2), sqlite_to_uint(m_stmt_player_load_inventory, 3)); invList->setWidth(sqlite_to_uint(m_stmt_player_load_inventory, 1)); u32 invId = sqlite_to_uint(m_stmt_player_load_inventory, 0); str_to_sqlite(m_stmt_player_load_inventory_items, 1, player->getName()); int_to_sqlite(m_stmt_player_load_inventory_items, 2, invId); while (sqlite3_step(m_stmt_player_load_inventory_items) == SQLITE_ROW) { const std::string itemStr = sqlite_to_string(m_stmt_player_load_inventory_items, 1); if (itemStr.length() > 0) { ItemStack stack; stack.deSerialize(itemStr); invList->addItem(sqlite_to_uint(m_stmt_player_load_inventory_items, 0), stack); } } sqlite3_reset(m_stmt_player_load_inventory_items); } sqlite3_reset(m_stmt_player_load_inventory); str_to_sqlite(m_stmt_player_metadata_load, 1, sao->getPlayer()->getName()); while (sqlite3_step(m_stmt_player_metadata_load) == SQLITE_ROW) { std::string attr = sqlite_to_string(m_stmt_player_metadata_load, 0); std::string value = sqlite_to_string(m_stmt_player_metadata_load, 1); sao->setExtendedAttribute(attr, value); } sqlite3_reset(m_stmt_player_metadata_load); return true; }
// add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack // Returns the leftover stack int InvRef::l_add_item(lua_State *L) { NO_MAP_LOCK_REQUIRED; InvRef *ref = checkobject(L, 1); const char *listname = luaL_checkstring(L, 2); ItemStack item = read_item(L, 3, getServer(L)->idef()); InventoryList *list = getlist(L, ref, listname); if(list){ ItemStack leftover = list->addItem(item); if(leftover.count != item.count) reportInventoryChange(L, ref); LuaItemStack::create(L, leftover); } else { LuaItemStack::create(L, item); } return 1; }
bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gamedef) const { try { switch (type) { case TYPE_NOTHING: return true; case TYPE_SET_NODE: { INodeDefManager *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); 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) { 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; return false; } 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)) { 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); } // Inform other things that the meta data has changed v3s16 blockpos = getContainerPos(p, MAP_BLOCKSIZE); 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, MOD_REASON_REPORT_META_CHANGE); } } catch (InvalidPositionException &e) { infostream << "RollbackAction::applyRevert(): " << "InvalidPositionException: " << e.what() << std::endl; return false; } // Success return true; } case TYPE_MODIFY_INVENTORY_STACK: { InventoryLocation loc; loc.deSerialize(inventory_location); 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; 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; 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 item was added, take away item, otherwise add removed item if (inventory_add) { // Silently ignore different current item if (list->getItem(inventory_index).name != real_name) return false; list->takeItem(inventory_index, inventory_stack.count); } else { 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; return false; } } catch(SerializationError &e) { errorstream << "RollbackAction::applyRevert(): n_old.name=" << n_old.name << ", SerializationError: " << e.what() << std::endl; } return false; }