diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6bdb63ef3..9a5754368 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4240,6 +4240,13 @@ Definition tables on ground when the player places the item. Server will always update actual result to client in a short moment. ]] + node_dig_prediction = "air", + --[[ + ^ if "", no prediction is made + ^ if "air", node is removed + ^ Otherwise should be name of node which the client immediately places + upon digging. Server will always update actual result shortly. + ]] sound = { breaks = "default_tool_break", -- tools only place = --[[]], diff --git a/src/game.cpp b/src/game.cpp index 04688e476..d85e34d35 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -4104,7 +4104,17 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos, client->getScript()->on_dignode(nodepos, wasnode)) { return; } - client->removeNode(nodepos); + + const ContentFeatures &f = client->ndef()->get(wasnode); + if (f.node_dig_prediction == "air") { + client->removeNode(nodepos); + } else if (!f.node_dig_prediction.empty()) { + content_t id; + bool found = client->ndef()->getId(f.node_dig_prediction, id); + if (found) + client->addNode(nodepos, id, true); + } + // implicit else: no prediction } client->interact(2, pointed); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index bc03b71e7..e547e31b1 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -335,6 +335,7 @@ void ContentFeatures::reset() color = video::SColor(0xFFFFFFFF); palette_name = ""; palette = NULL; + node_dig_prediction = "air"; } void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const @@ -422,6 +423,8 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const // legacy writeU8(os, legacy_facedir_simple); writeU8(os, legacy_wallmounted); + + os << serializeString(node_dig_prediction); } void ContentFeatures::correctAlpha(TileDef *tiles, int length) @@ -530,6 +533,10 @@ void ContentFeatures::deSerialize(std::istream &is) // read legacy properties legacy_facedir_simple = readU8(is); legacy_wallmounted = readU8(is); + + try { + node_dig_prediction = deSerializeString(is); + } catch(SerializationError &e) {}; } #ifndef SERVER diff --git a/src/nodedef.h b/src/nodedef.h index 1392e51d4..853b9bddd 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -324,6 +324,8 @@ struct ContentFeatures // Player cannot build to these (placement prediction disabled) bool rightclickable; u32 damage_per_second; + // client dig prediction + std::string node_dig_prediction; // --- LIQUID PROPERTIES --- diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 9e1fed2f1..ad92741f8 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -737,6 +737,10 @@ ContentFeatures read_content_features(lua_State *L, int index) } lua_pop(L, 1); + // Node immediately placed by client when node is dug + getstringfield(L, index, "node_dig_prediction", + f.node_dig_prediction); + return f; } @@ -861,6 +865,8 @@ void push_content_features(lua_State *L, const ContentFeatures &c) lua_setfield(L, -2, "legacy_facedir_simple"); lua_pushboolean(L, c.legacy_wallmounted); lua_setfield(L, -2, "legacy_wallmounted"); + lua_pushstring(L, c.node_dig_prediction.c_str()); + lua_setfield(L, -2, "node_dig_prediction"); } /******************************************************************************/