aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/game.cpp263
1 files changed, 133 insertions, 130 deletions
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 2b0976649..ef846fe18 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -801,8 +801,8 @@ private:
void updateChat(f32 dtime, const v2u32 &screensize);
- bool nodePlacementPrediction(const ItemDefinition &selected_def,
- const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos);
+ bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
+ const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed);
static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
InputHandler *input = nullptr;
@@ -1083,7 +1083,7 @@ void Game::run()
// RenderingEngine::run() from this iteration
// + Sleep time until the wanted FPS are reached
limitFps(&draw_times, &dtime);
-
+
// Prepare render data for next iteration
updateStats(&stats, draw_times, dtime);
@@ -3225,39 +3225,24 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
camera->setDigging(1); // right click animation (always shown for feedback)
+ soundmaker->m_player_rightpunch_sound = SimpleSoundSpec();
+
// If the wielded item has node placement prediction,
// make that happen
+ // And also set the sound and send the interact
auto &def = selected_item.getDefinition(itemdef_manager);
- bool placed = nodePlacementPrediction(def, selected_item, nodepos,
- neighbourpos);
-
- if (placed) {
- // Report to server
- client->interact(INTERACT_PLACE, pointed);
- // Read the sound
- soundmaker->m_player_rightpunch_sound =
- def.sound_place;
-
- if (client->modsLoaded())
- client->getScript()->on_placenode(pointed, def);
- } else {
- soundmaker->m_player_rightpunch_sound =
- SimpleSoundSpec();
+ bool placed = nodePlacement(def, selected_item, nodepos, neighbourpos,
+ pointed);
- if (def.node_placement_prediction.empty() ||
- nodedef_manager->get(map.getNode(nodepos)).rightclickable) {
- client->interact(INTERACT_PLACE, pointed); // Report to server
- } else {
- soundmaker->m_player_rightpunch_sound =
- def.sound_place_failed;
- }
- }
+ if (placed && client->modsLoaded())
+ client->getScript()->on_placenode(pointed, def);
}
}
}
-bool Game::nodePlacementPrediction(const ItemDefinition &selected_def,
- const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos)
+bool Game::nodePlacement(const ItemDefinition &selected_def,
+ const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos,
+ const PointedThing &pointed)
{
std::string prediction = selected_def.node_placement_prediction;
const NodeDefManager *nodedef = client->ndef();
@@ -3266,144 +3251,162 @@ bool Game::nodePlacementPrediction(const ItemDefinition &selected_def,
bool is_valid_position;
node = map.getNode(nodepos, &is_valid_position);
- if (!is_valid_position)
+ if (!is_valid_position) {
+ soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
return false;
+ }
- if (!prediction.empty() && !(nodedef->get(node).rightclickable &&
+ if (prediction.empty() || (nodedef->get(node).rightclickable &&
!isKeyDown(KeyType::SNEAK))) {
- verbosestream << "Node placement prediction for "
- << selected_item.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)
- return false;
+ // 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) {
+ // Report to server
+ client->interact(INTERACT_PLACE, pointed);
+ return false;
}
}
+ }
- // Find id of predicted node
- content_t id;
- bool found = nodedef->getId(prediction, id);
+ // Find id of predicted node
+ content_t id;
+ bool found = nodedef->getId(prediction, id);
- if (!found) {
- errorstream << "Node placement prediction failed for "
- << selected_item.name << " (places "
- << prediction
- << ") - Name not known" << std::endl;
- return false;
- }
+ if (!found) {
+ errorstream << "Node placement prediction failed for "
+ << selected_def.name << " (places "
+ << prediction
+ << ") - Name not known" << std::endl;
+ // Handle this as if prediction was empty
+ // Report to server
+ client->interact(INTERACT_PLACE, pointed);
+ return false;
+ }
- const ContentFeatures &predicted_f = nodedef->get(id);
+ const ContentFeatures &predicted_f = nodedef->get(id);
- // Predict param2 for facedir and wallmounted nodes
- u8 param2 = 0;
+ // Predict param2 for facedir and wallmounted nodes
+ u8 param2 = 0;
- if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
+ if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
- v3s16 dir = nodepos - neighbourpos;
+ v3s16 dir = nodepos - neighbourpos;
- if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
- param2 = dir.Y < 0 ? 1 : 0;
- } else if (abs(dir.X) > abs(dir.Z)) {
- param2 = dir.X < 0 ? 3 : 2;
- } else {
- param2 = dir.Z < 0 ? 5 : 4;
- }
+ if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
+ param2 = dir.Y < 0 ? 1 : 0;
+ } else if (abs(dir.X) > abs(dir.Z)) {
+ param2 = dir.X < 0 ? 3 : 2;
+ } else {
+ param2 = dir.Z < 0 ? 5 : 4;
}
+ }
- if (predicted_f.param_type_2 == CPT2_FACEDIR ||
+ if (predicted_f.param_type_2 == CPT2_FACEDIR ||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
- v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
+ v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
- if (abs(dir.X) > abs(dir.Z)) {
- param2 = dir.X < 0 ? 3 : 1;
- } else {
- param2 = dir.Z < 0 ? 2 : 0;
- }
+ if (abs(dir.X) > abs(dir.Z)) {
+ param2 = dir.X < 0 ? 3 : 1;
+ } else {
+ param2 = dir.Z < 0 ? 2 : 0;
}
+ }
- assert(param2 <= 5);
-
- //Check attachment if node is in group attached_node
- if (((ItemGroupList) predicted_f.groups)["attached_node"] != 0) {
- static v3s16 wallmounted_dirs[8] = {
- v3s16(0, 1, 0),
- v3s16(0, -1, 0),
- v3s16(1, 0, 0),
- v3s16(-1, 0, 0),
- v3s16(0, 0, 1),
- v3s16(0, 0, -1),
- };
- v3s16 pp;
-
- if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
+ assert(param2 <= 5);
+
+ //Check attachment if node is in group attached_node
+ if (((ItemGroupList) predicted_f.groups)["attached_node"] != 0) {
+ static v3s16 wallmounted_dirs[8] = {
+ v3s16(0, 1, 0),
+ v3s16(0, -1, 0),
+ v3s16(1, 0, 0),
+ v3s16(-1, 0, 0),
+ v3s16(0, 0, 1),
+ v3s16(0, 0, -1),
+ };
+ v3s16 pp;
+
+ if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
- pp = p + wallmounted_dirs[param2];
- else
- pp = p + v3s16(0, -1, 0);
+ pp = p + wallmounted_dirs[param2];
+ else
+ pp = p + v3s16(0, -1, 0);
- if (!nodedef->get(map.getNode(pp)).walkable)
- return false;
+ if (!nodedef->get(map.getNode(pp)).walkable) {
+ // Report to server
+ client->interact(INTERACT_PLACE, pointed);
+ return false;
}
+ }
- // Apply color
- if ((predicted_f.param_type_2 == CPT2_COLOR
+ // Apply color
+ if ((predicted_f.param_type_2 == CPT2_COLOR
|| predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
|| predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
- const std::string &indexstr = selected_item.metadata.getString(
- "palette_index", 0);
- if (!indexstr.empty()) {
- s32 index = mystoi(indexstr);
- if (predicted_f.param_type_2 == CPT2_COLOR) {
- param2 = index;
- } else if (predicted_f.param_type_2
- == CPT2_COLORED_WALLMOUNTED) {
- // param2 = pure palette index + other
- param2 = (index & 0xf8) | (param2 & 0x07);
- } else if (predicted_f.param_type_2
- == CPT2_COLORED_FACEDIR) {
- // param2 = pure palette index + other
- param2 = (index & 0xe0) | (param2 & 0x1f);
- }
+ const std::string &indexstr = selected_item.metadata.getString(
+ "palette_index", 0);
+ if (!indexstr.empty()) {
+ s32 index = mystoi(indexstr);
+ if (predicted_f.param_type_2 == CPT2_COLOR) {
+ param2 = index;
+ } else if (predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
+ // param2 = pure palette index + other
+ param2 = (index & 0xf8) | (param2 & 0x07);
+ } else if (predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
+ // param2 = pure palette index + other
+ param2 = (index & 0xe0) | (param2 & 0x1f);
}
}
+ }
- // Add node to client map
- MapNode n(id, 0, param2);
+ // Add node to client map
+ MapNode n(id, 0, param2);
- try {
- LocalPlayer *player = client->getEnv().getLocalPlayer();
+ try {
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- // Dont place node when player would be inside new node
- // NOTE: This is to be eventually implemented by a mod as client-side Lua
- if (!nodedef->get(n).walkable ||
+ // Dont place node when player would be inside new node
+ // NOTE: This is to be eventually implemented by a mod as client-side Lua
+ if (!nodedef->get(n).walkable ||
g_settings->getBool("enable_build_where_you_stand") ||
(client->checkPrivilege("noclip") && g_settings->getBool("noclip")) ||
(nodedef->get(n).walkable &&
neighbourpos != player->getStandingNodePos() + v3s16(0, 1, 0) &&
neighbourpos != player->getStandingNodePos() + v3s16(0, 2, 0))) {
-
- // This triggers the required mesh update too
- client->addNode(p, n);
- return true;
- }
- } catch (InvalidPositionException &e) {
- errorstream << "Node placement prediction failed for "
- << selected_item.name << " (places "
- << prediction
- << ") - Position not loaded" << std::endl;
+ // This triggers the required mesh update too
+ client->addNode(p, n);
+ // Report to server
+ client->interact(INTERACT_PLACE, pointed);
+ // A node is predicted, also play a sound
+ soundmaker->m_player_rightpunch_sound = selected_def.sound_place;
+ return true;
+ } else {
+ soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
+ return false;
}
+ } catch (InvalidPositionException &e) {
+ errorstream << "Node placement prediction failed for "
+ << selected_def.name << " (places "
+ << prediction
+ << ") - Position not loaded" << std::endl;
+ soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
+ return false;
}
-
- return false;
}
void Game::handlePointingAtObject(const PointedThing &pointed,