Skip to content

Commit

Permalink
[CSM] Expose more env functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sfan5 committed Nov 11, 2019
1 parent b0260b5 commit b57dc70
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 11 deletions.
21 changes: 16 additions & 5 deletions clientmods/preview/init.lua
Expand Up @@ -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)

Expand All @@ -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)
Expand Down
61 changes: 61 additions & 0 deletions doc/client_lua_api.txt
Expand Up @@ -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)`
Expand Down Expand Up @@ -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)`
Expand Down
13 changes: 13 additions & 0 deletions src/client/client.cpp
Expand Up @@ -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()");
Expand Down
1 change: 1 addition & 0 deletions src/client/client.h
Expand Up @@ -264,6 +264,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
// 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);

Expand Down
1 change: 0 additions & 1 deletion src/script/cpp_api/s_item.h
Expand Up @@ -51,7 +51,6 @@ class ScriptApiItem
protected:
friend class LuaItemStack;
friend class ModApiItemMod;
friend class LuaRaycast;

bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr);
/*!
Expand Down
37 changes: 32 additions & 5 deletions src/script/lua_api/l_env.cpp
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
1 change: 1 addition & 0 deletions src/script/scripting_client.cpp
Expand Up @@ -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);
Expand Down

0 comments on commit b57dc70

Please sign in to comment.