Implement client node dig prediction
authorAuke Kok <sofar@foo-projects.org>
Mon, 11 Sep 2017 12:50:06 +0000 (14:50 +0200)
committersfan5 <sfan5@live.de>
Mon, 11 Sep 2017 18:54:20 +0000 (20:54 +0200)
Dig prediction allows clients to remove dug nodes without
waiting for server acknowledgement.
This patch allows mods to override dig prediction,
it can either be turned off or a different "prediction node"
can be selected.

doc/lua_api.txt
src/game.cpp
src/nodedef.cpp
src/nodedef.h
src/script/common/c_content.cpp

index 6bdb63ef3008b88e7cc743f2c166bef7bfed3780..9a5754368e5c4706a951ec2bb566ee6ceb243dbe 100644 (file)
@@ -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 = --[[<SimpleSoundSpec>]],
index 04688e476133633e21cf1897d9d45cb0bb874cc0..d85e34d35a1e1d1f8b247c9323ee4391d5645147 100644 (file)
@@ -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);
index bc03b71e75f361e8ec16a78af0b85a8684e66925..e547e31b131db5b74375ade37727940e9268ec82 100644 (file)
@@ -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
index 1392e51d41005cfb93d9d905cf35f62930d65f64..853b9bdddeb199025854871b2457dfbbe57afffb 100644 (file)
@@ -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 ---
 
index 9e1fed2f11cc054433db120737ec1584ea7fef7c..ad92741f85797876b1f8ac59fef0a6dcc74fbc9e 100644 (file)
@@ -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");
 }
 
 /******************************************************************************/