2024-12-10 02:34:33 +01:00

699 lines
27 KiB
Lua

local S = minetest.get_translator("lzr_laser")
local colortiles = {
lzr_laser.TILE_LASER_R,
lzr_laser.TILE_LASER_G,
lzr_laser.TILE_LASER_Y,
lzr_laser.TILE_LASER_B,
lzr_laser.TILE_LASER_M,
lzr_laser.TILE_LASER_C,
lzr_laser.TILE_LASER_W,
}
-- Special string to mark a tile in a laser element as the 'laser tile'
-- for lzr_laser.register_element. The laser tile is the
-- the tile (texture) that represents the laser itself. This string
-- will be replaced automatically by the appropriate laser texture
-- on registration
lzr_laser.LASER_TILE = "<<<LASER>>>"
-- Update the lasers within level bounds, if neccessary
lzr_laser.full_laser_update_if_needed = function(extra_state)
local state = lzr_gamestate.get_state()
if state ~= lzr_gamestate.LEVEL and state ~= lzr_gamestate.LEVEL_COMPLETE and state ~= lzr_gamestate.LEVEL_TEST and state ~= lzr_gamestate.EDITOR and state ~= lzr_gamestate.DEV then
return false
end
local minpos, maxpos = lzr_world.get_level_bounds()
lzr_laser.full_laser_update(minpos, maxpos, extra_state)
return true
end
minetest.register_on_placenode(function(pos, newnode, placer)
local state = lzr_gamestate.get_state()
if state ~= lzr_gamestate.LEVEL and state ~= lzr_gamestate.LEVEL_COMPLETE and state ~= lzr_gamestate.LEVEL_TEST and state ~= lzr_gamestate.EDITOR and state ~= lzr_gamestate.DEV then
return
end
lzr_laser.full_laser_update_if_needed()
end)
minetest.register_on_dignode(function(pos, oldnode, placer)
local state = lzr_gamestate.get_state()
if state ~= lzr_gamestate.LEVEL and state ~= lzr_gamestate.LEVEL_COMPLETE and state ~= lzr_gamestate.LEVEL_TEST and state ~= lzr_gamestate.EDITOR and state ~= lzr_gamestate.DEV then
return
end
do
lzr_laser.full_laser_update_if_needed()
end
end)
local element_on_place = function(itemstack, placer, pointed_thing)
-- node's on_rightclick action takes precedence
if pointed_thing.type == "node" and placer then
local node = minetest.get_node(pointed_thing.under)
local def = minetest.registered_nodes[node.name]
local sneak = placer:get_player_control().sneak
if def and def.on_rightclick and not sneak then
def.on_rightclick(pointed_thing.under, node, placer, itemstack, pointed_thing)
return itemstack
end
end
-- Default node placement behavior
return minetest.item_place_node(itemstack, placer, pointed_thing)
end
--[[ Register a 'laser element', i.e. a collection of nodes that
are supposed to interact with lasers. Each of these nodes is called a 'laser block'.
A single laser element may register many many nodes, depending on its
complexity.
Laser elements may have the following properties:
* They may be in an active or inactive state
* They may be rotated by the player, or not (must be enabled with `options.allow_rotate`)
* They may be takable by the player, or not (must be enabled with `options.allow_take`)
(note: all takable nodes are also rotatable by implication)
* For the active state, by default a node for every laser color will be added
* All its nodes share a new group that identify it as part of a laser element (in `options.group`)
The registered nodes follow these naming conventions:
* `<basename>_fixed`: This is the base node. Inactive, cannot be taken or rotated
* `<basename>_fixed_on_<color>`: Active, cannot be taken or rotated.
* `<basename>_rotatable`: Inactive, can be rotated but not be taken
* `<basename>_rotatable_on_<color>`: Active, can be rotated but not be taken
* `<basename>_takable`: Inactive, can be taken and rotated
* `<basename>_takable_on_<color>`: Active, can be taken and rotated.
`<color>` is a colorcode from 1 to lzr_globals.MAX_COLORCODE.
If `options.register_color` is false, the active nodes won't have a `<color>`
suffix. Instead, they will be:
* `<basename>_fixed_on`: Active, non-takable, not-rotatable
* `<basename>_rotatable_on`: Active, rotatable, non-takable
* `<basename>_takable_on`: Active, rotatable, takable
Groups:
The following groups will be added automatically to the nodes:
* `[options.group]=1` to the inactive nodes
* `[options.group]=2` to the active nodes
* `breakable=1` to every node
* `takable=1` to nodes that can be taken by the player
* `rotatable=1` to nodes that can be rotated by the player
* `rotatable=3` to nodes that can only be rotated in the editor
* `not_in_creative_inventory=1` to active nodes by default
* `laser_block_color=<colorcode>` to active nodes with a laser color (not if `options.register_color` is false)
Parameters:
* basename: Itemstring identifier of the base node
May be preceded by a color to force a node name, as handled by minetest.register_node
* def: Definition table to define the node. All fields of the Luanti node definition can be applied here,
but note that some fields will be overwritten.
To use after_dig_node, you must specify it as __after_dig_node.
To use after_place_node, you must specify it as __after_place_node.
In addition, the following fields are special:
* description: Description of the base node. The other node variants
will have automatic variations added
* __tiles_off: `tiles` table for the inactive and non-takable state
* __tiles_on: `tiles` table for the active and non-takable state
* __tiles_rotatable_off: `tiles` table for the inactive and rotatable state
* __tiles_rotatable_on: `tiles` table for the active and rotatable state
* __tiles_takable_off: `tiles` table for the inactive and non-takable state
* __tiles_takable_on: `tiles` table for the active and non-takable state
* __sounds_off: `sounds` table for the inactive state
* __sounds_on: `sounds` table for the inactive state
* __overlay_tiles_off: `overlay_tiles` table for the inactive and non-takable state
* __overlay_tiles_on: `overlay_tiles` table for the active and non-takable state
* __overlay_tiles_rotatable_off: `overlay_tiles` table for the inactive and rotatable state
* __overlay_tiles_rotatable_on: `overlay_tiles` table for the active and rotatable state
* __overlay_tiles_takable_off: `overlay_tiles` table for the inactive and non-takable state
* __overlay_tiles_takable_on: `overlay_tiles` table for the active and non-takable state
* __mesh_off: `mesh` value in inactive state
* __mesh_on: `mesh` value in active state
* __tt_help_off: `_tt_help` field for the inactive state (see `tt` mod)
* __tt_help_on: `_tt_help` field for the active state (see `tt` mod)
* __light_source_on: `light_source` value for the nodes in active state (default: 0)
* __light_source_off: `light_source` value for the nodes in inactive state (default: 0)
* __use_texture_alpha_on: `on_texture_alpha` value for the nodes in active state
* __use_texture_alpha_off: `on_texture_alpha` value for the nodes in inactive state
* __after_dig_node: You must use this instead of `after_dig_node`
* __after_place_node: You must use this instead of `after_place_node`
* __on_place: You must use this instead of `on_place`
* __lzr_next_color: Contains the basename of the node with the next color in a
sequence of colors, for the color change tool (use only if register_colors is false)
* __lzr_prev_color: Same as __lzr_next_color, but for the previous color
Note about tiles: If your laser element has a laser in it, use the special tile `lzr_laser.LASER_TILE`
in the `tiles_*` tables to represent the tiles texture. This function will replace
it with the appropriate laser color.
* options: Additional options to further specify the laser element.
All fields are optional except 'group'. List of fields:
* group: Mandatory name of group that identifies the nodes as
part of the laser element to add. Will add [group]=1 for inactive nodes
and [group]=2 for active nodes. Will also be added as
the `_lzr_element_group` field to all nodes
* not_walkable_if_off: If true, the element turns non-walkable
if inactive (default: false)
* not_walkable_if_on: If true, the element turns non-walkable
if active (default: false)
* not_pointable_if_off: If true, the element turns non-pointable
if inactive (default: false)
* not_pointable_if_on: If true, the element turns non-pointable
if active (default: false)
* allow_take: If true, add 'takable' nodes (default: false)
* keep_state_on_take: If true, element will keep its on/off state
when taken by player (default: false)
* activate: If true, add 'activated' nodes (default: true)
* inactive: If set, override define the node name of the element in inactive
state, without the '_fixed', '_rotatable', '_takable' suffix
(default: nil)
* active_in_creative: If true, allow the 'active' nodes to
be shown in the “Creative inventory” (read: level editor)
(default: false)
* register_colors: If true, all laser color variants will
be added for the active node state, registering a node
for every colorcode (default: true)
* explicit_inactive_description: By default, the word "active" will be added
to the description to active nodes and nothing to inactive nodes.
Set this to true to add the word "inactive" for inactive nodes as well.
(default: false)
]]
lzr_laser.register_element = function(basename, def, options)
local real_basename = basename
if string.sub(basename, 1, 1) == ":" then
real_basename = string.sub(basename, 2, -1)
end
local special_fields = {
"__tiles_off",
"__tiles_on",
"__tiles_rotatable_off",
"__tiles_rotatable_on",
"__tiles_takable_off",
"__tiles_takable_on",
"__sounds_off",
"__sounds_on",
"__overlay_tiles_off",
"__overlay_tiles_on",
"__overlay_tiles_rotatable_off",
"__overlay_tiles_rotatable_on",
"__overlay_tiles_takable_off",
"__overlay_tiles_takable_on",
"__tt_help_off",
"__tt_help_on",
"__mesh_off",
"__mesh_on",
"__light_source_on",
"__light_source_off",
"__use_texture_alpha_on",
"__use_texture_alpha_off",
"__after_dig_node",
"__after_place_node",
"__on_place",
"__lzr_next_color",
"__lzr_prev_color",
}
local def_core = table.copy(def)
def_core._lzr_element_group = options.group
if def_core.groups and (def_core.groups.sender or def_core.groups.receiver) then
-- The following two functions transport the 'trigger_id' in
-- metadata from a trigger node when it
-- transforms from node to item form and vice-versa.
-- Also update the trigger location.
-- When a trigger node is converted to an item
def_core.preserve_metadata = function(pos, oldnode, oldmeta, drops)
if not oldmeta and not oldmeta.trigger_id then
return
end
local trigger_id = oldmeta.trigger_id
local gs = lzr_gamestate.get_state()
if gs ~= lzr_gamestate.LEVEL and gs ~= lzr_gamestate.LEVEL_TEST then
lzr_triggers.remove_trigger(trigger_id)
return
end
-- Copy the item's trigger_id into all of the node's drops.
-- This assumes the node has no 'weird' drops
-- like an additional item.
for d=1, #drops do
local dmeta = drops[d]:get_meta()
dmeta:set_string("trigger_id", trigger_id)
end
-- Update trigger location
lzr_triggers.set_trigger_location(trigger_id, "player")
end
-- When a trigger node has been placed back by the player
def_core.after_place_node = function(pos, placer, itemstack, pointed_thing)
local state = lzr_gamestate.get_state()
if state == lzr_gamestate.EDITOR then
local minpos, maxpos = lzr_world.get_level_bounds()
if vector.in_area(pos, minpos, maxpos) then
local trigger_id = lzr_triggers.add_trigger(pos)
if trigger_id then
local meta = minetest.get_meta(pos)
meta:set_string("trigger_id", trigger_id)
end
end
return
elseif state == lzr_gamestate.LEVEL or state == lzr_gamestate.LEVEL_TEST then
local minpos, maxpos = lzr_world.get_level_bounds()
if not vector.in_area(pos, minpos, maxpos) then
minetest.log("error", "[lzr_laser] Placed a trigger node out of level bounds at: "..minetest.pos_to_string(pos))
return
end
-- Copy item's trigger_id into node
local imeta = itemstack:get_meta()
local nmeta = minetest.get_meta(pos)
local trigger_id = imeta:get_string("trigger_id")
nmeta:set_string("trigger_id", trigger_id)
-- Update trigger location
if lzr_triggers.trigger_exists(trigger_id) then
lzr_triggers.set_trigger_location(trigger_id, pos)
else
minetest.log("error", "[lzr_laser] Tried to set trigger location of non-existing trigger at: "..minetest.pos_to_string(pos))
return
end
end
if def.__after_place_node then
def.__after_place_node(pos, placer, itemstack, pointed_thing)
end
end
if def_core.groups.sender then
def_core.after_dig_node = function(pos, oldnode, oldmeta, pointed_thing)
-- If a sender was dug, we have to pass its information to the laser update function
-- so it can update the trigger state properly. If we don't do this,
-- the laser update function will see the map incorrectly.
if lzr_laser.is_laser_block_active(oldnode.name) then
local triggered = false
if oldmeta and oldmeta.fields and oldmeta.fields.trigger_id then
local trigger_id = oldmeta.fields.trigger_id
local trigger = lzr_triggers.get_trigger(trigger_id)
if trigger then
local extra_state = {
removed_active_sender_trigger_id = trigger_id,
removed_active_sender_pos = pos,
removed_active_sender_send_to = lzr_triggers.get_receivers(trigger_id),
removed_active_sender_signal_type = trigger.signal_type,
}
lzr_laser.full_laser_update_if_needed(extra_state)
triggered = true
end
end
if not triggered then
local gs = lzr_gamestate.get_state()
if gs == lzr_gamestate.LEVEL or gs == lzr_gamestate.LEVEL_TEST then
minetest.log("error", "[lzr_laser] Dug node at "..minetest.pos_to_string(pos).." should be a trigger but appears not to be one")
end
end
end
if def.__after_dig_node then
def.__after_dig_node(pos, oldnode, oldmeta, pointed_thing)
end
end
end
end
local def_spec = {}
for s=1, #special_fields do
local field = special_fields[s]
def_spec[field] = def[field]
def_core[field] = nil
end
if not options then options = {} end
if options.not_walkable_if_off then
def_core.walkable = false
end
if options.not_pointable_if_off then
def_core.pointable = false
end
def_core._lzr_fixed = real_basename.."_fixed"
if options.allow_take then
def_core._lzr_takable = real_basename.."_takable"
end
if options.allow_rotate then
def_core._lzr_rotatable = real_basename.."_rotatable"
end
if options.allow_take or options.allow_rotate then
if options.explicit_inactive_description then
--~ Annotation for a block @1. "fixed" means it cannot be picked up or rotated
def_core.description = S("@1 (fixed, inactive)", def.description)
else
--~ Annotation for a block @1. "fixed" means it cannot be picked up or rotated
def_core.description = S("@1 (fixed)", def.description)
end
else
if options.explicit_inactive_description then
--~ Annotation for a block @1
def_core.description = S("@1 (inactive)", def.description)
else
def_core.description = def.description
end
end
def_core.tiles = def_spec.__tiles_off
def_core.overlay_tiles = def_spec.__overlay_tiles_off
def_core.mesh = def_spec.__mesh_off
if def_spec.__sounds_off then
def_core.sounds = def_spec.__sounds_off
end
if def_spec.__tt_help_off then
def_core._tt_help = def_spec.__tt_help_off
end
if def_spec.__use_texture_alpha_off then
def_core.use_texture_alpha = def_spec.__use_texture_alpha_off
end
if not def_core.groups then
def_core.groups = {}
end
def_core.groups.breakable = 1
if options.allow_rotate or options.allow_take then
def_core.groups.rotatable = 3
end
local groupname
if options.group then
groupname = options.group
else
error("[lzr_laser] lzr_laser.register_element: No group name specified in options for laser element with basename: "..tostring(basename))
end
def_core.groups[groupname] = 1
if def.__on_place then
def_core.on_place = def.__on_place
else
def_core.on_place = element_on_place
end
if options.inactive ~= nil then
def_core._lzr_inactive = options.inactive .. "_fixed"
if not options.keep_state_on_take then
def_core.drop = options.inactive .. "_fixed"
end
else
def_core._lzr_inactive = real_basename.."_fixed"
end
if options.activate ~= false then
def_core._lzr_active = real_basename .. "_fixed_on"
end
if def.__lzr_next_color then
def_core._lzr_next_color = def.__lzr_next_color.."_fixed"
def_core._lzr_prev_color = def.__lzr_prev_color.."_fixed"
end
minetest.register_node(basename.."_fixed", def_core)
local def_core_on
if options.activate ~= false then
def_core_on = table.copy(def_core)
if def.__lzr_next_color then
def_core_on._lzr_next_color = def.__lzr_next_color.."_fixed_on"
def_core_on._lzr_prev_color = def.__lzr_prev_color.."_fixed_on"
end
if options.not_walkable_if_off then
def_core_on.walkable = true
elseif options.not_walkable_if_on then
def_core_on.walkable = false
end
if options.not_pointable_if_off then
def_core_on.pointable = true
elseif options.not_pointable_if_on then
def_core_on.pointable = false
end
if options.allow_take or options.allow_rotate then
--~ Annotation for a block @1. "fixed" it means cannot be picked up or rotated
def_core_on.description = S("@1 (fixed, active)", def.description)
else
--~ Annotation for a block @1
def_core_on.description = S("@1 (active)", def.description)
end
def_core_on._lzr_inactive = real_basename.."_fixed"
def_core_on.tiles = def_spec.__tiles_on
def_core_on.overlay_tiles = def_spec.__overlay_tiles_on
def_core_on.mesh = def_spec.__mesh_on
if def_spec.__sounds_on then
def_core_on.sounds = def_spec.__sounds_on
end
if def_spec.__tt_help_on then
def_core_on._tt_help = def_spec.__tt_help_on
end
if def_spec.__use_texture_alpha_on then
def_core_on.use_texture_alpha = def_spec.__use_texture_alpha_on
end
if not options.keep_state_on_take then
def_core_on.drop = real_basename.."_fixed"
end
def_core_on._lzr_fixed = real_basename.."_fixed_on"
if options.allow_take then
def_core_on._lzr_takable = real_basename.."_takable_on"
end
def_core_on.groups[groupname] = 2
if not options.active_in_creative then
def_core_on.groups.not_in_creative_inventory = 1
def_core_on.inventory_image = nil
def_core_on.wield_image = nil
end
def_core_on.light_source = def_spec.__light_source_on
if options.register_color == false then
def_core_on._lzr_fixed = real_basename.."_fixed_on"
if options.allow_take then
def_core_on._lzr_takable = real_basename.."_takable_on"
end
if options.allow_rotate then
def_core_on._lzr_rotatable = real_basename.."_rotatable_on"
end
minetest.register_node(basename.."_fixed_on", def_core_on)
else
for c=1, lzr_globals.MAX_COLORCODE do
local def_core_on_c = table.copy(def_core_on)
if options.allow_take or options.allow_rotate then
--~ Annotation for a block @1. "fixed" means it cannot be picked up or rotated. @2 is a color code uniquely identifying the active laser color in that block
def_core_on_c.description = S("@1 (fixed, active, @2)", def.description, lzr_laser.dirstring_to_colstring(tostring(c)))
else
--~ Annotation for a block @1. @2 is a color code uniquely identifying the active laser color in that block
def_core_on_c.description = S("@1 (active, @2)", def.description, lzr_laser.dirstring_to_colstring(tostring(c)))
end
for t=1, #def_core_on_c.tiles do
if def_core_on_c.tiles[t] == lzr_laser.LASER_TILE then
def_core_on_c.tiles[t] = colortiles[c]
end
end
def_core_on_c.groups.laser_block_color = c
def_core_on_c._lzr_fixed = real_basename.."_fixed_on_"..c
if options.allow_take then
def_core_on_c._lzr_takable = real_basename.."_takable_on_"..c
end
if options.allow_rotate then
def_core_on_c._lzr_rotatable = real_basename.."_rotatable_on_"..c
end
minetest.register_node(basename.."_fixed_on_"..c, def_core_on_c)
end
end
end
if options.allow_rotate then
local def_rotatable = table.copy(def_core)
def_rotatable._lzr_fixed = real_basename.."_fixed"
if options.allow_take then
def_rotatable._lzr_takable = real_basename.."_takable"
end
def_rotatable._lzr_rotatable = real_basename.."_rotatable"
def_rotatable.tiles = def_spec.__tiles_rotatable_off
def_rotatable.overlay_tiles = def_spec.__overlay_tiles_rotatable_off
def_rotatable.groups.rotatable = 1
if options.explicit_inactive_description then
--~ Annotation for a block @1. "soft-fixed" means it cannot be picked up but it CAN be rotated
def_rotatable.description = S("@1 (soft-fixed, inactive)", def.description)
else
--~ Annotation for a block @1. "soft-fixed" means it cannot be picked up but it CAN be rotated
def_rotatable.description = S("@1 (soft-fixed)", def.description)
end
if options.inactive ~= nil then
def_rotatable._lzr_inactive = options.inactive.."_rotatable"
if not options.keep_state_on_take then
def_rotatable.drop = options.inactive.."_rotatable"
end
else
def_rotatable._lzr_inactive = real_basename.."_rotatable"
end
if def.__lzr_next_color then
def_rotatable._lzr_next_color = def.__lzr_next_color.."_rotatable"
def_rotatable._lzr_prev_color = def.__lzr_prev_color.."_rotatable"
end
if options.activate ~= false then
def_rotatable._lzr_active = real_basename.."_rotatable_on"
end
minetest.register_node(basename.."_rotatable", def_rotatable)
if options.activate ~= false then
local def_rotatable_on = table.copy(def_core_on)
if def.__lzr_next_color then
def_rotatable_on._lzr_next_color = def.__lzr_next_color.."_rotatable_on"
def_rotatable_on._lzr_prev_color = def.__lzr_prev_color.."_rotatable_on"
end
def_rotatable_on.tiles = def_spec.__tiles_rotatable_on
def_rotatable_on.overlay_tiles = def_spec.__overlay_tiles_rotatable_on
def_rotatable_on.light_source = def_spec.__light_source_on
def_rotatable_on.groups.rotatable = 1
if not options.active_in_creative then
def_rotatable_on.groups.not_in_creative_inventory = 1
def_rotatable_on.inventory_image = nil
def_rotatable_on.wield_image = nil
end
--~ Annotation for a block @1. "soft-fixed" means it cannot be picked up but it CAN be rotated
def_rotatable_on.description = S("@1 (soft-fixed, active)", def.description)
if not options.keep_state_on_take then
def_rotatable_on.drop = real_basename.."_rotatable"
end
def_rotatable_on._lzr_inactive = real_basename.."_rotatable"
def_rotatable_on._lzr_active = real_basename.."_rotatable_on"
if options.register_color == false then
def_rotatable_on._lzr_fixed = real_basename.."_fixed_on"
if options.allow_take then
def_rotatable_on._lzr_takable = real_basename.."_takable_on"
end
def_rotatable_on._lzr_rotatable = real_basename.."_rotatable_on"
minetest.register_node(basename.."_rotatable_on", def_rotatable_on)
else
for c=1, lzr_globals.MAX_COLORCODE do
local def_rotatable_on_c = table.copy(def_rotatable_on)
--~ Annotation for a block @1. "soft-fixed" means it cannot be picked up but it CAN be rotated. @2 is a color code uniquely identifying the block's laser color
def_rotatable_on_c.description = S("@1 (soft-fixed, active, @2)", def.description, lzr_laser.dirstring_to_colstring(tostring(c)))
for t=1, #def_rotatable_on_c.tiles do
if def_rotatable_on_c.tiles[t] == lzr_laser.LASER_TILE then
def_rotatable_on_c.tiles[t] = colortiles[c]
end
end
def_rotatable_on_c.groups.laser_block_color = c
def_rotatable_on_c._lzr_fixed = real_basename.."_fixed_on_"..c
if options.allow_take then
def_rotatable_on_c._lzr_takable = real_basename.."_takable_on_"..c
end
def_rotatable_on_c._lzr_rotatable = real_basename.."_rotatable_on_"..c
minetest.register_node(basename.."_rotatable_on_"..c, def_rotatable_on_c)
end
end
end
end
if options.allow_take then
local def_takable = table.copy(def_core)
def_takable._lzr_fixed = real_basename.."_fixed"
if options.allow_rotate then
def_takable._lzr_rotatable = real_basename.."_rotatable"
end
def_takable._lzr_takable = real_basename.."_takable"
def_takable.tiles = def_spec.__tiles_takable_off
def_takable.overlay_tiles = def_spec.__overlay_tiles_takable_off
def_takable.groups.takable = 1
-- takable nodes are also always rotatable by implication
def_takable.groups.rotatable = 1
if options.explicit_inactive_description then
--~ Annotation for a block @1
def_takable.description = S("@1 (inactive)", def.description)
else
def_takable.description = def.description
end
if options.inactive ~= nil then
def_takable._lzr_inactive = options.inactive.."_takable"
if not options.keep_state_on_take then
def_takable.drop = options.inactive.."_takable"
end
else
def_takable._lzr_inactive = real_basename.."_takable"
end
if def.__lzr_next_color then
def_takable._lzr_next_color = def.__lzr_next_color.."_takable"
def_takable._lzr_prev_color = def.__lzr_prev_color.."_takable"
end
if options.activate ~= false then
def_takable._lzr_active = real_basename.."_takable_on"
end
minetest.register_node(basename.."_takable", def_takable)
if options.activate ~= false then
local def_takable_on = table.copy(def_core_on)
if def.__lzr_next_color then
def_takable_on._lzr_next_color = def.__lzr_next_color.."_takable_on"
def_takable_on._lzr_prev_color = def.__lzr_prev_color.."_takable_on"
end
def_takable_on.tiles = def_spec.__tiles_takable_on
def_takable_on.overlay_tiles = def_spec.__overlay_tiles_takable_on
def_takable_on.light_source = def_spec.__light_source_on
def_takable_on.groups.takable = 1
def_takable_on.groups.rotatable = 1
if not options.active_in_creative then
def_takable_on.groups.not_in_creative_inventory = 1
def_takable_on.inventory_image = nil
def_takable_on.wield_image = nil
end
def_takable_on.description = S("@1 (active)", def.description)
if not options.keep_state_on_take then
def_takable_on.drop = real_basename.."_takable"
end
def_takable_on._lzr_inactive = real_basename.."_takable"
def_takable_on._lzr_active = real_basename.."_takable_on"
if options.register_color == false then
def_takable_on._lzr_fixed = real_basename.."_fixed_on"
if options.allow_rotate then
def_takable_on._lzr_rotatable = real_basename.."_rotatable_on"
end
def_takable_on._lzr_takable = real_basename.."_takable_on"
minetest.register_node(basename.."_takable_on", def_takable_on)
else
for c=1, lzr_globals.MAX_COLORCODE do
local def_takable_on_c = table.copy(def_takable_on)
--~ Annotation for a block @1. @2 is a color core uniquely identifying this block's laser color
def_takable_on_c.description = S("@1 (active, @2)", def.description, lzr_laser.dirstring_to_colstring(tostring(c)))
for t=1, #def_takable_on_c.tiles do
if def_takable_on_c.tiles[t] == lzr_laser.LASER_TILE then
def_takable_on_c.tiles[t] = colortiles[c]
end
end
def_takable_on_c.groups.laser_block_color = c
def_takable_on_c._lzr_fixed = real_basename.."_fixed_on_"..c
if options.allow_rotate then
def_takable_on_c._lzr_rotatable = real_basename.."_rotatable_on_"..c
end
def_takable_on_c._lzr_takable = real_basename.."_takable_on_"..c
minetest.register_node(basename.."_takable_on_"..c, def_takable_on_c)
end
end
end
end
end