Post your modding questions here

User avatar
paramat
Developer
Posts: 3700
Joined: Sun Oct 28, 2012 00:05
GitHub: paramat
IRC: paramat
Location: UK

Re: Post your modding questions here

by paramat » Post

> Somewhere l read that minetest.set_node works faster when it's used in an on_generated, is it true?

I saw that too, i think it is a little faster inside 'on gen' but still much slower than LVM for a large number of nodes.

everamzah, the lua voxelmanips are already flat arrays.
The voxelmanip index always increases by 1 along the x direction, so instead of calculating index per node, calculate the initial index (for x = x0) before the x loop, then increment it by 1 per node.

The end of your code doesn't reset lighting, it should be:

Code: Select all

	vm:set_data(data)
	vm:set_lighting({day = 0, night = 0})
	vm:calc_lighting()
	vm:write_to_map(data)

User avatar
Hybrid Dog
Member
Posts: 2834
Joined: Thu Nov 01, 2012 12:46
GitHub: HybridDog

Re: Post your modding questions here

by Hybrid Dog » Post

everamzah wrote:Oh thank you very much HybridDog! I guess I do have to set air though, because I'm using mgv6. Thanks again.

Edit: This is what I've got now:
Spoiler

Code: Select all

minetest.register_node("kalite:plastic_grass", {
        description = "Plastic Grass",
        tiles = {"default_grass.png"},
        groups = {cracky = default.dig.cobble}
})

local c_cloud = minetest.get_content_id("default:cloud")
local c_plastic_grass = minetest.get_content_id("kalite:plastic_grass")
--local c_air = minetest.get_content_id("air")

minetest.register_on_generated(function(minp, maxp, seed)

        if maxp.y < 14400 or
            minp.y > 14401 then
                return
        end

        local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
        local data = vm:get_data()
        local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}

        local x1 = maxp.x
        local y1 = maxp.y
        local z1 = maxp.z
        local x0 = minp.x
        local y0 = minp.y
        local z0 = minp.z

        for z = z0, z1 do
                for x = x0, x1 do
--3
                        --[[
                        for vi in area:iter(x0, 14400, z0, x1, 14400, z1) do
                                data[vi] = c_cloud
                        end
                        for vi in area:iter(x0, 14401, z0, x1, 14401, z1) do
                                data[vi] = c_plastic_grass
                        end
                        --]]
--2
                        ---[[
                        data[area:index(x, 14400, z)] = c_cloud
                        data[area:index(x, 14401, z)] = c_plastic_grass
                        --]]
--1
                        --[[
                        for y = y0, y1 do
                                local vi = area:index(x, y, z)
                                if y == 14400 then
                                        data[vi] = c_cloud
                                elseif y == 14401 then
                                        data[vi] = c_plastic_grass
                                else
                                        data[vi] = c_air
                                end
                        end
                        --]]
                end
        end

        vm:set_data(data)
        vm:write_to_map()
end)
Option 2 seemed to be the fastest. Also, I tried without air and it still works. Were you talking about the singlenode mapgen or the fact that I was only working with a couple of single nodes?
singlenode mapgen
paramat wrote:> Somewhere l read that minetest.set_node works faster when it's used in an on_generated, is it true?

I saw that too, i think it is a little faster inside 'on gen' but still much slower than LVM for a large number of nodes.
How can l determine the least number of nodes LVM works faster if l know the approximate shape?

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪

User avatar
everamzah
Member
Posts: 490
Joined: Thu Jan 29, 2015 00:47
GitHub: everamzah
IRC: everamzah
In-game: everamzah

Re: Post your modding questions here

by everamzah » Post

paramat wrote:everamzah, the lua voxelmanips are already flat arrays.
The voxelmanip index always increases by 1 along the x direction, so instead of calculating index per node, calculate the initial index (for x = x0) before the x loop, then increment it by 1 per node.

The end of your code doesn't reset lighting, it should be:

Code: Select all

	vm:set_data(data)
	vm:set_lighting({day = 0, night = 0})
	vm:calc_lighting()
	vm:write_to_map(data)
Well I added the bit at the end, but all I noticed change was that the bottom of the cloud is dark. Also, I wonder why write_to_map() worked without passing data to it.

I have to admit I'm pretty lost on what you say about calculating index. I'm using #2:

Code: Select all

