- if (!prediction.empty() && !nodedef->get(node).rightclickable) {
- verbosestream << "Node placement prediction for "
- << playeritem_def.name << " is "
- << prediction << std::endl;
- v3s16 p = neighbourpos;
-
- // Place inside node itself if buildable_to
- MapNode n_under = map.getNodeNoEx(nodepos, &is_valid_position);
- if (is_valid_position)
- {
- if (nodedef->get(n_under).buildable_to)
- p = nodepos;
- else {
- node = map.getNodeNoEx(p, &is_valid_position);
- if (is_valid_position &&!nodedef->get(node).buildable_to)
- return false;
+ InventoryLocation inventoryloc;
+ inventoryloc.setNodeMeta(nodepos);
+
+ NodeMetadataFormSource *fs_src = new NodeMetadataFormSource(
+ &client->getEnv().getClientMap(), nodepos);
+ TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
+
+ auto *&formspec = m_game_ui->updateFormspec("");
+ GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
+ &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound);
+
+ formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
+ return false;
+ }
+
+ // on_rightclick callback
+ if (prediction.empty() || (nodedef->get(node).rightclickable &&
+ !isKeyDown(KeyType::SNEAK))) {
+ // Report to server
+ client->interact(INTERACT_PLACE, pointed);
+ return false;
+ }
+
+ verbosestream << "Node placement prediction for "
+ << selected_def.name << " is " << prediction << std::endl;
+ v3s16 p = neighbourpos;
+
+ // Place inside node itself if buildable_to
+ MapNode n_under = map.getNode(nodepos, &is_valid_position);
+ if (is_valid_position) {
+ if (nodedef->get(n_under).buildable_to) {
+ p = nodepos;
+ } else {
+ node = map.getNode(p, &is_valid_position);
+ if (is_valid_position && !nodedef->get(node).buildable_to) {
+ soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
+ // Report to server
+ client->interact(INTERACT_PLACE, pointed);
+ return false;