[CSM] Expose more env functions
authorsfan5 <sfan5@live.de>
Fri, 8 Nov 2019 23:22:42 +0000 (00:22 +0100)
committersfan5 <sfan5@live.de>
Mon, 11 Nov 2019 13:06:48 +0000 (14:06 +0100)
clientmods/preview/init.lua
doc/client_lua_api.txt
src/client/client.cpp
src/client/client.h
src/script/cpp_api/s_item.h
src/script/lua_api/l_env.cpp
src/script/scripting_client.cpp

index c1358b1c14f4d76257b084846c03e3ad759a485f..96deae0749a79a01a2049748a94f615f74fca29f 100644 (file)
@@ -65,6 +65,22 @@ core.register_on_item_use(function(itemstack, pointed_thing)
        print("The local player used an item!")
        print("pointed_thing :" .. dump(pointed_thing))
        print("item = " .. itemstack:get_name())
+
+       local pos = vector.add(core.localplayer:get_pos(), core.camera:get_offset())
+       local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 100))
+
+       local rc = core.raycast(pos, pos2)
+       local i = rc:next()
+       print("[PREVIEW] raycast next: " .. dump(i))
+       if i then
+               print("[PREVIEW] line of sight: " .. (core.line_of_sight(pos, i.above) and "yes" or "no"))
+
+               local n1 = core.find_nodes_in_area(pos, i.under, {"default:stone"})
+               local n2 = core.find_nodes_in_area_under_air(pos, i.under, {"default:stone"})
+               print(("[PREVIEW] found %s nodes, %s nodes under air"):format(
+                               n1 and #n1 or "?", n2 and #n2 or "?"))
+       end
+
        return false
 end)
 
@@ -90,11 +106,6 @@ core.register_on_damage_taken(function(hp)
        print("[PREVIEW] Damage taken " .. hp)
 end)
 
--- This is an example function to ensure it's working properly, should be removed before merge
-core.register_globalstep(function(dtime)
-       -- print("[PREVIEW] globalstep " .. dtime)
-end)
-
 -- This is an example function to ensure it's working properly, should be removed before merge
 core.register_chatcommand("dump", {
        func = function(param)
index a71421747ff5380482bef2668386fa7beb9f3eae..78cd2ead28988c92c4ff6b17761932ece4d73fbd 100644 (file)
@@ -742,11 +742,46 @@ Call these functions only at load time!
     * Returns the node at the given position as table in the format
       `{name="node_name", param1=0, param2=0}`, returns `nil`
       for unloaded areas or flavor limited areas.
+* `minetest.get_node_light(pos, timeofday)`
+    * Gets the light value at the given position. Note that the light value
+      "inside" the node at the given position is returned, so you usually want
+      to get the light value of a neighbor.
+    * `pos`: The position where to measure the light.
+    * `timeofday`: `nil` for current time, `0` for night, `0.5` for day
+    * Returns a number between `0` and `15` or `nil`
 * `minetest.find_node_near(pos, radius, nodenames, [search_center])`: returns pos or `nil`
     * `radius`: using a maximum metric
     * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
     * `search_center` is an optional boolean (default: `false`)
       If true `pos` is also checked for the nodes
+* `minetest.find_nodes_in_area(pos1, pos2, nodenames)`: returns a list of
+  positions.
+    * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
+    * First return value: Table with all node positions
+    * Second return value: Table with the count of each node with the node name
+      as index.
+    * Area volume is limited to 4,096,000 nodes
+* `minetest.find_nodes_in_area_under_air(pos1, pos2, nodenames)`: returns a
+  list of positions.
+    * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
+    * Return value: Table with all node positions with a node air above
+    * Area volume is limited to 4,096,000 nodes
+* `minetest.line_of_sight(pos1, pos2)`: returns `boolean, pos`
+    * Checks if there is anything other than air between pos1 and pos2.
+    * Returns false if something is blocking the sight.
+    * Returns the position of the blocking node when `false`
+    * `pos1`: First position
+    * `pos2`: Second position
+* `minetest.raycast(pos1, pos2, objects, liquids)`: returns `Raycast`
+    * Creates a `Raycast` object.
+    * `pos1`: start of the ray
+    * `pos2`: end of the ray
+    * `objects`: if false, only nodes will be returned. Default is `true`.
+    * `liquids`: if false, liquid nodes won't be returned. Default is `false`.
+
+* `minetest.find_nodes_with_meta(pos1, pos2)`
+    * Get a table of positions of nodes that have metadata within a region
+      {pos1, pos2}.
 * `minetest.get_meta(pos)`
     * Get a `NodeMetaRef` at that position
 * `minetest.get_node_level(pos)`
@@ -1073,6 +1108,32 @@ Can be obtained via `minetest.get_meta(pos)`.
     * `fields`: key-value storage
     * `inventory`: `{list1 = {}, ...}}`
 
+### `Raycast`
+
+A raycast on the map. It works with selection boxes.
+Can be used as an iterator in a for loop as:
+
+    local ray = Raycast(...)
+    for pointed_thing in ray do
+        ...
+    end
+
+The map is loaded as the ray advances. If the map is modified after the
+`Raycast` is created, the changes may or may not have an effect on the object.
+
+It can be created via `Raycast(pos1, pos2, objects, liquids)` or
+`minetest.raycast(pos1, pos2, objects, liquids)` where:
+
+* `pos1`: start of the ray
+* `pos2`: end of the ray
+* `objects`: if false, only nodes will be returned. Default is true.
+* `liquids`: if false, liquid nodes won't be returned. Default is false.
+
+#### Methods
+
+* `next()`: returns a `pointed_thing` with exact pointing location
+    * Returns the next thing pointed by the ray or nil.
+
 -----------------
 ### Definitions
 * `minetest.get_node_def(nodename)`
index 89873ade39dec6ed24f83a3d4143bc6bb351ec39..36d4f8df99d6b089cda24b4356f94738205d7fa5 100644 (file)
@@ -1337,6 +1337,19 @@ int Client::CSMClampRadius(v3s16 pos, int radius)
        return std::min<int>(radius, m_csm_restriction_noderange - distance);
 }
 
+v3s16 Client::CSMClampPos(v3s16 pos)
+{
+       if (!checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_LOOKUP_NODES))
+               return pos;
+       v3s16 ppos = floatToInt(m_env.getLocalPlayer()->getPosition(), BS);
+       const int range = m_csm_restriction_noderange;
+       return v3s16(
+               core::clamp<int>(pos.X, (int)ppos.X - range, (int)ppos.X + range),
+               core::clamp<int>(pos.Y, (int)ppos.Y - range, (int)ppos.Y + range),
+               core::clamp<int>(pos.Z, (int)ppos.Z - range, (int)ppos.Z + range)
+       );
+}
+
 void Client::addNode(v3s16 p, MapNode n, bool remove_metadata)
 {
        //TimeTaker timer1("Client::addNode()");
index 5f33625094e46630fb783820ccdafe20cfe7ebca..5144af69fe7ca4b37903e65af7ce87807429b1f9 100644 (file)
@@ -264,6 +264,7 @@ public:
        // helpers to enforce CSM restrictions
        MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
        int CSMClampRadius(v3s16 pos, int radius);
+       v3s16 CSMClampPos(v3s16 pos);
 
        void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
 
index ad229f73e18c9da62f9fec238a4f926796caccd2..25a3501f984afb96b2144ece575d59654e55695e 100644 (file)
@@ -51,7 +51,6 @@ public:
 protected:
        friend class LuaItemStack;
        friend class ModApiItemMod;
-       friend class LuaRaycast;
 
        bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr);
        /*!
index 203ffcfdc423c746cb5fc872c9deb2dd7110d7a2..762612af488cd1b524b96d88fd07863eb80d2658 100644 (file)
@@ -140,17 +140,20 @@ void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
 int LuaRaycast::l_next(lua_State *L)
 {
        MAP_LOCK_REQUIRED;
-
-       ScriptApiItem *script = getScriptApi<ScriptApiItem>(L);
        GET_ENV_PTR;
 
+       bool csm = false;
+#ifndef SERVER
+       csm = getClient(L) != nullptr;
+#endif
+
        LuaRaycast *o = checkobject(L, 1);
        PointedThing pointed;
        env->continueRaycast(&o->state, &pointed);
        if (pointed.type == POINTEDTHING_NOTHING)
                lua_pushnil(L);
        else
-               script->pushPointedThing(pointed, true);
+               push_pointed_thing(L, pointed, csm, true);
 
        return 1;
 }
@@ -793,11 +796,20 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 {
        GET_ENV_PTR;
 
-       const NodeDefManager *ndef = getServer(L)->ndef();
        v3s16 minp = read_v3s16(L, 1);
        v3s16 maxp = read_v3s16(L, 2);
        sortBoxVerticies(minp, maxp);
 
+#ifndef SERVER
+       const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
+       if (getClient(L)) {
+               minp = getClient(L)->CSMClampPos(minp);
+               maxp = getClient(L)->CSMClampPos(maxp);
+       }
+#else
+       const NodeDefManager *ndef = getServer(L)->ndef();
+#endif
+
        v3s16 cube = maxp - minp + 1;
        // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
        if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
@@ -861,11 +873,20 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
 
        GET_ENV_PTR;
 
-       const NodeDefManager *ndef = getServer(L)->ndef();
        v3s16 minp = read_v3s16(L, 1);
        v3s16 maxp = read_v3s16(L, 2);
        sortBoxVerticies(minp, maxp);
 
+#ifndef SERVER
+       const NodeDefManager *ndef = getClient(L) ? getClient(L)->ndef() : getServer(L)->ndef();
+       if (getClient(L)) {
+               minp = getClient(L)->CSMClampPos(minp);
+               maxp = getClient(L)->CSMClampPos(maxp);
+       }
+#else
+       const NodeDefManager *ndef = getServer(L)->ndef();
+#endif
+
        v3s16 cube = maxp - minp + 1;
        // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
        if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
@@ -1326,8 +1347,14 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
 
 void ModApiEnvMod::InitializeClient(lua_State *L, int top)
 {
+       API_FCT(get_node_light);
        API_FCT(get_timeofday);
        API_FCT(get_node_max_level);
        API_FCT(get_node_level);
+       API_FCT(find_nodes_with_meta);
        API_FCT(find_node_near);
+       API_FCT(find_nodes_in_area);
+       API_FCT(find_nodes_in_area_under_air);
+       API_FCT(line_of_sight);
+       API_FCT(raycast);
 }
index c3e0ca373bb1adb8b9564ad70e987e328383b4f3..1288b1df756bfed704341deacd59dcb6d38bbd32 100644 (file)
@@ -69,6 +69,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
 {
        LuaItemStack::Register(L);
        ItemStackMetaRef::Register(L);
+       LuaRaycast::Register(L);
        StorageRef::Register(L);
        LuaMinimap::Register(L);
        NodeMetaRef::RegisterClient(L);