mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-02 16:38:41 +00:00
Merge branch 'minetest:master' into master
This commit is contained in:
commit
a8163f6d25
27 changed files with 319 additions and 76 deletions
|
@ -272,3 +272,29 @@ function core.get_globals_to_transfer()
|
||||||
}
|
}
|
||||||
return all
|
return all
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local function valid_object_iterator(objects)
|
||||||
|
local i = 0
|
||||||
|
local function next_valid_object()
|
||||||
|
i = i + 1
|
||||||
|
local obj = objects[i]
|
||||||
|
if obj == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if obj:is_valid() then
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
return next_valid_object()
|
||||||
|
end
|
||||||
|
return next_valid_object
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.objects_inside_radius(center, radius)
|
||||||
|
return valid_object_iterator(core.get_objects_inside_radius(center, radius))
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.objects_in_area(min_pos, max_pos)
|
||||||
|
return valid_object_iterator(core.get_objects_in_area(min_pos, max_pos))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -114,11 +114,11 @@ always_fly_fast (Always fly fast) bool true
|
||||||
# the place button.
|
# the place button.
|
||||||
#
|
#
|
||||||
# Requires: keyboard_mouse
|
# Requires: keyboard_mouse
|
||||||
repeat_place_time (Place repetition interval) float 0.25 0.15 2.0
|
repeat_place_time (Place repetition interval) float 0.25 0.16 2.0
|
||||||
|
|
||||||
# The minimum time in seconds it takes between digging nodes when holding
|
# The minimum time in seconds it takes between digging nodes when holding
|
||||||
# the dig button.
|
# the dig button.
|
||||||
repeat_dig_time (Dig repetition interval) float 0.15 0.15 2.0
|
repeat_dig_time (Minimum dig repetition interval) float 0.0 0.0 2.0
|
||||||
|
|
||||||
# Automatically jump up single-node obstacles.
|
# Automatically jump up single-node obstacles.
|
||||||
autojump (Automatic jumping) bool false
|
autojump (Automatic jumping) bool false
|
||||||
|
|
|
@ -2352,9 +2352,12 @@ for this group, and unable to dig the rating `1`, which is the toughest.
|
||||||
Unless there is a matching group that enables digging otherwise.
|
Unless there is a matching group that enables digging otherwise.
|
||||||
|
|
||||||
If the result digging time is 0, a delay of 0.15 seconds is added between
|
If the result digging time is 0, a delay of 0.15 seconds is added between
|
||||||
digging nodes; If the player releases LMB after digging, this delay is set to 0,
|
digging nodes. If the player releases LMB after digging, this delay is set to 0,
|
||||||
i.e. players can more quickly click the nodes away instead of holding LMB.
|
i.e. players can more quickly click the nodes away instead of holding LMB.
|
||||||
|
|
||||||
|
This extra delay is not applied in case of a digging time between 0 and 0.15,
|
||||||
|
so a digging time of 0.01 is actually faster than a digging time of 0.
|
||||||
|
|
||||||
### Damage groups
|
### Damage groups
|
||||||
|
|
||||||
List of damage for groups of entities. See [Entity damage mechanism].
|
List of damage for groups of entities. See [Entity damage mechanism].
|
||||||
|
@ -3245,7 +3248,7 @@ Elements
|
||||||
* Types: `text`, `image`, `color`, `indent`, `tree`
|
* Types: `text`, `image`, `color`, `indent`, `tree`
|
||||||
* `text`: show cell contents as text
|
* `text`: show cell contents as text
|
||||||
* `image`: cell contents are an image index, use column options to define
|
* `image`: cell contents are an image index, use column options to define
|
||||||
images.
|
images. images are scaled down to fit the row height if necessary.
|
||||||
* `color`: cell contents are a ColorString and define color of following
|
* `color`: cell contents are a ColorString and define color of following
|
||||||
cell.
|
cell.
|
||||||
* `indent`: cell contents are a number and define indentation of following
|
* `indent`: cell contents are a number and define indentation of following
|
||||||
|
@ -3266,7 +3269,7 @@ Elements
|
||||||
* `0=<value>` sets image for image index 0
|
* `0=<value>` sets image for image index 0
|
||||||
* `1=<value>` sets image for image index 1
|
* `1=<value>` sets image for image index 1
|
||||||
* `2=<value>` sets image for image index 2
|
* `2=<value>` sets image for image index 2
|
||||||
* and so on; defined indices need not be contiguous empty or
|
* and so on; defined indices need not be contiguous. empty or
|
||||||
non-numeric cells are treated as `0`.
|
non-numeric cells are treated as `0`.
|
||||||
* `color` column options:
|
* `color` column options:
|
||||||
* `span=<value>`: number of following columns to affect
|
* `span=<value>`: number of following columns to affect
|
||||||
|
@ -6130,12 +6133,24 @@ Environment access
|
||||||
* Items can be added also to unloaded and non-generated blocks.
|
* Items can be added also to unloaded and non-generated blocks.
|
||||||
* `minetest.get_player_by_name(name)`: Get an `ObjectRef` to a player
|
* `minetest.get_player_by_name(name)`: Get an `ObjectRef` to a player
|
||||||
* Returns nothing in case of error (player offline, doesn't exist, ...).
|
* Returns nothing in case of error (player offline, doesn't exist, ...).
|
||||||
* `minetest.get_objects_inside_radius(pos, radius)`
|
* `minetest.get_objects_inside_radius(center, radius)`
|
||||||
* returns a list of ObjectRefs.
|
* returns a list of ObjectRefs
|
||||||
* `radius`: using a Euclidean metric
|
* `radius`: using a Euclidean metric
|
||||||
* `minetest.get_objects_in_area(pos1, pos2)`
|
* **Warning**: Any kind of interaction with the environment or other APIs
|
||||||
* returns a list of ObjectRefs.
|
can cause later objects in the list to become invalid while you're iterating it.
|
||||||
* `pos1` and `pos2` are the min and max positions of the area to search.
|
(e.g. punching an entity removes its children)
|
||||||
|
It is recommended to use `minetest.objects_inside_radius` instead, which
|
||||||
|
transparently takes care of this possibility.
|
||||||
|
* `minetest.objects_inside_radius(center, radius)`
|
||||||
|
* returns an iterator of valid objects
|
||||||
|
* example: `for obj in minetest.objects_inside_radius(center, radius) do obj:punch(...) end`
|
||||||
|
* `minetest.get_objects_in_area(min_pos, max_pos)`
|
||||||
|
* returns a list of ObjectRefs
|
||||||
|
* `min_pos` and `max_pos` are the min and max positions of the area to search
|
||||||
|
* **Warning**: The same warning as for `minetest.get_objects_inside_radius` applies.
|
||||||
|
Use `minetest.objects_in_area` instead to iterate only valid objects.
|
||||||
|
* `minetest.objects_in_area(min_pos, max_pos)`
|
||||||
|
* returns an iterator of valid objects
|
||||||
* `minetest.set_timeofday(val)`: set time of day
|
* `minetest.set_timeofday(val)`: set time of day
|
||||||
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
|
* `val` is between `0` and `1`; `0` for midnight, `0.5` for midday
|
||||||
* `minetest.get_timeofday()`: get time of day
|
* `minetest.get_timeofday()`: get time of day
|
||||||
|
@ -6727,6 +6742,7 @@ This allows you easy interoperability for delegating work to jobs.
|
||||||
### List of APIs available in an async environment
|
### List of APIs available in an async environment
|
||||||
|
|
||||||
Classes:
|
Classes:
|
||||||
|
|
||||||
* `AreaStore`
|
* `AreaStore`
|
||||||
* `ItemStack`
|
* `ItemStack`
|
||||||
* `PerlinNoise`
|
* `PerlinNoise`
|
||||||
|
@ -6740,17 +6756,20 @@ Classes:
|
||||||
* `Settings`
|
* `Settings`
|
||||||
|
|
||||||
Class instances that can be transferred between environments:
|
Class instances that can be transferred between environments:
|
||||||
|
|
||||||
* `ItemStack`
|
* `ItemStack`
|
||||||
* `PerlinNoise`
|
* `PerlinNoise`
|
||||||
* `PerlinNoiseMap`
|
* `PerlinNoiseMap`
|
||||||
* `VoxelManip`
|
* `VoxelManip`
|
||||||
|
|
||||||
Functions:
|
Functions:
|
||||||
|
|
||||||
* Standalone helpers such as logging, filesystem, encoding,
|
* Standalone helpers such as logging, filesystem, encoding,
|
||||||
hashing or compression APIs
|
hashing or compression APIs
|
||||||
* `minetest.register_async_metatable` (see above)
|
* `minetest.register_async_metatable` (see above)
|
||||||
|
|
||||||
Variables:
|
Variables:
|
||||||
|
|
||||||
* `minetest.settings`
|
* `minetest.settings`
|
||||||
* `minetest.registered_items`, `registered_nodes`, `registered_tools`,
|
* `minetest.registered_items`, `registered_nodes`, `registered_tools`,
|
||||||
`registered_craftitems` and `registered_aliases`
|
`registered_craftitems` and `registered_aliases`
|
||||||
|
@ -6802,6 +6821,7 @@ does not have a global step or timer.
|
||||||
### List of APIs available in the mapgen env
|
### List of APIs available in the mapgen env
|
||||||
|
|
||||||
Classes:
|
Classes:
|
||||||
|
|
||||||
* `AreaStore`
|
* `AreaStore`
|
||||||
* `ItemStack`
|
* `ItemStack`
|
||||||
* `PerlinNoise`
|
* `PerlinNoise`
|
||||||
|
@ -6815,6 +6835,7 @@ Classes:
|
||||||
* `Settings`
|
* `Settings`
|
||||||
|
|
||||||
Functions:
|
Functions:
|
||||||
|
|
||||||
* Standalone helpers such as logging, filesystem, encoding,
|
* Standalone helpers such as logging, filesystem, encoding,
|
||||||
hashing or compression APIs
|
hashing or compression APIs
|
||||||
* `minetest.get_biome_id`, `get_biome_name`, `get_heat`, `get_humidity`,
|
* `minetest.get_biome_id`, `get_biome_name`, `get_heat`, `get_humidity`,
|
||||||
|
@ -6825,6 +6846,7 @@ Functions:
|
||||||
* these only operate on the current chunk (if inside a callback)
|
* these only operate on the current chunk (if inside a callback)
|
||||||
|
|
||||||
Variables:
|
Variables:
|
||||||
|
|
||||||
* `minetest.settings`
|
* `minetest.settings`
|
||||||
* `minetest.registered_items`, `registered_nodes`, `registered_tools`,
|
* `minetest.registered_items`, `registered_nodes`, `registered_tools`,
|
||||||
`registered_craftitems` and `registered_aliases`
|
`registered_craftitems` and `registered_aliases`
|
||||||
|
@ -7797,13 +7819,18 @@ When you receive an `ObjectRef` as a callback argument or from another API
|
||||||
function, it is possible to store the reference somewhere and keep it around.
|
function, it is possible to store the reference somewhere and keep it around.
|
||||||
It will keep functioning until the object is unloaded or removed.
|
It will keep functioning until the object is unloaded or removed.
|
||||||
|
|
||||||
However, doing this is **NOT** recommended as there is (intentionally) no method
|
However, doing this is **NOT** recommended - `ObjectRefs` should be "let go"
|
||||||
to test if a previously acquired `ObjectRef` is still valid.
|
of as soon as control is returned from Lua back to the engine.
|
||||||
Instead, `ObjectRefs` should be "let go" of as soon as control is returned from
|
|
||||||
Lua back to the engine.
|
|
||||||
Doing so is much less error-prone and you will never need to wonder if the
|
Doing so is much less error-prone and you will never need to wonder if the
|
||||||
object you are working with still exists.
|
object you are working with still exists.
|
||||||
|
|
||||||
|
If this is not feasible, you can test whether an `ObjectRef` is still valid
|
||||||
|
via `object:is_valid()`.
|
||||||
|
|
||||||
|
Getters may be called for invalid objects and will return nothing then.
|
||||||
|
All other methods should not be called on invalid objects.
|
||||||
|
|
||||||
### Attachments
|
### Attachments
|
||||||
|
|
||||||
It is possible to attach objects to other objects (`set_attach` method).
|
It is possible to attach objects to other objects (`set_attach` method).
|
||||||
|
@ -7822,6 +7849,8 @@ child will follow movement and rotation of that bone.
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
|
* `is_valid()`: returns whether the object is valid.
|
||||||
|
* See "Advice on handling `ObjectRefs`" above.
|
||||||
* `get_pos()`: returns position as vector `{x=num, y=num, z=num}`
|
* `get_pos()`: returns position as vector `{x=num, y=num, z=num}`
|
||||||
* `set_pos(pos)`:
|
* `set_pos(pos)`:
|
||||||
* Sets the position of the object.
|
* Sets the position of the object.
|
||||||
|
@ -10654,7 +10683,10 @@ Used by `minetest.add_particle`.
|
||||||
texture = "image.png",
|
texture = "image.png",
|
||||||
-- The texture of the particle
|
-- The texture of the particle
|
||||||
-- v5.6.0 and later: also supports the table format described in the
|
-- v5.6.0 and later: also supports the table format described in the
|
||||||
-- following section
|
-- following section, but due to a bug this did not take effect
|
||||||
|
-- (beyond the texture name).
|
||||||
|
-- v5.9.0 and later: fixes the bug.
|
||||||
|
-- Note: "texture.animation" is ignored here. Use "animation" below instead.
|
||||||
|
|
||||||
playername = "singleplayer",
|
playername = "singleplayer",
|
||||||
-- Optional, if specified spawns particle only on the player's client
|
-- Optional, if specified spawns particle only on the player's client
|
||||||
|
|
|
@ -71,7 +71,7 @@ end
|
||||||
-- Mese Pickaxe: special tool that digs "everything" instantly
|
-- Mese Pickaxe: special tool that digs "everything" instantly
|
||||||
minetest.register_tool("basetools:pick_mese", {
|
minetest.register_tool("basetools:pick_mese", {
|
||||||
description = "Mese Pickaxe".."\n"..
|
description = "Mese Pickaxe".."\n"..
|
||||||
"Digs diggable nodes instantly",
|
"Digs diggable nodes instantly.",
|
||||||
inventory_image = "basetools_mesepick.png",
|
inventory_image = "basetools_mesepick.png",
|
||||||
tool_capabilities = {
|
tool_capabilities = {
|
||||||
full_punch_interval = 1.0,
|
full_punch_interval = 1.0,
|
||||||
|
@ -88,6 +88,28 @@ minetest.register_tool("basetools:pick_mese", {
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- A variant of the mese pickaxe that is not affected by the 0.15s digging delay
|
||||||
|
minetest.register_tool("basetools:pick_mese_no_delay", {
|
||||||
|
description = "Mese Pickaxe (no delay)".."\n"..
|
||||||
|
"Digs diggable nodes instantly.".."\n"..
|
||||||
|
"There is no delay between digging each node,\n"..
|
||||||
|
'but the "repeat_dig_time" setting is still respected.',
|
||||||
|
inventory_image = "basetools_mesepick_no_delay.png",
|
||||||
|
tool_capabilities = {
|
||||||
|
full_punch_interval = 1.0,
|
||||||
|
max_drop_level=3,
|
||||||
|
groupcaps={
|
||||||
|
cracky={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
|
||||||
|
crumbly={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
|
||||||
|
snappy={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
|
||||||
|
choppy={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
|
||||||
|
dig_immediate={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
|
||||||
|
},
|
||||||
|
damage_groups = {fleshy=100},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Pickaxes: Dig cracky
|
-- Pickaxes: Dig cracky
|
||||||
--
|
--
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 169 B |
|
@ -64,6 +64,41 @@ local inv_style_fs = [[
|
||||||
list[current_player;main;.5,7;8,4]
|
list[current_player;main;.5,7;8,4]
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
-- Some textures from textures/base/pack and Devtest, with many different sizes
|
||||||
|
-- and aspect ratios.
|
||||||
|
local image_column = "image,0=logo.png,1=rare_controls.png,2=checkbox_16.png," ..
|
||||||
|
"3=checkbox_32.png,4=checkbox_64.png,5=default_lava.png," ..
|
||||||
|
"6=progress_bar.png,7=progress_bar_bg.png"
|
||||||
|
local words = {
|
||||||
|
"esciunt", "repudiandae", "repellat", "voluptatem", "autem", "vitae", "et",
|
||||||
|
"minima", "quasi", "facere", "nihil", "ea", "nemo", "rem", "non", "eos",
|
||||||
|
"laudantium", "eveniet", "veritatis",
|
||||||
|
}
|
||||||
|
|
||||||
|
local reseed = math.random(2^31-1)
|
||||||
|
math.randomseed(1337)
|
||||||
|
|
||||||
|
local table_content = {}
|
||||||
|
for i = 1, 100 do
|
||||||
|
table.insert(table_content, words[math.random(#words)])
|
||||||
|
table.insert(table_content, words[math.random(#words)])
|
||||||
|
table.insert(table_content, words[math.random(#words)])
|
||||||
|
table.insert(table_content, math.random(0, 7))
|
||||||
|
table.insert(table_content, math.random(0, 7))
|
||||||
|
table.insert(table_content, math.random(0, 7))
|
||||||
|
table.insert(table_content, words[math.random(#words)])
|
||||||
|
end
|
||||||
|
|
||||||
|
math.randomseed(reseed)
|
||||||
|
|
||||||
|
local table_fs = table.concat({
|
||||||
|
"tablecolumns[text,align=left;text,align=right;text,align=center;",
|
||||||
|
image_column, ",align=left;",
|
||||||
|
image_column, ",align=right;",
|
||||||
|
image_column, ",align=center;text,align=right]",
|
||||||
|
"table[0,0;17,12;the_table;", table.concat(table_content, ","), ";1]"
|
||||||
|
})
|
||||||
|
|
||||||
local hypertext_basic = [[A hypertext element
|
local hypertext_basic = [[A hypertext element
|
||||||
<bigger>Normal test</bigger>
|
<bigger>Normal test</bigger>
|
||||||
This is a normal text.
|
This is a normal text.
|
||||||
|
@ -350,6 +385,10 @@ local pages = {
|
||||||
"label[11,0.5;Noclip]" ..
|
"label[11,0.5;Noclip]" ..
|
||||||
"container[11.5,1]" .. clip_fs:gsub("%%c", "true") .. "container_end[]",
|
"container[11.5,1]" .. clip_fs:gsub("%%c", "true") .. "container_end[]",
|
||||||
|
|
||||||
|
-- Table
|
||||||
|
"size[18,13]real_coordinates[true]" ..
|
||||||
|
"container[0.5,0.5]" .. table_fs.. "container_end[]",
|
||||||
|
|
||||||
-- Hypertext
|
-- Hypertext
|
||||||
"size[12,13]real_coordinates[true]" ..
|
"size[12,13]real_coordinates[true]" ..
|
||||||
"container[0.5,0.5]" .. hypertext_fs .. "container_end[]",
|
"container[0.5,0.5]" .. hypertext_fs .. "container_end[]",
|
||||||
|
@ -477,7 +516,7 @@ local function show_test_formspec(pname)
|
||||||
page = page()
|
page = page()
|
||||||
end
|
end
|
||||||
|
|
||||||
local fs = page .. "tabheader[0,0;11,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Invs,Window,Anim,Model,ScrollC,Sound,Background,Unsized;" .. page_id .. ";false;false]"
|
local fs = page .. "tabheader[0,0;11,0.65;maintabs;Real Coord,Styles,Noclip,Table,Hypertext,Tabs,Invs,Window,Anim,Model,ScrollC,Sound,Background,Unsized;" .. page_id .. ";false;false]"
|
||||||
|
|
||||||
minetest.show_formspec(pname, "testformspec:formspec", fs)
|
minetest.show_formspec(pname, "testformspec:formspec", fs)
|
||||||
end
|
end
|
||||||
|
|
|
@ -71,13 +71,13 @@ local function test_entity_lifecycle(_, pos)
|
||||||
|
|
||||||
-- with binary in staticdata
|
-- with binary in staticdata
|
||||||
local obj = core.add_entity(pos, "unittests:callbacks", "abc\000def")
|
local obj = core.add_entity(pos, "unittests:callbacks", "abc\000def")
|
||||||
|
assert(obj and obj:is_valid())
|
||||||
check_log({"on_activate(7)"})
|
check_log({"on_activate(7)"})
|
||||||
|
|
||||||
obj:set_hp(0)
|
obj:set_hp(0)
|
||||||
check_log({"on_death(nil)", "on_deactivate(true)"})
|
check_log({"on_death(nil)", "on_deactivate(true)"})
|
||||||
|
|
||||||
-- objectref must be invalid now
|
assert(not obj:is_valid())
|
||||||
assert(obj:get_velocity() == nil)
|
|
||||||
end
|
end
|
||||||
unittests.register("test_entity_lifecycle", test_entity_lifecycle, {map=true})
|
unittests.register("test_entity_lifecycle", test_entity_lifecycle, {map=true})
|
||||||
|
|
||||||
|
@ -130,3 +130,57 @@ local function test_entity_attach(player, pos)
|
||||||
obj:remove()
|
obj:remove()
|
||||||
end
|
end
|
||||||
unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true})
|
unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true})
|
||||||
|
|
||||||
|
core.register_entity("unittests:dummy", {
|
||||||
|
initial_properties = {
|
||||||
|
hp_max = 1,
|
||||||
|
visual = "upright_sprite",
|
||||||
|
textures = { "no_texture.png" },
|
||||||
|
static_save = false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local function test_entity_raycast(_, pos)
|
||||||
|
local obj1 = core.add_entity(pos, "unittests:dummy")
|
||||||
|
local obj2 = core.add_entity(pos:offset(1, 0, 0), "unittests:dummy")
|
||||||
|
local raycast = core.raycast(pos:offset(-1, 0, 0), pos:offset(2, 0, 0), true, false)
|
||||||
|
for pt in raycast do
|
||||||
|
if pt.type == "object" then
|
||||||
|
assert(pt.ref == obj1)
|
||||||
|
obj1:remove()
|
||||||
|
obj2:remove()
|
||||||
|
obj1 = nil -- object should be hit exactly one
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert(obj1 == nil)
|
||||||
|
end
|
||||||
|
unittests.register("test_entity_raycast", test_entity_raycast, {map=true})
|
||||||
|
|
||||||
|
local function test_object_iterator(pos, make_iterator)
|
||||||
|
local obj1 = core.add_entity(pos, "unittests:dummy")
|
||||||
|
local obj2 = core.add_entity(pos, "unittests:dummy")
|
||||||
|
assert(obj1 and obj2)
|
||||||
|
local found = false
|
||||||
|
-- As soon as we find one of the objects, we remove both, invalidating the other.
|
||||||
|
for obj in make_iterator() do
|
||||||
|
assert(obj:is_valid())
|
||||||
|
if obj == obj1 or obj == obj2 then
|
||||||
|
obj1:remove()
|
||||||
|
obj2:remove()
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert(found)
|
||||||
|
end
|
||||||
|
|
||||||
|
unittests.register("test_objects_inside_radius", function(_, pos)
|
||||||
|
test_object_iterator(pos, function()
|
||||||
|
return core.objects_inside_radius(pos, 1)
|
||||||
|
end)
|
||||||
|
end, {map=true})
|
||||||
|
|
||||||
|
unittests.register("test_objects_in_area", function(_, pos)
|
||||||
|
test_object_iterator(pos, function()
|
||||||
|
return core.objects_in_area(pos:offset(-1, -1, -1), pos:offset(1, 1, 1))
|
||||||
|
end)
|
||||||
|
end, {map=true})
|
||||||
|
|
6
lib/lua/README.md
Normal file
6
lib/lua/README.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
## Lua 5.1.5 source
|
||||||
|
|
||||||
|
This copy has been patched with Minetest-specific changes (`lua_atccall`)
|
||||||
|
so it is *not* interchangeable with upstream PUC Lua.
|
||||||
|
|
||||||
|
A patch for CVE-2014-5461 has been applied.
|
|
@ -340,13 +340,14 @@ static int luaB_assert (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
static int luaB_unpack (lua_State *L) {
|
static int luaB_unpack (lua_State *L) {
|
||||||
int i, e, n;
|
int i, e;
|
||||||
|
unsigned int n;
|
||||||
luaL_checktype(L, 1, LUA_TTABLE);
|
luaL_checktype(L, 1, LUA_TTABLE);
|
||||||
i = luaL_optint(L, 2, 1);
|
i = luaL_optint(L, 2, 1);
|
||||||
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
|
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
|
||||||
if (i > e) return 0; /* empty range */
|
if (i > e) return 0; /* empty range */
|
||||||
n = e - i + 1; /* number of elements */
|
n = (unsigned int)e - (unsigned int)i; /* number of elements minus 1 */
|
||||||
if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
|
if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n))
|
||||||
return luaL_error(L, "too many results to unpack");
|
return luaL_error(L, "too many results to unpack");
|
||||||
lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
|
lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
|
||||||
while (i++ < e) /* push arg[i + 1...e] */
|
while (i++ < e) /* push arg[i + 1...e] */
|
||||||
|
|
|
@ -101,6 +101,7 @@ static int db_getinfo (lua_State *L) {
|
||||||
int arg;
|
int arg;
|
||||||
lua_State *L1 = getthread(L, &arg);
|
lua_State *L1 = getthread(L, &arg);
|
||||||
const char *options = luaL_optstring(L, arg+2, "flnSu");
|
const char *options = luaL_optstring(L, arg+2, "flnSu");
|
||||||
|
luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'");
|
||||||
if (lua_isnumber(L, arg+1)) {
|
if (lua_isnumber(L, arg+1)) {
|
||||||
if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
|
if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
|
||||||
lua_pushnil(L); /* level out of range */
|
lua_pushnil(L); /* level out of range */
|
||||||
|
|
|
@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
StkId st, base;
|
StkId st, base;
|
||||||
Proto *p = cl->p;
|
Proto *p = cl->p;
|
||||||
luaD_checkstack(L, p->maxstacksize);
|
luaD_checkstack(L, p->maxstacksize + p->numparams);
|
||||||
func = restorestack(L, funcr);
|
func = restorestack(L, funcr);
|
||||||
if (!p->is_vararg) { /* no varargs? */
|
if (!p->is_vararg) { /* no varargs? */
|
||||||
base = func + 1;
|
base = func + 1;
|
||||||
|
|
|
@ -133,7 +133,7 @@ static void inclinenumber (LexState *ls) {
|
||||||
if (currIsNewline(ls) && ls->current != old)
|
if (currIsNewline(ls) && ls->current != old)
|
||||||
next(ls); /* skip `\n\r' or `\r\n' */
|
next(ls); /* skip `\n\r' or `\r\n' */
|
||||||
if (++ls->linenumber >= MAX_INT)
|
if (++ls->linenumber >= MAX_INT)
|
||||||
luaX_syntaxerror(ls, "chunk has too many lines");
|
luaX_lexerror(ls, "chunk has too many lines", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -209,14 +209,15 @@ static int l_strcmp (const TString *ls, const TString *rs) {
|
||||||
int temp = strcoll(l, r);
|
int temp = strcoll(l, r);
|
||||||
if (temp != 0) return temp;
|
if (temp != 0) return temp;
|
||||||
else { /* strings are equal up to a `\0' */
|
else { /* strings are equal up to a `\0' */
|
||||||
size_t len = strlen(l); /* index of first `\0' in both strings */
|
size_t zl1 = strlen(l); /* index of first '\0' in 'l' */
|
||||||
if (len == lr) /* r is finished? */
|
size_t zl2 = strlen(r); /* index of first '\0' in 'r' */
|
||||||
return (len == ll) ? 0 : 1;
|
if (zl2 == lr) /* 'r' is finished? */
|
||||||
else if (len == ll) /* l is finished? */
|
return (zl1 == ll) ? 0 : 1; /* check 'l' */
|
||||||
return -1; /* l is smaller than r (because r is not finished) */
|
else if (zl1 == ll) /* 'l' is finished? */
|
||||||
/* both strings longer than `len'; go on comparing (after the `\0') */
|
return -1; /* 'l' is less than 'r' ('r' is not finished) */
|
||||||
len++;
|
/* both strings longer than 'zl'; go on comparing after the '\0' */
|
||||||
l += len; ll -= len; r += len; lr -= len;
|
zl1++; zl2++;
|
||||||
|
l += zl1; ll -= zl1; r += zl2; lr -= zl2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3987,8 +3987,12 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
|
||||||
runData.nodig_delay_timer =
|
runData.nodig_delay_timer =
|
||||||
runData.dig_time_complete / (float)crack_animation_length;
|
runData.dig_time_complete / (float)crack_animation_length;
|
||||||
|
|
||||||
// Don't add a corresponding delay to very time consuming nodes.
|
// We don't want a corresponding delay to very time consuming nodes
|
||||||
runData.nodig_delay_timer = std::min(runData.nodig_delay_timer, 0.3f);
|
// and nodes without digging time (e.g. torches) get a fixed delay.
|
||||||
|
if (runData.nodig_delay_timer > 0.3f)
|
||||||
|
runData.nodig_delay_timer = 0.3f;
|
||||||
|
else if (runData.dig_instantly)
|
||||||
|
runData.nodig_delay_timer = 0.15f;
|
||||||
|
|
||||||
// Ensure that the delay between breaking nodes
|
// Ensure that the delay between breaking nodes
|
||||||
// (dig_time_complete + nodig_delay_timer) is at least the
|
// (dig_time_complete + nodig_delay_timer) is at least the
|
||||||
|
@ -4392,8 +4396,8 @@ void Game::readSettings()
|
||||||
m_cache_enable_fog = g_settings->getBool("enable_fog");
|
m_cache_enable_fog = g_settings->getBool("enable_fog");
|
||||||
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity", 0.001f, 10.0f);
|
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity", 0.001f, 10.0f);
|
||||||
m_cache_joystick_frustum_sensitivity = std::max(g_settings->getFloat("joystick_frustum_sensitivity"), 0.001f);
|
m_cache_joystick_frustum_sensitivity = std::max(g_settings->getFloat("joystick_frustum_sensitivity"), 0.001f);
|
||||||
m_repeat_place_time = g_settings->getFloat("repeat_place_time", 0.15f, 2.0f);
|
m_repeat_place_time = g_settings->getFloat("repeat_place_time", 0.16f, 2.0f);
|
||||||
m_repeat_dig_time = g_settings->getFloat("repeat_dig_time", 0.15f, 2.0f);
|
m_repeat_dig_time = g_settings->getFloat("repeat_dig_time", 0.0f, 2.0f);
|
||||||
|
|
||||||
m_cache_enable_noclip = g_settings->getBool("noclip");
|
m_cache_enable_noclip = g_settings->getBool("noclip");
|
||||||
m_cache_enable_free_move = g_settings->getBool("free_move");
|
m_cache_enable_free_move = g_settings->getBool("free_move");
|
||||||
|
|
|
@ -359,7 +359,7 @@ void set_default_settings()
|
||||||
settings->setDefault("invert_hotbar_mouse_wheel", "false");
|
settings->setDefault("invert_hotbar_mouse_wheel", "false");
|
||||||
settings->setDefault("mouse_sensitivity", "0.2");
|
settings->setDefault("mouse_sensitivity", "0.2");
|
||||||
settings->setDefault("repeat_place_time", "0.25");
|
settings->setDefault("repeat_place_time", "0.25");
|
||||||
settings->setDefault("repeat_dig_time", "0.15");
|
settings->setDefault("repeat_dig_time", "0.0");
|
||||||
settings->setDefault("safe_dig_and_place", "false");
|
settings->setDefault("safe_dig_and_place", "false");
|
||||||
settings->setDefault("random_input", "false");
|
settings->setDefault("random_input", "false");
|
||||||
settings->setDefault("aux1_descends", "false");
|
settings->setDefault("aux1_descends", "false");
|
||||||
|
|
|
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <IGUIFont.h>
|
#include <IGUIFont.h>
|
||||||
#include "client/renderingengine.h"
|
#include "client/renderingengine.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "irrlicht_changes/CGUITTFont.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "client/texturesource.h"
|
#include "client/texturesource.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
|
@ -227,6 +228,8 @@ void GUITable::setTable(const TableOptions &options,
|
||||||
s32 content_index;
|
s32 content_index;
|
||||||
// Next cell: Width in pixels
|
// Next cell: Width in pixels
|
||||||
s32 content_width;
|
s32 content_width;
|
||||||
|
// Next cell: Image scale (only for "image" column type)
|
||||||
|
f32 image_scale;
|
||||||
// Vector of completed cells in this row
|
// Vector of completed cells in this row
|
||||||
std::vector<Cell> cells;
|
std::vector<Cell> cells;
|
||||||
// Stores colors and how long they last (maximum column index)
|
// Stores colors and how long they last (maximum column index)
|
||||||
|
@ -236,6 +239,17 @@ void GUITable::setTable(const TableOptions &options,
|
||||||
};
|
};
|
||||||
TempRow *rows = new TempRow[rowcount];
|
TempRow *rows = new TempRow[rowcount];
|
||||||
|
|
||||||
|
CGUITTFont *ttfont = dynamic_cast<CGUITTFont *>(m_font);
|
||||||
|
f32 desired_image_scale = 1.0f;
|
||||||
|
if (ttfont) {
|
||||||
|
// This gives us the effective font size, which is chosen taking display
|
||||||
|
// density and gui_scaling into account.
|
||||||
|
// Since row height scales with font size, this gives better results than
|
||||||
|
// just using display density and gui_scaling when a non-standard font
|
||||||
|
// size is used (e.g. Android default of 14).
|
||||||
|
desired_image_scale = std::max(1.0f, ttfont->getFontSize() / 16.0f);
|
||||||
|
}
|
||||||
|
|
||||||
// Get em width. Pedantically speaking, the width of "M" is not
|
// Get em width. Pedantically speaking, the width of "M" is not
|
||||||
// necessarily the same as the em width, but whatever, close enough.
|
// necessarily the same as the em width, but whatever, close enough.
|
||||||
s32 em = 6;
|
s32 em = 6;
|
||||||
|
@ -373,8 +387,18 @@ void GUITable::setTable(const TableOptions &options,
|
||||||
if (row->content_index >= 0)
|
if (row->content_index >= 0)
|
||||||
image = m_images[row->content_index];
|
image = m_images[row->content_index];
|
||||||
|
|
||||||
|
row->image_scale = 1.0f;
|
||||||
|
row->content_width = 0;
|
||||||
|
if (image) {
|
||||||
|
f32 max_image_scale = (f32)m_rowheight / (f32)image->getOriginalSize().Height;
|
||||||
|
// Scale with display density and make sure it fits into the row
|
||||||
|
row->image_scale = std::min(desired_image_scale, max_image_scale);
|
||||||
|
// When upscaling, fractional factors would cause artifacts
|
||||||
|
if (row->image_scale > 1.0f)
|
||||||
|
row->image_scale = std::floor(row->image_scale);
|
||||||
|
row->content_width = image->getOriginalSize().Width * row->image_scale;
|
||||||
|
}
|
||||||
// Get content width and update xmax
|
// Get content width and update xmax
|
||||||
row->content_width = image ? image->getOriginalSize().Width : 0;
|
|
||||||
row->content_width = MYMAX(row->content_width, width);
|
row->content_width = MYMAX(row->content_width, width);
|
||||||
s32 row_xmax = row->x + padding + row->content_width;
|
s32 row_xmax = row->x + padding + row->content_width;
|
||||||
xmax = MYMAX(xmax, row_xmax);
|
xmax = MYMAX(xmax, row_xmax);
|
||||||
|
@ -384,6 +408,7 @@ void GUITable::setTable(const TableOptions &options,
|
||||||
newcell.xmin = rows[i].x + padding;
|
newcell.xmin = rows[i].x + padding;
|
||||||
alignContent(&newcell, xmax, rows[i].content_width, align);
|
alignContent(&newcell, xmax, rows[i].content_width, align);
|
||||||
newcell.content_index = rows[i].content_index;
|
newcell.content_index = rows[i].content_index;
|
||||||
|
newcell.image_scale = rows[i].image_scale;
|
||||||
rows[i].cells.push_back(newcell);
|
rows[i].cells.push_back(newcell);
|
||||||
rows[i].x = newcell.xmax;
|
rows[i].x = newcell.xmax;
|
||||||
}
|
}
|
||||||
|
@ -740,23 +765,23 @@ void GUITable::drawCell(const Cell *cell, video::SColor color,
|
||||||
video::ITexture *image = m_images[cell->content_index];
|
video::ITexture *image = m_images[cell->content_index];
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
core::position2d<s32> dest_pos =
|
|
||||||
row_rect.UpperLeftCorner;
|
|
||||||
dest_pos.X += cell->xpos;
|
|
||||||
core::rect<s32> source_rect(
|
core::rect<s32> source_rect(
|
||||||
core::position2d<s32>(0, 0),
|
core::position2d<s32>(0, 0),
|
||||||
image->getOriginalSize());
|
image->getOriginalSize());
|
||||||
s32 imgh = source_rect.LowerRightCorner.Y;
|
core::rect<s32> dest_rect(
|
||||||
|
0, 0,
|
||||||
|
image->getOriginalSize().Width * cell->image_scale,
|
||||||
|
image->getOriginalSize().Height * cell->image_scale);
|
||||||
|
dest_rect += row_rect.UpperLeftCorner + v2s32(cell->xpos, 0);
|
||||||
|
|
||||||
|
s32 imgh = dest_rect.getHeight();
|
||||||
s32 rowh = row_rect.getHeight();
|
s32 rowh = row_rect.getHeight();
|
||||||
|
// Center vertically if needed
|
||||||
if (imgh < rowh)
|
if (imgh < rowh)
|
||||||
dest_pos.Y += (rowh - imgh) / 2;
|
dest_rect += v2s32(0, (rowh - imgh) / 2);
|
||||||
else
|
|
||||||
source_rect.LowerRightCorner.Y = rowh;
|
|
||||||
|
|
||||||
video::SColor color(255, 255, 255, 255);
|
driver->draw2DImage(image, dest_rect, source_rect,
|
||||||
|
&client_clip, nullptr, true);
|
||||||
driver->draw2DImage(image, dest_pos, source_rect,
|
|
||||||
&client_clip, color, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,7 @@ protected:
|
||||||
video::SColor color;
|
video::SColor color;
|
||||||
bool color_defined;
|
bool color_defined;
|
||||||
s32 reported_column;
|
s32 reported_column;
|
||||||
|
f32 image_scale; // only for "image" type columns
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Row {
|
struct Row {
|
||||||
|
|
|
@ -59,14 +59,8 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
|
||||||
m_menumgr(menumgr),
|
m_menumgr(menumgr),
|
||||||
m_remap_click_outside(remap_click_outside)
|
m_remap_click_outside(remap_click_outside)
|
||||||
{
|
{
|
||||||
m_gui_scale = std::max(g_settings->getFloat("gui_scaling"), 0.5f);
|
m_gui_scale = g_settings->getFloat("gui_scaling", 0.5f, 20.0f) *
|
||||||
const float screen_dpi_scale = RenderingEngine::getDisplayDensity();
|
RenderingEngine::getDisplayDensity();
|
||||||
|
|
||||||
if (g_settings->getBool("enable_touch")) {
|
|
||||||
m_gui_scale *= 1.1f - 0.3f * screen_dpi_scale + 0.2f * screen_dpi_scale * screen_dpi_scale;
|
|
||||||
} else {
|
|
||||||
m_gui_scale *= screen_dpi_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
m_menumgr->createdMenu(this);
|
m_menumgr->createdMenu(this);
|
||||||
|
|
|
@ -197,7 +197,8 @@ enum class ParticleTextureFlags : u8 {
|
||||||
* decltype everywhere */
|
* decltype everywhere */
|
||||||
using FlagT = std::underlying_type_t<ParticleTextureFlags>;
|
using FlagT = std::underlying_type_t<ParticleTextureFlags>;
|
||||||
|
|
||||||
void ServerParticleTexture::serialize(std::ostream &os, u16 protocol_ver, bool newPropertiesOnly) const
|
void ServerParticleTexture::serialize(std::ostream &os, u16 protocol_ver,
|
||||||
|
bool newPropertiesOnly, bool skipAnimation) const
|
||||||
{
|
{
|
||||||
/* newPropertiesOnly is used to de/serialize parameters of the legacy texture
|
/* newPropertiesOnly is used to de/serialize parameters of the legacy texture
|
||||||
* field, which are encoded separately from the texspec string */
|
* field, which are encoded separately from the texspec string */
|
||||||
|
@ -213,14 +214,19 @@ void ServerParticleTexture::serialize(std::ostream &os, u16 protocol_ver, bool n
|
||||||
if (!newPropertiesOnly)
|
if (!newPropertiesOnly)
|
||||||
os << serializeString32(string);
|
os << serializeString32(string);
|
||||||
|
|
||||||
if (animated)
|
if (!skipAnimation && animated)
|
||||||
animation.serialize(os, protocol_ver);
|
animation.serialize(os, protocol_ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerParticleTexture::deSerialize(std::istream &is, u16 protocol_ver, bool newPropertiesOnly)
|
void ServerParticleTexture::deSerialize(std::istream &is, u16 protocol_ver,
|
||||||
|
bool newPropertiesOnly, bool skipAnimation)
|
||||||
{
|
{
|
||||||
FlagT flags = 0;
|
FlagT flags = 0;
|
||||||
deSerializeParameterValue(is, flags);
|
deSerializeParameterValue(is, flags);
|
||||||
|
// new texture properties were missing in ParticleParameters::serialize
|
||||||
|
// before Minetest 5.9.0
|
||||||
|
if (is.eof())
|
||||||
|
return;
|
||||||
|
|
||||||
animated = !!(flags & FlagT(ParticleTextureFlags::animated));
|
animated = !!(flags & FlagT(ParticleTextureFlags::animated));
|
||||||
blendmode = BlendMode((flags & FlagT(ParticleTextureFlags::blend)) >> 1);
|
blendmode = BlendMode((flags & FlagT(ParticleTextureFlags::blend)) >> 1);
|
||||||
|
@ -230,7 +236,7 @@ void ServerParticleTexture::deSerialize(std::istream &is, u16 protocol_ver, bool
|
||||||
if (!newPropertiesOnly)
|
if (!newPropertiesOnly)
|
||||||
string = deSerializeString32(is);
|
string = deSerializeString32(is);
|
||||||
|
|
||||||
if (animated)
|
if (!skipAnimation && animated)
|
||||||
animation.deSerialize(is, protocol_ver);
|
animation.deSerialize(is, protocol_ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +260,7 @@ void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const
|
||||||
writeV3F32(os, drag);
|
writeV3F32(os, drag);
|
||||||
jitter.serialize(os);
|
jitter.serialize(os);
|
||||||
bounce.serialize(os);
|
bounce.serialize(os);
|
||||||
|
texture.serialize(os, protocol_ver, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, T (reader)(std::istream& is)>
|
template <typename T, T (reader)(std::istream& is)>
|
||||||
|
@ -291,4 +298,5 @@ void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
|
||||||
return;
|
return;
|
||||||
jitter.deSerialize(is);
|
jitter.deSerialize(is);
|
||||||
bounce.deSerialize(is);
|
bounce.deSerialize(is);
|
||||||
|
texture.deSerialize(is, protocol_ver, true, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,8 +276,10 @@ struct ParticleTexture
|
||||||
struct ServerParticleTexture : public ParticleTexture
|
struct ServerParticleTexture : public ParticleTexture
|
||||||
{
|
{
|
||||||
std::string string;
|
std::string string;
|
||||||
void serialize(std::ostream &os, u16 protocol_ver, bool newPropertiesOnly = false) const;
|
void serialize(std::ostream &os, u16 protocol_ver, bool newPropertiesOnly = false,
|
||||||
void deSerialize(std::istream &is, u16 protocol_ver, bool newPropertiesOnly = false);
|
bool skipAnimation = false) const;
|
||||||
|
void deSerialize(std::istream &is, u16 protocol_ver, bool newPropertiesOnly = false,
|
||||||
|
bool skipAnimation = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommonParticleParams
|
struct CommonParticleParams
|
||||||
|
|
|
@ -760,7 +760,7 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
||||||
|
|
||||||
f.setDefaultAlphaMode();
|
f.setDefaultAlphaMode();
|
||||||
|
|
||||||
warn_if_field_exists(L, index, "alpha",
|
warn_if_field_exists(L, index, "alpha", "node " + f.name,
|
||||||
"Obsolete, only limited compatibility provided; "
|
"Obsolete, only limited compatibility provided; "
|
||||||
"replaced by \"use_texture_alpha\"");
|
"replaced by \"use_texture_alpha\"");
|
||||||
if (getintfield_default(L, index, "alpha", 255) != 255)
|
if (getintfield_default(L, index, "alpha", 255) != 255)
|
||||||
|
@ -768,7 +768,7 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
||||||
|
|
||||||
lua_getfield(L, index, "use_texture_alpha");
|
lua_getfield(L, index, "use_texture_alpha");
|
||||||
if (lua_isboolean(L, -1)) {
|
if (lua_isboolean(L, -1)) {
|
||||||
warn_if_field_exists(L, index, "use_texture_alpha",
|
warn_if_field_exists(L, index, "use_texture_alpha", "node " + f.name,
|
||||||
"Boolean values are deprecated; use the new choices");
|
"Boolean values are deprecated; use the new choices");
|
||||||
if (lua_toboolean(L, -1))
|
if (lua_toboolean(L, -1))
|
||||||
f.alpha = (f.drawtype == NDT_NORMAL) ? ALPHAMODE_CLIP : ALPHAMODE_BLEND;
|
f.alpha = (f.drawtype == NDT_NORMAL) ? ALPHAMODE_CLIP : ALPHAMODE_BLEND;
|
||||||
|
@ -1315,13 +1315,16 @@ void pushnode(lua_State *L, const MapNode &n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void warn_if_field_exists(lua_State *L, int table,
|
void warn_if_field_exists(lua_State *L, int table, const char *fieldname,
|
||||||
const char *name, const std::string &message)
|
std::string_view name, std::string_view message)
|
||||||
{
|
{
|
||||||
lua_getfield(L, table, name);
|
lua_getfield(L, table, fieldname);
|
||||||
if (!lua_isnil(L, -1)) {
|
if (!lua_isnil(L, -1)) {
|
||||||
warningstream << "Field \"" << name << "\": "
|
warningstream << "Field \"" << fieldname << "\"";
|
||||||
<< message << std::endl;
|
if (!name.empty()) {
|
||||||
|
warningstream << " on " << name;
|
||||||
|
}
|
||||||
|
warningstream << ": " << message << std::endl;
|
||||||
infostream << script_get_backtrace(L) << std::endl;
|
infostream << script_get_backtrace(L) << std::endl;
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
|
@ -120,7 +120,8 @@ void push_aabb3f_vector (lua_State *L, const std::vector<aabb3f>
|
||||||
|
|
||||||
void warn_if_field_exists(lua_State *L, int table,
|
void warn_if_field_exists(lua_State *L, int table,
|
||||||
const char *fieldname,
|
const char *fieldname,
|
||||||
const std::string &message);
|
std::string_view name,
|
||||||
|
std::string_view message);
|
||||||
|
|
||||||
size_t write_array_slice_float(lua_State *L, int table_index, float *data,
|
size_t write_array_slice_float(lua_State *L, int table_index, float *data,
|
||||||
v3u16 data_size, v3u16 slice_offset, v3u16 slice_size);
|
v3u16 data_size, v3u16 slice_offset, v3u16 slice_size);
|
||||||
|
|
|
@ -155,6 +155,7 @@ void LuaLBM::trigger(ServerEnvironment *env, v3s16 p,
|
||||||
int LuaRaycast::l_next(lua_State *L)
|
int LuaRaycast::l_next(lua_State *L)
|
||||||
{
|
{
|
||||||
GET_PLAIN_ENV_PTR;
|
GET_PLAIN_ENV_PTR;
|
||||||
|
ServerEnvironment *senv = dynamic_cast<ServerEnvironment*>(env);
|
||||||
|
|
||||||
bool csm = false;
|
bool csm = false;
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
@ -163,7 +164,17 @@ int LuaRaycast::l_next(lua_State *L)
|
||||||
|
|
||||||
LuaRaycast *o = checkObject<LuaRaycast>(L, 1);
|
LuaRaycast *o = checkObject<LuaRaycast>(L, 1);
|
||||||
PointedThing pointed;
|
PointedThing pointed;
|
||||||
|
for (;;) {
|
||||||
env->continueRaycast(&o->state, &pointed);
|
env->continueRaycast(&o->state, &pointed);
|
||||||
|
if (pointed.type != POINTEDTHING_OBJECT)
|
||||||
|
break;
|
||||||
|
if (!senv)
|
||||||
|
break;
|
||||||
|
const auto *obj = senv->getActiveObject(pointed.object_id);
|
||||||
|
if (obj && !obj->isGone())
|
||||||
|
break;
|
||||||
|
// skip gone object
|
||||||
|
}
|
||||||
if (pointed.type == POINTEDTHING_NOTHING)
|
if (pointed.type == POINTEDTHING_NOTHING)
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
else
|
else
|
||||||
|
|
|
@ -1354,7 +1354,7 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
||||||
ore->flags = 0;
|
ore->flags = 0;
|
||||||
|
|
||||||
//// Get noise_threshold
|
//// Get noise_threshold
|
||||||
warn_if_field_exists(L, index, "noise_threshhold",
|
warn_if_field_exists(L, index, "noise_threshhold", "ore " + ore->name,
|
||||||
"Deprecated: new name is \"noise_threshold\".");
|
"Deprecated: new name is \"noise_threshold\".");
|
||||||
|
|
||||||
float nthresh;
|
float nthresh;
|
||||||
|
@ -1364,9 +1364,9 @@ int ModApiMapgen::l_register_ore(lua_State *L)
|
||||||
ore->nthresh = nthresh;
|
ore->nthresh = nthresh;
|
||||||
|
|
||||||
//// Get y_min/y_max
|
//// Get y_min/y_max
|
||||||
warn_if_field_exists(L, index, "height_min",
|
warn_if_field_exists(L, index, "height_min", "ore " + ore->name,
|
||||||
"Deprecated: new name is \"y_min\".");
|
"Deprecated: new name is \"y_min\".");
|
||||||
warn_if_field_exists(L, index, "height_max",
|
warn_if_field_exists(L, index, "height_max", "ore " + ore->name,
|
||||||
"Deprecated: new name is \"y_max\".");
|
"Deprecated: new name is \"y_max\".");
|
||||||
|
|
||||||
int ymin, ymax;
|
int ymin, ymax;
|
||||||
|
|
|
@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "lua_api/l_object.h"
|
#include "lua_api/l_object.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <lua.h>
|
||||||
#include "lua_api/l_internal.h"
|
#include "lua_api/l_internal.h"
|
||||||
#include "lua_api/l_inventory.h"
|
#include "lua_api/l_inventory.h"
|
||||||
#include "lua_api/l_item.h"
|
#include "lua_api/l_item.h"
|
||||||
|
@ -106,6 +107,13 @@ int ObjectRef::l_remove(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is_valid(self)
|
||||||
|
int ObjectRef::l_is_valid(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushboolean(L, getobject(checkObject<ObjectRef>(L, 1)) != nullptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// get_pos(self)
|
// get_pos(self)
|
||||||
int ObjectRef::l_get_pos(lua_State *L)
|
int ObjectRef::l_get_pos(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -2646,6 +2654,7 @@ const char ObjectRef::className[] = "ObjectRef";
|
||||||
luaL_Reg ObjectRef::methods[] = {
|
luaL_Reg ObjectRef::methods[] = {
|
||||||
// ServerActiveObject
|
// ServerActiveObject
|
||||||
luamethod(ObjectRef, remove),
|
luamethod(ObjectRef, remove),
|
||||||
|
luamethod(ObjectRef, is_valid),
|
||||||
luamethod_aliased(ObjectRef, get_pos, getpos),
|
luamethod_aliased(ObjectRef, get_pos, getpos),
|
||||||
luamethod_aliased(ObjectRef, set_pos, setpos),
|
luamethod_aliased(ObjectRef, set_pos, setpos),
|
||||||
luamethod(ObjectRef, add_pos),
|
luamethod(ObjectRef, add_pos),
|
||||||
|
|
|
@ -67,6 +67,9 @@ private:
|
||||||
// remove(self)
|
// remove(self)
|
||||||
static int l_remove(lua_State *L);
|
static int l_remove(lua_State *L);
|
||||||
|
|
||||||
|
// is_valid(self)
|
||||||
|
static int l_is_valid(lua_State *L);
|
||||||
|
|
||||||
// get_pos(self)
|
// get_pos(self)
|
||||||
static int l_get_pos(lua_State *L);
|
static int l_get_pos(lua_State *L);
|
||||||
|
|
||||||
|
|
|
@ -458,7 +458,7 @@ def generate_template(folder, mod_name):
|
||||||
dOut[s] = sources
|
dOut[s] = sources
|
||||||
|
|
||||||
if len(dOut) == 0:
|
if len(dOut) == 0:
|
||||||
return None
|
return (None, None)
|
||||||
|
|
||||||
# Convert source file set to list, sort it and add comment symbols.
|
# Convert source file set to list, sort it and add comment symbols.
|
||||||
# Needed because a set is unsorted and might result in unpredictable.
|
# Needed because a set is unsorted and might result in unpredictable.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue