[CSM] Expose more env functions

This commit is contained in:
sfan5 2019-11-09 00:22:42 +01:00
parent b0260b5ec8
commit b57dc70769
7 changed files with 124 additions and 11 deletions

@ -65,6 +65,22 @@ core.register_on_item_use(function(itemstack, pointed_thing)
print("The local player used an item!") print("The local player used an item!")
print("pointed_thing :" .. dump(pointed_thing)) print("pointed_thing :" .. dump(pointed_thing))
print("item = " .. itemstack:get_name()) 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 return false
end) end)
@ -90,11 +106,6 @@ core.register_on_damage_taken(function(hp)
print("[PREVIEW] Damage taken " .. hp) print("[PREVIEW] Damage taken " .. hp)
end) 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 -- This is an example function to ensure it's working properly, should be removed before merge
core.register_chatcommand("dump", { core.register_chatcommand("dump", {
func = function(param) func = function(param)

@ -742,11 +742,46 @@ Call these functions only at load time!
* Returns the node at the given position as table in the format * Returns the node at the given position as table in the format
`{name="node_name", param1=0, param2=0}`, returns `nil` `{name="node_name", param1=0, param2=0}`, returns `nil`
for unloaded areas or flavor limited areas. 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` * `minetest.find_node_near(pos, radius, nodenames, [search_center])`: returns pos or `nil`
* `radius`: using a maximum metric * `radius`: using a maximum metric
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"` * `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
* `search_center` is an optional boolean (default: `false`) * `search_center` is an optional boolean (default: `false`)
If true `pos` is also checked for the nodes 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)` * `minetest.get_meta(pos)`
* Get a `NodeMetaRef` at that position * Get a `NodeMetaRef` at that position
* `minetest.get_node_level(pos)` * `minetest.get_node_level(pos)`
@ -1073,6 +1108,32 @@ Can be obtained via `minetest.get_meta(pos)`.
* `fields`: key-value storage * `fields`: key-value storage
* `inventory`: `{list1 = {}, ...}}` * `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 ### Definitions
* `minetest.get_node_def(nodename)` * `minetest.get_node_def(nodename)`

@ -1337,6 +1337,19 @@ int Client::CSMClampRadius(v3s16 pos, int radius)
return std::min<int>(radius, m_csm_restriction_noderange - distance); 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) void Client::addNode(v3s16 p, MapNode n, bool remove_metadata)
{ {
//TimeTaker timer1("Client::addNode()"); //TimeTaker timer1("Client::addNode()");

@ -264,6 +264,7 @@ public:
// helpers to enforce CSM restrictions // helpers to enforce CSM restrictions
MapNode CSMGetNode(v3s16 p, bool *is_valid_position); MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
int CSMClampRadius(v3s16 pos, int radius); int CSMClampRadius(v3s16 pos, int radius);
v3s16 CSMClampPos(v3s16 pos);
void addNode(v3s16 p, MapNode n, bool remove_metadata = true); void addNode(v3s16 p, MapNode n, bool remove_metadata = true);

@ -51,7 +51,6 @@ public:
protected: protected:
friend class LuaItemStack; friend class LuaItemStack;
friend class ModApiItemMod; friend class ModApiItemMod;
friend class LuaRaycast;
bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr); bool getItemCallback(const char *name, const char *callbackname, const v3s16 *p = nullptr);
/*! /*!

@ -140,17 +140,20 @@ void LuaLBM::trigger(ServerEnvironment *env, v3s16 p, MapNode n)
int LuaRaycast::l_next(lua_State *L) int LuaRaycast::l_next(lua_State *L)
{ {
MAP_LOCK_REQUIRED; MAP_LOCK_REQUIRED;
ScriptApiItem *script = getScriptApi<ScriptApiItem>(L);
GET_ENV_PTR; GET_ENV_PTR;
bool csm = false;
#ifndef SERVER
csm = getClient(L) != nullptr;
#endif
LuaRaycast *o = checkobject(L, 1); LuaRaycast *o = checkobject(L, 1);
PointedThing pointed; PointedThing pointed;
env->continueRaycast(&o->state, &pointed); env->continueRaycast(&o->state, &pointed);
if (pointed.type == POINTEDTHING_NOTHING) if (pointed.type == POINTEDTHING_NOTHING)
lua_pushnil(L); lua_pushnil(L);
else else
script->pushPointedThing(pointed, true); push_pointed_thing(L, pointed, csm, true);
return 1; return 1;
} }
@ -793,11 +796,20 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{ {
GET_ENV_PTR; GET_ENV_PTR;
const NodeDefManager *ndef = getServer(L)->ndef();
v3s16 minp = read_v3s16(L, 1); v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2); v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp); 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; v3s16 cube = maxp - minp + 1;
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000 // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) { 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; GET_ENV_PTR;
const NodeDefManager *ndef = getServer(L)->ndef();
v3s16 minp = read_v3s16(L, 1); v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2); v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp); 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; v3s16 cube = maxp - minp + 1;
// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000 // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) { 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) void ModApiEnvMod::InitializeClient(lua_State *L, int top)
{ {
API_FCT(get_node_light);
API_FCT(get_timeofday); API_FCT(get_timeofday);
API_FCT(get_node_max_level); API_FCT(get_node_max_level);
API_FCT(get_node_level); API_FCT(get_node_level);
API_FCT(find_nodes_with_meta);
API_FCT(find_node_near); 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);
} }

@ -69,6 +69,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
{ {
LuaItemStack::Register(L); LuaItemStack::Register(L);
ItemStackMetaRef::Register(L); ItemStackMetaRef::Register(L);
LuaRaycast::Register(L);
StorageRef::Register(L); StorageRef::Register(L);
LuaMinimap::Register(L); LuaMinimap::Register(L);
NodeMetaRef::RegisterClient(L); NodeMetaRef::RegisterClient(L);