2013-05-27 17:27:55 +02:00

465 lines
12 KiB
Lua

redstone = {}
dofile(minetest.get_modpath("redstone").."/crafting.lua")
local function add(v1, v2)
return {x=v1.x+v2.x, y=v1.y+v2.y, z=v1.z+v2.z}
end
local function hacky_swap_node(pos,name, param2)
local node = minetest.env:get_node(pos)
local meta = minetest.env:get_meta(pos)
if node.name == name then
return
end
node.name = name
node.param2 = param2 or node.param2
local meta0 = meta:to_table()
minetest.env:set_node(pos,node)
meta = minetest.env:get_meta(pos)
meta:from_table(meta0)
end
local function get_wallmounted_dir(pos, param2)
local d = {x=0,y=0,z=0}
if param2 == 0 then
d.y = 1
elseif param2 == 1 then
d.y = -1
elseif param2 == 2 then
d.x = 1
elseif param2 == 3 then
d.x = -1
elseif param2 == 4 then
d.z = 1
elseif param2 == 5 then
d.z = -1
end
return d
end
local function get_wallmounted_node(pos, param2)
return add(pos, get_wallmounted_dir(pos, param2))
end
local function get_facedir_node(pos, param2)
local d = {x=0,y=0,z=0}
if param2 == 0 then
d.z = 1
elseif param2 == 1 then
d.x = 1
elseif param2 == 2 then
d.z = -1
elseif param2 == 3 then
d.x = -1
end
return add(pos, d)
end
function redstone.level_at(pos, rule)
rule = rule or {
{x= 1, y= 0, z=0},
{x=-1, y= 0, z=0},
{x= 1, y= 1, z=0},
{x=-1, y= 1, z=0},
{x= 1, y=-1, z=0},
{x=-1, y=-1, z=0},
{x=0, y= 0, z= 1},
{x=0, y= 0, z=-1},
{x=0, y= 1, z= 1},
{x=0, y= 1, z=-1},
{x=0, y=-1, z= 1},
{x=0, y=-1, z=-1},
}
local level = 0
for _,offset in ipairs(rule) do
local p = add(pos, offset)
local m = minetest.env:get_meta(p)
local tmp = tonumber(m:get_string("redstone_level")) or 0
if tmp > 0 then
tmp = tmp-1
end
if tmp > level then
level = tmp
end
end
return level
end
function redstone.set_level(pos, level, force)
local m = minetest.env:get_meta(pos)
if force or (level ~= (tonumber(m:get_string("redstone_level")) or 0)) then
m:set_string("redstone_level", tostring(level))
for dx=-1,1 do
for dy=-1,1 do
for dz=-1,1 do
if dx~=0 or dy~=0 or dz~=0 then
local p = add(pos, {x=dx, y=dy, z=dz})
local nn = minetest.env:get_node(p).name
if
minetest.registered_nodes[nn] and
minetest.registered_nodes[nn].redstone_update and
nn ~= "redstone:torch_off" and
nn ~= "redstone:torch_on"
then
minetest.registered_nodes[nn].redstone_update(p)
end
end
end
end
end
for dx=-2,2 do
for dy=-2,2 do
for dz=-2,2 do
if dx~=0 or dy~=0 or dz~=0 then
local p = add(pos, {x=dx, y=dy, z=dz})
local nn = minetest.env:get_node(p).name
if nn == "redstone:torch_off" or nn == "redstone:torch_on" then
minetest.after(0.5, function(p)
local nn = minetest.env:get_node(p).name
if nn == "redstone:torch_off" or nn == "redstone:torch_on" then
minetest.registered_nodes[nn].redstone_update(p)
end
end, p)
end
end
end
end
end
end
end
minetest.register_craftitem("redstone:redstone", {
description = "Redstone",
inventory_image = "redstone_redstone_item.png",
stack_max = 64,
sounds = default.node_sound_defaults(),
on_place = function(itemstack, placer, pointed_thing)
local tmpstack = ItemStack("redstone:redstone_off "..itemstack:get_count())
tmpstack = minetest.item_place(tmpstack, placer, pointed_thing)
return ItemStack("redstone:redstone "..tmpstack:get_count())
end,
})
minetest.register_node("redstone:redstone_off", {
tiles = {"redstone_redstone_off.png"},
drawtype = "raillike",
drop = "redstone:redstone",
walkable = false,
paramtype = "light",
groups = {dig_immediate=3,attached_node=1,not_in_creative_inventory=1},
sounds = default.node_sound_defaults(),
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -0.5+3/16, 0.5},
},
},
after_place_node = function(pos)
local level = redstone.level_at(pos)
if level > 0 then
minetest.env:set_node(pos, {name="redstone:redstone_on"})
end
redstone.set_level(pos, level)
end,
redstone_update = function(pos)
local level = redstone.level_at(pos)
if level > 0 then
minetest.env:set_node(pos, {name="redstone:redstone_on"})
end
redstone.set_level(pos, level)
end,
})
minetest.register_node("redstone:redstone_on", {
tiles = {"redstone_redstone_on.png"},
drawtype = "raillike",
drop = "redstone:redstone",
walkable = false,
paramtype = "light",
light_source = 5,
groups = {dig_immediate=3,attached_node=1,not_in_creative_inventory=1},
sounds = default.node_sound_defaults(),
selection_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -0.5+3/16, 0.5},
},
},
after_destruct = function(pos)
redstone.set_level(pos, 0, true)
end,
redstone_update = function(pos)
local level = redstone.level_at(pos)
if level <= 0 then
minetest.env:set_node(pos, {name="redstone:redstone_off"})
end
redstone.set_level(pos, level)
end,
})
minetest.register_node("redstone:lever_off", {
description = "Lever",
drawtype = "torchlike",
tiles = {"redstone_lever_bottom_off.png", "redstone_lever_wall_off.png"},
inventory_image = "redstone_lever_bottom_off.png",
wield_image = "redstone_lever_bottom_off.png",
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
stack_max = 64,
groups = {dig_immediate=3,attached_node=1},
sounds = default.node_sound_defaults(),
selection_box = {
type = "wallmounted",
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
},
on_rightclick = function(pos, node)
node.name = "redstone:lever_on"
minetest.env:set_node(pos, node)
redstone.set_level(pos, 16)
local param2 = minetest.env:get_node(pos).param2
redstone.set_level(get_wallmounted_node(pos, param2), 16)
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local p0 = pointed_thing.under
local p1 = pointed_thing.above
if p0.y-1 == p1.y then
return itemstack
end
return minetest.item_place(itemstack, placer, pointed_thing)
end,
})
minetest.register_node("redstone:lever_on", {
drawtype = "torchlike",
tiles = {"redstone_lever_bottom_on.png", "redstone_lever_wall_on.png"},
paramtype = "light",
paramtype2 = "wallmounted",
drop = "redstone:lever_off",
walkable = false,
groups = {dig_immediate=3,attached_node=1,not_in_creative_inventory=1},
sounds = default.node_sound_defaults(),
selection_box = {
type = "wallmounted",
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
},
after_destruct = function(pos, oldnode)
redstone.set_level(pos, 0, true)
redstone.set_level(get_wallmounted_node(pos, oldnode.param2), 0)
end,
on_rightclick = function(pos, node)
node.name = "redstone:lever_off"
minetest.env:set_node(pos, node)
redstone.set_level(pos, 0, true)
redstone.set_level(get_wallmounted_node(pos, node.param2), 0)
end,
})
minetest.register_node("redstone:torch_on", {
description = "Redstone Torch",
drawtype = "torchlike",
tiles = {
{name="default_torch_on_floor_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}},
{name="default_torch_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}
},
inventory_image = "default_torch_on_floor.png",
wield_image = "default_torch_on_floor.png",
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
light_source = 10,
selection_box = {
type = "wallmounted",
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
},
groups = {dig_immediate=3,attached_node=1},
stack_max = 64,
sounds = default.node_sound_defaults(),
redstone_update = function(pos)
local n = minetest.env:get_node(pos)
local m = minetest.env:get_meta(pos)
m:set_string("redstone_level", tostring(0))
local level = redstone.level_at(get_wallmounted_node(pos, n.param2), {get_wallmounted_dir(pos, n.param2)})
m:set_string("redstone_level", tostring(16))
if level > 0 then
n.name = "redstone:torch_off"
minetest.env:set_node(pos, n)
redstone.set_level(pos, 0)
else
redstone.set_level(pos, 16)
end
end,
after_destruct = function(pos, oldnode)
redstone.set_level(pos, 0, true)
end,
after_place_node = function(pos)
local n = minetest.env:get_node(pos)
local level = redstone.level_at(get_wallmounted_node(pos, n.param2), {get_wallmounted_dir(pos, n.param2)})
if level > 0 then
n.name = "redstone:torch_off"
minetest.env:set_node(pos, n)
redstone.set_level(pos, 0)
else
redstone.set_level(pos, 16)
end
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local p0 = pointed_thing.under
local p1 = pointed_thing.above
if p0.y-1 == p1.y then
return itemstack
end
return minetest.item_place(itemstack, placer, pointed_thing)
end,
})
minetest.register_node("redstone:torch_off", {
drawtype = "torchlike",
tiles = {
{name="default_torch_on_floor_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}},
{name="default_torch_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}
},
paramtype = "light",
paramtype2 = "wallmounted",
walkable = false,
drop = "redstone:torch_on",
selection_box = {
type = "wallmounted",
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
},
groups = {dig_immediate=3,attached_node=1,not_in_creative_inventory=1},
sounds = default.node_sound_defaults(),
redstone_update = function(pos)
local n = minetest.env:get_node(pos)
local level = redstone.level_at(get_wallmounted_node(pos, n.param2), {get_wallmounted_dir(pos, n.param2)})
if level <= 0 then
n.name = "redstone:torch_on"
minetest.env:set_node(pos, n)
redstone.set_level(pos, 16)
else
redstone.set_level(pos, 0)
end
end,
})
minetest.register_node("redstone:stone_with_redstone", {
description = "Redstone Ore",
tiles = {"default_stone.png^redstone_mineral_redstone.png"},
is_ground_content = true,
groups = {cracky=default.dig.redstone_ore},
drop = 'redstone:redstone 5',
stack_max = 64,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_ore({
ore_type = "scatter",
ore = "default:stone_with_diamond",
wherein = "default:stone",
clust_scarcity = 13*13*13,
clust_num_ores = 6,
clust_size = 3,
height_min = -59,
height_max = -52,
})
minetest.register_ore({
ore_type = "scatter",
ore = "default:stone_with_diamond",
wherein = "default:stone",
clust_scarcity = 15*15*15,
clust_num_ores = 4,
clust_size = 3,
height_min = -55,
height_max = -53,
})
minetest.register_node("redstone:button", {
description = "Button",
tiles = {"default_stone.png"},
inventory_image = "redstone_button_inventory.png",
wield_image = "redstone_button_inventory.png",
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
groups = {dig_immediate=2},
node_box = {
type = "fixed",
fixed = {
{-0.15, -0.1, 0.4, 0.15, 0.1, 0.5},
},
},
on_rightclick = function(pos, node)
redstone.set_level(pos, 16, true)
redstone.set_level(get_facedir_node(pos, node.param2), 16, true)
minetest.after(1, function(p1, p2)
redstone.set_level(p1, 0, true)
redstone.set_level(p2, 0, true)
end, pos, get_facedir_node(pos, node.param2))
end,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
local pp = placer:getpos()
local dir = {
x = pointed_thing.above.x - pp.x,
y = pointed_thing.above.y - pp.y,
z = pointed_thing.above.z - pp.z
}
local nn = minetest.env:get_node(get_facedir_node(pointed_thing.above, minetest.dir_to_facedir(dir))).name
if not minetest.registered_nodes[nn].walkable then
return itemstack
end
return minetest.item_place(itemstack, placer, pointed_thing)
end,
})
local function update_button_attachment(p)
-- Round p to prevent falling entities to get stuck
p.x = math.floor(p.x+0.5)
p.y = math.floor(p.y+0.5)
p.z = math.floor(p.z+0.5)
for x = -1,1 do
for y = -1,1 do
for z = -1,1 do
local n = minetest.env:get_node({x=p.x+x, y=p.y+y, z=p.z+z})
if n.name == "redstone:button" then
local nn = minetest.env:get_node(get_facedir_node({x=p.x+x, y=p.y+y, z=p.z+z}, n.param2)).name
if not minetest.registered_nodes[nn].walkable then
drop_attached_node({x=p.x+x, y=p.y+y, z=p.z+z})
end
end
end
end
end
end
minetest.register_on_dignode(update_button_attachment)
minetest.register_on_placenode(update_button_attachment)