Page 1 of 1

[Mod] Magic Lantern [magic_latern]

Posted: Sun Dec 04, 2011 21:11
by ironzorg
Hello everybody,

Here's a mod that allows you to make lights that will glow accordingly to the average level of light surrounding the lamp.
It's very useful as a decorative item: the darker it gets the brighter the lamp will be, and when the sun comes up the lamp stops glowing.

The recipe: one torch surrounded by glass.

Dependencies: default

Since I'm not an artist, I don't provide textures (sorry for that) but I had interesting ideas if you feel like creating the textures yourself:
- The block wears successively 14 textures (there are 14 levels of enlightment), so you can make them so they show a specific hour (like a clock).
- You can make the textures more and more bright as their id (the number of the file name) increases to add realism.

The threshold variables are just a trick I used so that the block emits the same amount of light during more then one cycle.

Code: Select all

local LANTERN_NODES = {}
local LIGHT_THRESHOLD_NIGHT = 4
local LIGHT_THRESHOLD_DAY = 10

for i = 0, LIGHT_MAX do
    table.insert(LANTERN_NODES, 'magic_lantern:magic_lantern_' .. i)
end

-- Functions
minetest.register_abm({
    nodenames = LANTERN_NODES,
    interval = 6,
    chance = 1,
    action = function(pos, node, _, __)
        local aname = node.name

        minetest.env:remove_node(pos)
        local l = minetest.env:get_node_light(pos, nil) - 1

        if l == nil then
            l = 0
        end

        if l < LIGHT_THRESHOLD_NIGHT then
            l = 0
        elseif l > LIGHT_THRESHOLD_DAY then
            l = LIGHT_MAX
        end

         local nname = 'magic_lantern:magic_lantern_' .. (LIGHT_MAX - l)

        minetest.env:add_node(pos, { name = nname })
    end
})

-- Nodes
for i, ml in ipairs(LANTERN_NODES) do
    minetest.register_node(ml, {
        tile_images = { 'magic_lantern_' .. (i - 1) .. '.png' },
        inventory_image = 'magic_lantern_' .. (i - 1) .. '.png',
        drawtype = 'glasslike',
        paramtype = "light",
        walkable = true,
        sunlight_propagates = true,
        light_source = i - 1,
        material = minetest.digprop_glasslike(2.0),
        furnace_burntime = 4,
    })
end

-- Crafts
minetest.register_craft({
    output = 'NodeItem "magic_lantern:magic_lantern_0" 1',
    recipe = {
        {'node "default:glass" 1', 'node "default:glass" 1', 'node "default:glass" 1'},
        {'node "default:glass" 1', 'node "default:torch" 1', 'node "default:glass" 1'},
        {'node "default:glass" 1', 'node "default:glass" 1', 'node "default:glass" 1'},
    },
})
Image

Image

Image

The screenshots are not really convincing because I used the same texture for all the sprites, but like I said you will probably get a better effect if you can draw good looking textures (don't hesitate to post your textures in this thread !).

Do-whatever-you-want-with-my-code license.

Download on mediafire

Feedback appreciated.

Posted: Sun Dec 04, 2011 22:34
by Miklosher
This is fu***ng amazing.

Posted: Mon Dec 05, 2011 15:00
by ironzorg
Miklosher wrote:This is fu***ng amazing.
Thank you, I will try and make a screenshot of the block ingame with proper textures ;)

Posted: Sun Dec 11, 2011 15:02
by Hackeridze
Where the textures?

Posted: Sun Dec 11, 2011 15:31
by sfan5
You must make the textures yourself

Posted: Sun Dec 11, 2011 15:47
by ironzorg
Hackeridze wrote:Where the textures?
You unfortunately have to draw them yourself, since I don't provide any.

Posted: Sun Dec 11, 2011 16:05
by bwog
Could you package everything into a .zip file? That would make it easier for everyone else.

Posted: Sun Dec 11, 2011 18:04
by MarkTraceur
More simpler, let gitorious do it for you:

https://gitorious.org