for z = z0, z1 do
  for x = x0, x1 do
    data[area:index(x, 14400, z)] = c_cloud
    data[area:index(x, 14401, z)] = c_plastic_grass
  end
end
Are you referring the the third option with area:iter() ?

User avatar
Hybrid Dog
Member
Posts: 2834
Joined: Thu Nov 01, 2012 12:46
GitHub: HybridDog

Re: Post your modding questions here

by Hybrid Dog » Post

everamzah wrote:
paramat wrote:everamzah, the lua voxelmanips are already flat arrays.
The voxelmanip index always increases by 1 along the x direction, so instead of calculating index per node, calculate the initial index (for x = x0) before the x loop, then increment it by 1 per node.

The end of your code doesn't reset lighting, it should be:

Code: Select all

	vm:set_data(data)
	vm:set_lighting({day = 0, night = 0})
	vm:calc_lighting()
	vm:write_to_map(data)
Well I added the bit at the end, but all I noticed change was that the bottom of the cloud is dark. Also, I wonder why write_to_map() worked without passing data to it.

I have to admit I'm pretty lost on what you say about calculating index. I'm using #2:

Code: Select all

for z = z0, z1 do
  for x = x0, x1 do
    data[area:index(x, 14400, z)] = c_cloud
    data[area:index(x, 14401, z)] = c_plastic_grass
  end
end
Are you referring the the third option with area:iter() ?
the indices are numbers
https://github.com/UgnilJoZ/lumpmg/blob/master/init.lua

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪

User avatar
everamzah
Member
Posts: 490
Joined: Thu Jan 29, 2015 00:47
GitHub: everamzah
IRC: everamzah
In-game: everamzah

Re: Post your modding questions here

by everamzah » Post

I'm aware that the way I'm doing it is very slow. I'm also aware that figuring out how to use indices to make it faster will take me a great deal of time. I put this project on GitHub and the file is https://github.com/everamzah/kalite/blo ... ldedge.lua

User avatar
paramat
Developer
Posts: 3700
Joined: Sun Oct 28, 2012 00:05
GitHub: paramat
IRC: paramat
Location: UK

Re: Post your modding questions here

by paramat » Post

I realised you probably want no shadows cast. Disabling lighting calculations is one way, the 'proper' but slower way is to define your grass and cloud nodes to have 'sunlight_propagates = true'.

I'm referring to the second method of your code, the best method.
For the index trick see https://github.com/minetest/minetest_ga ... s.lua#L312
Lines 312-324.
Your second method isn't slow, with the index trick it will be the fastest lua method there is.

Byakuren
Member
Posts: 818
Joined: Tue Apr 14, 2015 01:59
GitHub: raymoo
IRC: Hijiri
In-game: Raymoo + Clownpiece

Re: Post your modding questions here

by Byakuren » Post

Is there a way to make entities ignore lighting for their rendering?
Every time a mod API is left undocumented, a koala dies.

User avatar
Evergreen
Member
Posts: 2135
Joined: Sun Jan 06, 2013 01:22
GitHub: 4Evergreen4
IRC: EvergreenTree
In-game: Evergreen
Location: A forest in the midwest
Contact:

Re: Post your modding questions here

by Evergreen » Post

Is there a way of triggering a function when someone adds an item to an inventory? (or removes, or any action)
Back from the dead!

User avatar
Nathan.S
Member
Posts: 1147
Joined: Wed Sep 24, 2014 17:47
GitHub: NathanSalapat
IRC: NathanS21
In-game: NathanS21
Location: Bigsby Texas
Contact:

Re: Post your modding questions here

by Nathan.S » Post

Evergreen wrote:Is there a way of triggering a function when someone adds an item to an inventory? (or removes, or any action)
Yep, check this out. http://dev.minetest.net/minetest.regist ... ntory_move

Just call the function in this callback.
I record Minetest videos, Mod reviews, Modding tutorials, and Lets plays.
Check out my website, and brand new Minetest Modding Course

User avatar
BrunoMine
Member
Posts: 1082
Joined: Thu Apr 25, 2013 17:29
GitHub: BrunoMine
Location: SP-Brasil
Contact:

How can I save an inventory?

by BrunoMine » Post

I can not serialize an inventory.

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
data_base = minetest.serialize(list)

User avatar
rubenwardy
Moderator
Posts: 6977
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: How can I save an inventory?