They automatically generate tarballs for your project, and we already have a modders group on there:

https://gitorious.org/+minetest-modders

Join today! :)

Posted: Sun Dec 11, 2011 19:41
by ironzorg
bwog wrote:Could you package everything into a .zip file? That would make it easier for everyone else.
Since it's only a couple functions in a init file, I thought it would be overkill to upload a whole archive for the mod…
But since you're the second one to ask, here you go !
The textures I used for the screenshots are in it.

Posted: Wed Feb 08, 2012 02:23
by RabbiBob

Posted: Mon Feb 13, 2012 16:25
by MirceaKitsune
+1. This looks like a very nice mod... will try it out.

Posted: Wed Jun 27, 2012 18:26
by Mineing Master
How do you get the magic lanturn in the game I can't figure that out.

Posted: Wed Jun 27, 2012 22:59
by minenato
i tried install this but no works

/home/myusername/.minetest/mods/minetest/magic_lantern ?

Posted: Sun Nov 11, 2012 10:44
by prof-turbo
No,now it's
home/your_username/minetest~/games/minetest_game (or minimal)/mods/magic_lantern

Posted: Fri Dec 21, 2012 00:36
by luk3yx
I like the idea of this mod, I'll try and download it.

Posted: Fri Dec 21, 2012 00:44
by luk3yx
I didn't seem to be able to run it properly. It may be just me, however if it isn't, it's worth investigating.

Posted: Sat Dec 22, 2012 15:18
by Topywo
I found one, with .png's (thanks to Cornernote).

Changes already made (as far as I could see):
- tile images --> tiles

Changes I made:
- I put in a description (so it's visible in creative. However it will show all 14 .pngs, so if you don't like it, put -- before description in the init.lua)
- I changed the old materials digprop in the same groups as glass. At least it is diggable now. (long time ago I killed a nyanland clonestone with a non-diggable magic lantern on gameboom :-P )
- I copied the glass sound into it's init.lua.

I hope you enjoy this mod like I always did!

http://dl.dropbox.com/u/65428713/magic_lantern.zip

Posted: Wed Feb 20, 2013 13:39
by dsalt
There are problems with the lantern as it stands…
  • Flicker. When the brightness is checked, the object may briefly disappear. This is… sometimes rather noticeable in that it's briefly dark.
  • As others have noted, all variants (different brightnesses) appear in the palette in creative mode.
This version fixes these problems and makes a few brightness adjustments, but (currently) has a dependency on a patched minetest.

Code: Select all

local LANTERN_NODES = {}
local LIGHT_THRESHOLD_NIGHT = 4
local LIGHT_THRESHOLD_DAY = 10

-- Nodes
for i = 0, LIGHT_MAX do
    local name = 'magic_lantern:magic_lantern_' .. i
    table.insert(LANTERN_NODES, name)
    local obj = {
        tiles = { 'magic_lantern_' .. i .. '.png' },
        inventory_image = 'magic_lantern_' .. i .. '.png',
        drawtype = 'glasslike',
        paramtype = "light",
        walkable = true,
        sunlight_propagates = true,
        light_source = i,
        groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
        sounds = default.node_sound_glass_defaults(),
        furnace_burntime = 4,
    }
    if i == LIGHT_MAX then
        obj.description = "magic_lantern"
    end
    minetest.register_node(name, obj)
end

-- Functions
local function brightness_factor(level)
    -- we want non-linear; curve above x=y between 0 and LIGHT_MAX
    return math.floor((level / LIGHT_MAX) ^ (2 ^ 0.5 / 2) * LIGHT_MAX + 0.5)
end

minetest.register_abm({
    nodenames = LANTERN_NODES,
    interval = 3,
    chance = 1,
    action = function(pos, node, _, __)
        -- get ambient light only (ignore this source)
        local ambient = minetest.env:get_node_propagated_light(pos, nil) or 1

        -- current brightness and target brightness
        local current = minetest.registered_nodes[node.name].light_source or -1
        local target = brightness_factor(LIGHT_MAX + 1 - ambient)

        -- calculate the new setting
        local new = current + math.ceil((target - current) / 2)
        -- clip to the allowed range
        if new < 0 then
            new = 0
        elseif new > LIGHT_MAX then
            new = LIGHT_MAX
        end

        -- change the node if needed to set the new brightness
        if new ~= current then
            minetest.env:add_node(pos, { name = 'magic_lantern:magic_lantern_' .. new })
        end
    end
})