by rubenwardy » Post

BrunoMine wrote:I can not serialize an inventory.

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
data_base = minetest.serialize(list)

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
local retval = {}
for _, stack in pairs(list) do
    retval[#retval + 1] = stack:to_string()
end
local data_base = minetest.serialize(retval)
then to deserialise

Code: Select all

local list_strings = minetest.deserialize(text)
local list = {}
for _, str in pairs(list_strings) do
    list[#list + 1] = ItemStack(str)
end
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
BrunoMine
Member
Posts: 1082
Joined: Thu Apr 25, 2013 17:29
GitHub: BrunoMine
Location: SP-Brasil
Contact:

How can I save an inventory?

by BrunoMine » Post

text == data_base ?

User avatar
kaeza
Moderator
Posts: 2162
Joined: Thu Oct 18, 2012 05:00
GitHub: kaeza
IRC: kaeza diemartin blaaaaargh
In-game: kaeza
Location: Montevideo, Uruguay
Contact:

Re: How can I save an inventory?

by kaeza » Post

rubenwardy wrote:

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
local retval = {}
for _, stack in pairs(list) do
    retval[#retval + 1] = stack:to_string()
end
local data_base = minetest.serialize(retval)
[...]
It can be edited in-place, and you can use the index from `ipairs` to index instead of using `#t`:

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
for i, stack in ipairs(list) do
  list[i] = stack:to_string()
end
Also, I don't recall if `inv:get_list()` may return `nil` items, so you may want to check for that.
Your signature is not the place for a blog post. Please keep it as concise as possible. Thank you!

Check out my stuff! | Donations greatly appreciated! PayPal

User avatar
Hybrid Dog
Member
Posts: 2834
Joined: Thu Nov 01, 2012 12:46
GitHub: HybridDog

Re: Post your modding questions here

by Hybrid Dog » Post

paramat wrote:Your second method isn't slow, with the index trick it will be the fastest lua method there is.
Every chunk at that height has the same look, so you could cache (localize it outside the on_generated) the data table and set the cached one (passing it at that manip:set_data l think) instead of recalculating it, couldn't you?

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪

User avatar
rubenwardy
Moderator
Posts: 6977
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: How can I save an inventory?

by rubenwardy » Post

kaeza wrote:
rubenwardy wrote:

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
local retval = {}
for _, stack in pairs(list) do
    retval[#retval + 1] = stack:to_string()
end
local data_base = minetest.serialize(retval)
[...]
It can be edited in-place, and you can use the index from `ipairs` to index instead of using `#t`:

Code: Select all

local player_inv = player:get_inventory()
local list = player_inv:get_list("main")
for i, stack in ipairs(list) do
  list[i] = stack:to_string()
end
Also, I don't recall if `inv:get_list()` may return `nil` items, so you may want to check for that.
I'm pretty sure it doesn't return nil items, at least it doesn't when you do print(dump(list)). Are you sure that get_list returns a copy?
BrunoMine wrote:text == data_base ?
Yes, it's the same string.
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
Hybrid Dog
Member
Posts: 2834
Joined: Thu Nov 01, 2012 12:46
GitHub: HybridDog

Re: Post your modding questions here

by Hybrid Dog » Post

Code: Select all

    local player_inv = player:get_inventory()
    local list = player_inv:get_list("main")
    local retval = {}
    for _, stack in pairs(list) do
        retval[#retval + 1] = stack:to_string()
    end
    local data_base = minetest.serialize(retval)
Can an item in list be nil?
Even if not, l'd use the index from the list:

Code: Select all

    local player_inv = player:get_inventory()
    local list = player_inv:get_list("main")
    local retval = {}
    for n, stack in pairs(list) do
        retval[n] = stack:to_string()
    end
    local data_base = minetest.serialize(retval)
Are you sure that get_list returns a copy?
l guess else there wouldn't be the set_item and remove_item

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪

User avatar
kaeza
Moderator
Posts: 2162
Joined: Thu Oct 18, 2012 05:00
GitHub: kaeza
IRC: kaeza diemartin blaaaaargh
In-game: kaeza
Location: Montevideo, Uruguay
Contact:

Re: How can I save an inventory?

by kaeza » Post

rubenwardy wrote:I'm pretty sure it doesn't return nil items, at least it doesn't when you do print(dump(list)). Are you sure that get_list returns a copy?
Looked at the sources, and indeed the items are guaranteed to be `ItemStack`s. Also, a new table is created on the spot to hold the items, so editing it in-place has no side-effects.

Edit: Clarification.
Your signature is not the place for a blog post. Please keep it as concise as possible. Thank you!

Check out my stuff! | Donations greatly appreciated! PayPal

User avatar
BrunoMine
Member
Posts: 1082
Joined: Thu Apr 25, 2013 17:29
GitHub: BrunoMine
Location: SP-Brasil
Contact:

How can I save an inventory?

by BrunoMine » Post

Thanks! Another learning experience for me.

Byakuren
Member
Posts: 818
Joined: Tue Apr 14, 2015 01:59
GitHub: raymoo
IRC: Hijiri
In-game: Raymoo + Clownpiece

Re: Post your modding questions here

by Byakuren » Post

Are detached inventories persistent like player and node inventories?
Every time a mod API is left undocumented, a koala dies.

User avatar
rubenwardy
Moderator
Posts: 6977
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: Post your modding questions here

by rubenwardy » Post

Byakuren wrote:Are detached inventories persistent like player and node inventories?
No. They're deleted on shutdown.
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
BrunoMine
Member
Posts: 1082
Joined: Thu Apr 25, 2013 17:29
GitHub: BrunoMine
Location: SP-Brasil
Contact:

how can I delete a variable?

by BrunoMine » Post

I want to save memory.
This is correct?

Code: Select all

mytable = {}
table.insert(mytable,"a string")
table.insert(mytable,"another string")
[...]
mytable[1] = nil

User avatar
qwertymine3
Member
Posts: 202
Joined: Wed Jun 03, 2015 14:33
GitHub: Qwertymine
In-game: qwertymine3

Re: how can I delete a variable?

by qwertymine3 » Post

BrunoMine wrote:I want to save memory.
This is correct?

Code: Select all

mytable = {}
table.insert(mytable,"a string")
table.insert(mytable,"another string")
[...]
mytable[1] = nil
Yes this is the correct way, however...
The String
Strings in lua are references to a table of all strings, if the string "a string" is stored anywhere else (in any other variable in your mod or other mods), the interpreter won't be able to delete the global copy to free memory.
The Table
Tables in lua are only dynamically re-sized in memory when they are full - this means that setting only one of the indexes to nil won't cause it to re-size and reduce it's memory consumption

PS: Setting only [1] to nil means that you can no longer use ipairs() or # on the table - you may want to use...

Code: Select all

table.remove(mytable,1)  
mytable[1] == "another string" --this is now true
This is much slower but it shuffles the entries in the table down to fill the hole in
or, if it work with what you are trying to do

Code: Select all

mytable[1] = mytable[#mytable]
mytable[#mytable] = nil
This is faster, but messes up the order of the table
Avatar by :devnko-ennekappao:

User avatar
Evergreen
Member
Posts: 2135
Joined: Sun Jan 06, 2013 01:22
GitHub: 4Evergreen4
IRC: EvergreenTree
In-game: Evergreen
Location: A forest in the midwest
Contact:

Re: Post your modding questions here

by Evergreen » Post

How can I add an item to a nodes inventory when it is thrown into said node? This is the code I have for it, but it seems to only remove the item and not add it to the specified list within the nodes inventory.

Code: Select all

-- Store the old on_step function for __builtin:item so it can be called at the
-- end of the new on_step function.
local old_on_step = minetest.registered_entities["__builtin:item"].on_step
-- Register a new on_step function for __builtin:item
minetest.registered_entities["__builtin:item"].on_step = function(self, dtime)
	local item_pos = self.object:getpos()
	-- If the item is sitting in the same node as trash_can:trash_can_wooden,
	-- then continue.
	if minetest.get_node(item_pos).name == "trash_can:trash_can_wooden" then
		-- Get the ItemStack from the itemstring contained in this
		-- __builtin:item.
		local item_stack = ItemStack(self.itemstring)
		-- Get inventory of the trash_list:trash_can_wooden the item is sitting
		-- in
		local inv = minetest.get_inventory({type="node", pos=item_pos})
		-- Add the item to trash_list (a list defined in the formspec for
		-- trash_can_wooden
		inv:add_item("trash_list", item_stack)

		-- Remove the item itself
		self.object:remove()
		return
	end
	-- Call old on_step function.  This has the effect of simply adding this
	-- code to the beginning of the old on_step function.
	old_on_step(self, dtime)
end
Back from the dead!

User avatar
rubenwardy
Moderator
Posts: 6977
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: Post your modding questions here

by rubenwardy » Post

Evergreen wrote:How can I add an item to a nodes inventory when it is thrown into said node? This is the code I have for it, but it seems to only remove the item and not add it to the specified list within the nodes inventory.

Code: Select all

-- Store the old on_step function for __builtin:item so it can be called at the
-- end of the new on_step function.
local old_on_step = minetest.registered_entities["__builtin:item"].on_step
-- Register a new on_step function for __builtin:item
minetest.registered_entities["__builtin:item"].on_step = function(self, dtime)
	local item_pos = self.object:getpos()
	-- If the item is sitting in the same node as trash_can:trash_can_wooden,
	-- then continue.
	if minetest.get_node(item_pos).name == "trash_can:trash_can_wooden" then
		-- Get the ItemStack from the itemstring contained in this
		-- __builtin:item.
		local item_stack = ItemStack(self.itemstring)
		-- Get inventory of the trash_list:trash_can_wooden the item is sitting
		-- in
		local inv = minetest.get_inventory({type="node", pos=item_pos})
		-- Add the item to trash_list (a list defined in the formspec for
		-- trash_can_wooden
		inv:add_item("trash_list", item_stack)

		-- Remove the item itself
		self.object:remove()
		return
	end
	-- Call old on_step function.  This has the effect of simply adding this
	-- code to the beginning of the old on_step function.
	old_on_step(self, dtime)
end
You may need to floor the position, maybe?

Also, add_item won't necessarily add the whole stack.
You should check with inv:room_for_item(listname, stack).
See http://rubenwardy.com/minetest_modding_ ... -to-a-list
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
Evergreen
Member
Posts: 2135
Joined: Sun Jan 06, 2013 01:22
GitHub: 4Evergreen4
IRC: EvergreenTree
In-game: Evergreen
Location: A forest in the midwest
Contact:

Re: Post your modding questions here

by Evergreen » Post

rubenwardy wrote:
Evergreen wrote:How can I add an item to a nodes inventory when it is thrown into said node? This is the code I have for it, but it seems to only remove the item and not add it to the specified list within the nodes inventory.

Code: Select all

-- Store the old on_step function for __builtin:item so it can be called at the
-- end of the new on_step function.
local old_on_step = minetest.registered_entities["__builtin:item"].on_step
-- Register a new on_step function for __builtin:item
minetest.registered_entities["__builtin:item"].on_step = function(self, dtime)
	local item_pos = self.object:getpos()
	-- If the item is sitting in the same node as trash_can:trash_can_wooden,
	-- then continue.
	if minetest.get_node(item_pos).name == "trash_can:trash_can_wooden" then
		-- Get the ItemStack from the itemstring contained in this
		-- __builtin:item.
		local item_stack = ItemStack(self.itemstring)
		-- Get inventory of the trash_list:trash_can_wooden the item is sitting
		-- in
		local inv = minetest.get_inventory({type="node", pos=item_pos})
		-- Add the item to trash_list (a list defined in the formspec for
		-- trash_can_wooden
		inv:add_item("trash_list", item_stack)

		-- Remove the item itself
		self.object:remove()
		return
	end
	-- Call old on_step function.  This has the effect of simply adding this
	-- code to the beginning of the old on_step function.
	old_on_step(self, dtime)
end
You may need to floor the position, maybe?

Also, add_item won't necessarily add the whole stack.
You should check with inv:room_for_item(listname, stack).
See http://rubenwardy.com/minetest_modding_ ... -to-a-list
It seems that for one reason or another the inventory for the trash can is not being retrieved correctly. Any ideas as to why that may be?

EDIT:
I found out that the formspec isn't reloaded on the node unless you dig and replace it. I suppose this makes sense since forsmpecs are metadata. Whoops. The reason this messed things up was that the old formspec contained in that trash can didn't have the list I was trying to access.
Last edited by Evergreen on Tue Jan 12, 2016 19:43, edited 3 times in total.
Back from the dead!

Locked

Who is online

Users browsing this forum: Bing [Bot] and 4 guests