-- Crafts
minetest.register_craft({
    output = 'NodeItem "magic_lantern:magic_lantern_0" 1',
    recipe = {
        {'node "default:glass" 1', 'node "default:glass" 1', 'node "default:glass" 1'},
        {'node "default:glass" 1', 'node "default:torch" 1', 'node "default:glass" 1'},
        {'node "default:glass" 1', 'node "default:glass" 1', 'node "default:glass" 1'},
    },
})

Posted: Sun Mar 24, 2013 17:26
by bdjnk
edit: I case I wasn't clear, it does solve the flicker without rely on anything special

Working off the dsalt version, I have spewed out some hideously disjointed Lua to accommodate the deficiencies in the script API. It is terribly inefficient, absurdly roundabout, and might not work in all circumstances. With that glowing recommendation, here lies the beast:

Code: Select all

local LANTERN_NODES = {}

-- Nodes
for i = 0, LIGHT_MAX do
    local name = 'magic_lantern:magic_lantern_' .. i
    table.insert(LANTERN_NODES, name)
    local obj = {
        tiles = { 'magic_lantern_' .. i .. '.png' },
        inventory_image = 'magic_lantern_' .. i .. '.png',
        drawtype = 'glasslike',
        paramtype = "light",
        walkable = true,
        sunlight_propagates = true,
        light_source = i,
        groups = { snappy=2, cracky=3, oddly_breakable_by_hand=3 },
        sounds = default.node_sound_glass_defaults(),
        furnace_burntime = 4,
    }
    if i == LIGHT_MAX then
        obj.description = "magic_lantern"
    end
    minetest.register_node(name, obj)
end

minetest.register_abm({
    nodenames = LANTERN_NODES,
    interval = 8,
    chance = 1,
    action = function(pos, node, _, __)

        if node.name == 'ignore' then return end

        local minp = {x = 0, y = 0, z = 0}
        local maxp = {x = 0, y = 0, z = 0}

        for key,value in pairs(pos) do
            minp.x = pos.x - 3
            minp.y = pos.y - 3
            minp.z = pos.z - 3
            maxp.x = pos.x + 3
            maxp.y = pos.y + 3
            maxp.z = pos.z + 3
        end
        local locs = minetest.env:find_nodes_in_area(minp, maxp, {"air", "default:water", "default:glass"})

        local average = 0
        local count = 0
        for key,loc in pairs(locs) do
            if pos ~= loc then
                average = average + minetest.env:get_node_light(loc, nil)
                count = count + 1
            end
        end
        average = average / count

        local dimmer = (average - 10) * 3
        brightness = math.min(math.max(0, math.ceil(LIGHT_MAX - dimmer)), 14)

        minetest.env:add_node(pos, {name = 'magic_lantern:magic_lantern_' .. brightness})
    end
})

-- Crafts
minetest.register_craft({
    output = 'NodeItem "magic_lantern:magic_lantern_0" 1',
    recipe = {
        {'node "default:glass" 1', 'node "default:glass" 1', 'node "default:glass" 1'},
        {'node "default:glass" 1', 'node "default:torch" 1', 'node "default:glass" 1'},
        {'node "default:glass" 1', 'node "default:glass" 1', 'node "default:glass" 1'},
    },
})
Looking at it is making me physically ill. Hopefully this motivates a core developer to add a function to get a node's light level sans enumerated light sources.

Posted: Tue Mar 04, 2014 18:57
by Topywo
Version with bdjnk's code (+ commented description. Remove the comment -- to have (a lot of) lanterns in creative):

https://dl.dropboxusercontent.com/u/654 ... _bdjnk.zip