1
0
mirror of https://github.com/mt-mods/homedecor_modpack.git synced 2025-06-28 12:56:01 +02:00

Split the big "homedecor" mod into multiple sub-mods

Any of these new submods can be run without any other
components that were once part of the big "homedecor"
mod, other than homedecor_common and homedecor_i18n

Reduced dependencies where possible, but each submod still
has its various dependencies more or less the same as before,
i.e. some need basic_materials, others need unifieddyes,
some need building_blocks, and so on.

All of the stuff that used to be under homedecor/handlers
got moved to homedecor_common, as did any models and/or textures
that are used by more than one other homedecor component.

All the miscellaneous items that didn't warrant their own
mod ended up in homedecor_misc, which can also be thought
of as the remains of the original "homedecor" mod, renamed.
This commit is contained in:
Vanessa Dannenberg
2019-04-20 15:49:36 -04:00
parent 95590f23c5
commit b08c0905c0
732 changed files with 4520 additions and 4430 deletions

View File

@ -0,0 +1,73 @@
-- crafts for common items that are used by more than one home decor component
local S = homedecor_i18n.gettext
-- items
minetest.register_craftitem(":homedecor:roof_tile_terracotta", {
description = S("Terracotta Roof Tile"),
inventory_image = "homedecor_roof_tile_terracotta.png",
})
minetest.register_craftitem(":homedecor:drawer_small", {
description = S("Small Wooden Drawer"),
inventory_image = "homedecor_drawer_small.png",
})
-- cooking/fuel
minetest.register_craft({
type = "cooking",
output = "homedecor:roof_tile_terracotta",
recipe = "basic_materials:terracotta_base",
})
minetest.register_craft({
type = "fuel",
recipe = "homedecor:shingles_wood",
burntime = 30,
})
-- crafing
minetest.register_craft( {
output = "homedecor:shingles_terracotta",
recipe = {
{ "homedecor:roof_tile_terracotta", "homedecor:roof_tile_terracotta"},
{ "homedecor:roof_tile_terracotta", "homedecor:roof_tile_terracotta"},
},
})
minetest.register_craft( {
output = "homedecor:roof_tile_terracotta 8",
recipe = {
{ "homedecor:shingles_terracotta", "homedecor:shingles_terracotta" }
}
})
minetest.register_craft( {
output = "homedecor:shingles_wood 12",
recipe = {
{ "group:stick", "group:wood"},
{ "group:wood", "group:stick"},
},
})
minetest.register_craft( {
output = "homedecor:shingles_wood 12",
recipe = {
{ "group:wood", "group:stick"},
{ "group:stick", "group:wood"},
},
})
minetest.register_craft( {
output = "homedecor:shingles_asphalt 6",
recipe = {
{ "building_blocks:gravel_spread", "dye:black", "building_blocks:gravel_spread" },
{ "group:sand", "dye:black", "group:sand" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
},
})

View File

@ -0,0 +1,4 @@
default
homedecor_i18n
creative
building_blocks?

View File

@ -0,0 +1,379 @@
local S = homedecor_i18n.gettext
-- vectors to place one node next to or behind another
homedecor.fdir_to_right = {
{ 1, 0 },
{ 0, -1 },
{ -1, 0 },
{ 0, 1 },
}
homedecor.fdir_to_left = {
{ -1, 0 },
{ 0, 1 },
{ 1, 0 },
{ 0, -1 },
}
homedecor.fdir_to_fwd = {
{ 0, 1 },
{ 1, 0 },
{ 0, -1 },
{ -1, 0 },
}
-- special case for wallmounted nodes
homedecor.wall_fdir_to_right = {
nil,
nil,
{ -1, 0 },
{ 1, 0 },
{ 0, -1 },
{ 0, 1 },
}
homedecor.wall_fdir_to_left = {
nil,
nil,
{ 1, 0 },
{ -1, 0 },
{ 0, 1 },
{ 0, -1 },
}
homedecor.wall_fdir_to_fwd = {
nil,
nil,
{ 0, -1 },
{ 0, 1 },
{ 1, 0 },
{ -1, 0 },
}
local placeholder_node = "air"
minetest.register_alias("homedecor:expansion_placeholder", "air")
--- select which node was pointed at based on it being known, not ignored, buildable_to
-- returns nil if no node could be selected
local function select_node(pointed_thing)
local pos = pointed_thing.under
local node = minetest.get_node_or_nil(pos)
local def = node and minetest.registered_nodes[node.name]
if not def or not def.buildable_to then
pos = pointed_thing.above
node = minetest.get_node_or_nil(pos)
def = node and minetest.registered_nodes[node.name]
end
return def and pos, def
end
--- check if all nodes can and may be build to
local function is_buildable_to(placer_name, ...)
for _, pos in ipairs({...}) do
local node = minetest.get_node_or_nil(pos)
local def = node and minetest.registered_nodes[node.name]
if not (def and def.buildable_to) or minetest.is_protected(pos, placer_name) then
return false
end
end
return true
end
-- place one or two nodes if and only if both can be placed
local function stack(itemstack, placer, fdir, pos, def, pos2, node1, node2, pointed_thing)
local placer_name = placer:get_player_name() or ""
if is_buildable_to(placer_name, pos, pos2) then
local lfdir = fdir or minetest.dir_to_facedir(placer:get_look_dir())
minetest.set_node(pos, { name = node1, param2 = lfdir })
node2 = node2 or "air" -- this can be used to clear buildable_to nodes even though we are using a multinode mesh
-- do not assume by default, as we still might want to allow overlapping in some cases
local has_facedir = node2 ~= "air"
if node2 == "placeholder" then
has_facedir = false
node2 = placeholder_node
end
minetest.set_node(pos2, { name = node2, param2 = (has_facedir and lfdir) or nil })
-- call after_place_node of the placed node if available
local ctrl_node_def = minetest.registered_nodes[node1]
if ctrl_node_def and ctrl_node_def.after_place_node then
ctrl_node_def.after_place_node(pos, placer, itemstack, pointed_thing)
end
if not creative.is_enabled_for(placer_name) then
itemstack:take_item()
end
end
return itemstack
end
local function rightclick_pointed_thing(pos, placer, itemstack, pointed_thing)
local node = minetest.get_node_or_nil(pos)
if not node then return false end
local def = minetest.registered_nodes[node.name]
if not def or not def.on_rightclick then return false end
return def.on_rightclick(pos, node, placer, itemstack, pointed_thing) or itemstack
end
-- Stack one node above another
-- leave the last argument nil if it's one 2m high node
function homedecor.stack_vertically(itemstack, placer, pointed_thing, node1, node2)
local rightclick_result = rightclick_pointed_thing(pointed_thing.under, placer, itemstack, pointed_thing)
if rightclick_result then return rightclick_result end
local pos, def = select_node(pointed_thing)
if not pos then return itemstack end
local top_pos = { x=pos.x, y=pos.y+1, z=pos.z }
return stack(itemstack, placer, nil, pos, def, top_pos, node1, node2, pointed_thing)
end
-- Stack one door node above another
-- like homedecor.stack_vertically but tests first if it was placed as a right wing, then uses node1_right and node2_right instead
function homedecor.stack_wing(itemstack, placer, pointed_thing, node1, node2, node1_right, node2_right)
local rightclick_result = rightclick_pointed_thing(pointed_thing.under, placer, itemstack, pointed_thing)
if rightclick_result then return rightclick_result end
local pos, def = select_node(pointed_thing)
if not pos then return itemstack end
local forceright = placer:get_player_control()["sneak"]
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
local is_right_wing = node1 == minetest.get_node({ x = pos.x + homedecor.fdir_to_left[fdir+1][1], y=pos.y, z = pos.z + homedecor.fdir_to_left[fdir+1][2] }).name
if forceright or is_right_wing then
node1, node2 = node1_right, node2_right
end
local top_pos = { x=pos.x, y=pos.y+1, z=pos.z }
return stack(itemstack, placer, fdir, pos, def, top_pos, node1, node2, pointed_thing)
end
function homedecor.stack_sideways(itemstack, placer, pointed_thing, node1, node2, dir)
local rightclick_result = rightclick_pointed_thing(pointed_thing.under, placer, itemstack, pointed_thing)
if rightclick_result then return rightclick_result end
local pos, def = select_node(pointed_thing)
if not pos then return itemstack end
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
local fdir_transform = dir and homedecor.fdir_to_right or homedecor.fdir_to_fwd
local pos2 = { x = pos.x + fdir_transform[fdir+1][1], y=pos.y, z = pos.z + fdir_transform[fdir+1][2] }
return stack(itemstack, placer, fdir, pos, def, pos2, node1, node2, pointed_thing)
end
function homedecor.bed_expansion(pos, placer, itemstack, pointed_thing, trybunks)
local thisnode = minetest.get_node(pos)
local param2 = thisnode.param2
local fdir = param2 % 8
local fxd = homedecor.wall_fdir_to_fwd[fdir+1][1]
local fzd = homedecor.wall_fdir_to_fwd[fdir+1][2]
local forwardpos = {x=pos.x+fxd, y=pos.y, z=pos.z+fzd}
local forwardnode = minetest.get_node(forwardpos)
local def = minetest.registered_nodes[forwardnode.name]
local placer_name = placer:get_player_name()
if not (def and def.buildable_to) then
minetest.chat_send_player( placer:get_player_name(),
S("Not enough room - the space for the headboard is occupied!"))
minetest.set_node(pos, {name = "air"})
return true
end
if minetest.is_protected(forwardpos, placer_name) then
minetest.chat_send_player( placer:get_player_name(),
S("Someone already owns the spot where the headboard goes."))
return true
end
minetest.set_node(forwardpos, {name = "air"})
local lxd = homedecor.wall_fdir_to_left[fdir+1][1]
local lzd = homedecor.wall_fdir_to_left[fdir+1][2]
local leftpos = {x=pos.x+lxd, y=pos.y, z=pos.z+lzd}
local leftnode = minetest.get_node(leftpos)
local rxd = homedecor.wall_fdir_to_right[fdir+1][1]
local rzd = homedecor.wall_fdir_to_right[fdir+1][2]
local rightpos = {x=pos.x+rxd, y=pos.y, z=pos.z+rzd}
local rightnode = minetest.get_node(rightpos)
local inv = placer:get_inventory()
if leftnode.name == "homedecor:bed_regular" then
local newname = string.gsub(thisnode.name, "_regular", "_kingsize")
local meta = minetest.get_meta(pos)
local leftmeta = minetest.get_meta(leftpos)
minetest.set_node(pos, {name = "air"})
minetest.swap_node(leftpos, { name = newname, param2 = param2})
elseif rightnode.name == "homedecor:bed_regular" then
local newname = string.gsub(thisnode.name, "_regular", "_kingsize")
local meta = minetest.get_meta(pos)
local rightmeta = minetest.get_meta(rightpos)
minetest.set_node(rightpos, {name = "air"})
minetest.swap_node(pos, { name = newname, param2 = param2})
end
local toppos = {x=pos.x, y=pos.y+1.0, z=pos.z}
local topposfwd = {x=toppos.x+fxd, y=toppos.y, z=toppos.z+fzd}
if trybunks and is_buildable_to(placer_name, toppos, topposfwd) then
local newname = string.gsub(thisnode.name, "_regular", "_extended")
local newparam2 = param2 % 8
minetest.swap_node(toppos, { name = thisnode.name, param2 = param2})
minetest.swap_node(pos, { name = newname, param2 = param2})
itemstack:take_item()
end
end
function homedecor.unextend_bed(pos)
local bottomnode = minetest.get_node({x=pos.x, y=pos.y-1.0, z=pos.z})
local param2 = bottomnode.param2
if bottomnode.name == "homedecor:bed_extended" then
local newname = string.gsub(bottomnode.name, "_extended", "_regular")
minetest.swap_node({x=pos.x, y=pos.y-1.0, z=pos.z}, { name = newname, param2 = param2})
end
end
function homedecor.place_banister(itemstack, placer, pointed_thing)
local rightclick_result = rightclick_pointed_thing(pointed_thing.under, placer, itemstack, pointed_thing)
if rightclick_result then return rightclick_result end
local pos, _ = select_node(pointed_thing)
if not pos then return itemstack end
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
local meta = itemstack:get_meta()
local pindex = meta:get_int("palette_index")
local abovepos = { x=pos.x, y=pos.y+1, z=pos.z }
local abovenode = minetest.get_node(abovepos)
local adef = minetest.registered_nodes[abovenode.name]
local placer_name = placer:get_player_name()
if not (adef and adef.buildable_to) then
minetest.chat_send_player(placer_name, S("Not enough room - the upper space is occupied!" ))
return itemstack
end
if minetest.is_protected(abovepos, placer_name) then
minetest.chat_send_player(placer_name, S("Someone already owns that spot."))
return itemstack
end
local lxd = homedecor.fdir_to_left[fdir+1][1]
local lzd = homedecor.fdir_to_left[fdir+1][2]
local rxd = homedecor.fdir_to_right[fdir+1][1]
local rzd = homedecor.fdir_to_right[fdir+1][2]
local fxd = homedecor.fdir_to_fwd[fdir+1][1]
local fzd = homedecor.fdir_to_fwd[fdir+1][2]
local below_pos = { x=pos.x, y=pos.y-1, z=pos.z }
local fwd_pos = { x=pos.x+fxd, y=pos.y, z=pos.z+fzd }
local left_pos = { x=pos.x+lxd, y=pos.y, z=pos.z+lzd }
local right_pos = { x=pos.x+rxd, y=pos.y, z=pos.z+rzd }
local left_fwd_pos = { x=pos.x+lxd+fxd, y=pos.y, z=pos.z+lzd+fzd }
local right_fwd_pos = { x=pos.x+rxd+fxd, y=pos.y, z=pos.z+rzd+fzd }
local right_fwd_above_pos = { x=pos.x+rxd+fxd, y=pos.y+1, z=pos.z+rzd+fzd }
local left_fwd_above_pos = { x=pos.x+lxd+fxd, y=pos.y+1, z=pos.z+lzd+fzd }
local right_fwd_below_pos = { x=pos.x+rxd+fxd, y=pos.y-1, z=pos.z+rzd+fzd }
local left_fwd_below_pos = { x=pos.x+lxd+fxd, y=pos.y-1, z=pos.z+lzd+fzd }
local below_node = minetest.get_node(below_pos)
--local fwd_node = minetest.get_node(fwd_pos)
local left_node = minetest.get_node(left_pos)
local right_node = minetest.get_node(right_pos)
local left_fwd_node = minetest.get_node(left_fwd_pos)
local right_fwd_node = minetest.get_node(right_fwd_pos)
local left_below_node = minetest.get_node({x=left_pos.x, y=left_pos.y-1, z=left_pos.z})
local right_below_node = minetest.get_node({x=right_pos.x, y=right_pos.y-1, z=right_pos.z})
--local right_fwd_above_node = minetest.get_node(right_fwd_above_pos)
--local left_fwd_above_node = minetest.get_node(left_fwd_above_pos)
local right_fwd_below_node = minetest.get_node(right_fwd_below_pos)
local left_fwd_below_node = minetest.get_node(left_fwd_below_pos)
local new_place_name = itemstack:get_name()
-- try to place a diagonal one on the side of blocks stacked like stairs
-- or follow an existing diagonal with another.
if (left_below_node and string.find(left_below_node.name, "banister_.-_diagonal_right")
and below_node and is_buildable_to(placer_name, below_pos, below_pos))
or not is_buildable_to(placer_name, right_fwd_above_pos, right_fwd_above_pos) then
new_place_name = string.gsub(new_place_name, "_horizontal", "_diagonal_right")
elseif (right_below_node and string.find(right_below_node.name, "banister_.-_diagonal_left")
and below_node and is_buildable_to(placer_name, below_pos, below_pos))
or not is_buildable_to(placer_name, left_fwd_above_pos, left_fwd_above_pos) then
new_place_name = string.gsub(new_place_name, "_horizontal", "_diagonal_left")
-- try to follow a diagonal with the corresponding horizontal
-- from the top of a diagonal...
elseif left_below_node and string.find(left_below_node.name, "homedecor:banister_.*_diagonal") then
fdir = left_below_node.param2
new_place_name = string.gsub(left_below_node.name, "_diagonal_.-$", "_horizontal")
elseif right_below_node and string.find(right_below_node.name, "homedecor:banister_.*_diagonal") then
fdir = right_below_node.param2
new_place_name = string.gsub(right_below_node.name, "_diagonal_.-$", "_horizontal")
-- try to place a horizontal in-line with the nearest diagonal, at the top
elseif left_fwd_below_node and string.find(left_fwd_below_node.name, "homedecor:banister_.*_diagonal")
and is_buildable_to(placer_name, fwd_pos, fwd_pos) then
fdir = left_fwd_below_node.param2
pos = fwd_pos
new_place_name = string.gsub(left_fwd_below_node.name, "_diagonal_.-$", "_horizontal")
elseif right_fwd_below_node and string.find(right_fwd_below_node.name, "homedecor:banister_.*_diagonal")
and is_buildable_to(placer_name, fwd_pos, fwd_pos) then
fdir = right_fwd_below_node.param2
pos = fwd_pos
new_place_name = string.gsub(right_fwd_below_node.name, "_diagonal_.-$", "_horizontal")
-- try to follow a diagonal with a horizontal, at the bottom of the diagonal
elseif left_node and string.find(left_node.name, "homedecor:banister_.*_diagonal") then
fdir = left_node.param2
new_place_name = string.gsub(left_node.name, "_diagonal_.-$", "_horizontal")
elseif right_node and string.find(right_node.name, "homedecor:banister_.*_diagonal") then
fdir = right_node.param2
new_place_name = string.gsub(right_node.name, "_diagonal_.-$", "_horizontal")
-- try to place a horizontal in-line with the nearest diagonal, at the bottom
elseif left_fwd_node and string.find(left_fwd_node.name, "homedecor:banister_.*_diagonal")
and is_buildable_to(placer_name, fwd_pos, fwd_pos) then
fdir = left_fwd_node.param2
pos = fwd_pos
new_place_name = string.gsub(left_fwd_node.name, "_diagonal_.-$", "_horizontal")
elseif right_fwd_node and string.find(right_fwd_node.name, "homedecor:banister_.*_diagonal")
and is_buildable_to(placer_name, fwd_pos, fwd_pos) then
fdir = right_fwd_node.param2
pos = fwd_pos
new_place_name = string.gsub(right_fwd_node.name, "_diagonal_.-$", "_horizontal")
end
-- manually invert left-right orientation
if placer:get_player_control()["sneak"] then
if string.find(new_place_name, "banister_.*_diagonal") then
new_place_name = string.gsub(new_place_name, "_left", "_right")
else
new_place_name = string.gsub(new_place_name, "_right", "_left")
end
end
minetest.set_node(pos, {name = new_place_name, param2 = fdir+pindex})
itemstack:take_item()
return itemstack
end

View File

@ -0,0 +1,283 @@
-- This code supplies an oven/stove. Basically it's just a copy of the default furnace with different textures.
local S = homedecor_i18n.gettext
local function swap_node(pos, name)
local node = minetest.get_node(pos)
if node.name == name then return end
node.name = name
minetest.swap_node(pos, node)
end
local function make_formspec(furnacedef, percent)
local fire
if percent and (percent > 0) then
fire = ("%s^[lowpart:%d:%s"):format(
furnacedef.fire_bg,
(100-percent),
furnacedef.fire_fg
)
else
fire = "default_furnace_fire_bg.png"
end
local w = furnacedef.output_width
local h = math.ceil(furnacedef.output_slots / furnacedef.output_width)
return "size["..math.max(8, 6 + w)..",9]"..
"image[2,2;1,1;"..fire.."]"..
"list[current_name;fuel;2,3;1,1;]"..
"list[current_name;src;2,1;1,1;]"..
"list[current_name;dst;5,1;"..w..","..h..";]"..
"list[current_player;main;0,5;8,4;]"..
"listring[current_name;dst]"..
"listring[current_player;main]"..
"listring[current_name;src]"..
"listring[current_player;main]"
end
--[[
furnacedef = {
description = "Oven",
tiles = { ... },
tiles_active = { ... },
^ +Y -Y +X -X +Z -Z
tile_format = "oven_%s%s.png",
^ First '%s' replaced by one of "top", "bottom", "side", "front".
^ Second '%s' replaced by "" for inactive, and "_active" for active "front"
^ "side" is used for left, right and back.
^ tiles_active for front is set
output_slots = 4,
output_width = 2,
cook_speed = 1,
^ Higher values cook stuff faster.
extra_nodedef_fields = { ... },
^ Stuff here is copied verbatim into both active and inactive nodedefs
^ Useful for overriding drawtype, etc.
}
]]
local function make_tiles(tiles, fmt, active)
if not fmt then return tiles end
tiles = { }
for i,side in ipairs{"top", "bottom", "side", "side", "side", "front"} do
if active and (i == 6) then
tiles[i] = fmt:format(side, "_active")
else
tiles[i] = fmt:format(side, "")
end
end
return tiles
end
local furnace_can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("fuel")
and inv:is_empty("dst")
and inv:is_empty("src")
end
function homedecor.register_furnace(name, furnacedef)
furnacedef.fire_fg = furnacedef.fire_bg or "default_furnace_fire_fg.png"
furnacedef.fire_bg = furnacedef.fire_bg or "default_furnace_fire_bg.png"
furnacedef.output_slots = furnacedef.output_slots or 4
furnacedef.output_width = furnacedef.output_width or 2
furnacedef.cook_speed = furnacedef.cook_speed or 1
local description = furnacedef.description or S("Furnace")
local furnace_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", make_formspec(furnacedef, 0))
meta:set_string("infotext", description)
local inv = meta:get_inventory()
inv:set_size("fuel", 1)
inv:set_size("src", 1)
inv:set_size("dst", furnacedef.output_slots)
end
local furnace_allow_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if listname == "fuel" then
if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext", S("@1 (empty)", description))
end
return stack:get_count()
else
return 0
end
elseif listname == "src" then
return stack:get_count()
elseif listname == "dst" then
return 0
end
end
local furnace_allow_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
if to_list == "fuel" then
if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext", S("@1 (empty)", description))
end
return count
else
return 0
end
elseif to_list == "src" then
return count
elseif to_list == "dst" then
return 0
end
end
local def = {
description = description,
tiles = make_tiles(furnacedef.tiles, furnacedef.tile_format, false),
groups = furnacedef.groups or {cracky=2},
sounds = furnacedef.sounds or default.node_sound_wood_defaults(),
on_construct = furnace_construct,
can_dig = furnace_can_dig,
allow_metadata_inventory_put = furnace_allow_put,
allow_metadata_inventory_move = furnace_allow_move,
inventory = { lockable = true }
}
local def_active = {
description = S("@1 (active)", description),
tiles = make_tiles(furnacedef.tiles_active, furnacedef.tile_format, true),
light_source = 8,
drop = "homedecor:" .. name,
groups = furnacedef.groups or {cracky=2, not_in_creative_inventory=1},
sounds = furnacedef.sounds or default.node_sound_stone_defaults(),
on_construct = furnace_construct,
can_dig = furnace_can_dig,
allow_metadata_inventory_put = furnace_allow_put,
allow_metadata_inventory_move = furnace_allow_move,
inventory = { lockable = true }
}
if furnacedef.extra_nodedef_fields then
for k, v in pairs(furnacedef.extra_nodedef_fields) do
def[k] = v
def_active[k] = v
end
end
local n_active = name.."_active"
homedecor.register(name, def)
homedecor.register(n_active, def_active)
local nname, name_active = "homedecor:"..name, "homedecor:"..n_active
minetest.register_abm({
nodenames = {nname, name_active, nname.."_locked", name_active.."_locked"},
label = "furnaces",
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos)
for i, pname in ipairs({
"fuel_totaltime",
"fuel_time",
"src_totaltime",
"src_time"
}) do
if meta:get_string(pname) == "" then
meta:set_float(pname, 0.0)
end
end
local inv = meta:get_inventory()
local srclist = inv:get_list("src")
local cooked = nil
local aftercooked
if srclist then
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
end
local was_active = false
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
was_active = true
meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
meta:set_float("src_time", meta:get_float("src_time") + furnacedef.cook_speed)
if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
-- check if there's room for output in "dst" list
if inv:room_for_item("dst",cooked.item) then
-- Put result in "dst" list
inv:add_item("dst", cooked.item)
-- take stuff from "src" list
inv:set_stack("src", 1, aftercooked.items[1])
end
meta:set_string("src_time", 0)
end
end
-- XXX: Quick patch, make it better in the future.
local locked = node.name:find("_locked$") and "_locked" or ""
local desc = minetest.registered_nodes[nname..locked].description
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
local percent = math.floor(meta:get_float("fuel_time") /
meta:get_float("fuel_totaltime") * 100)
meta:set_string("infotext", S("@1 (active: @2%)", desc, percent))
swap_node(pos,name_active..locked)
meta:set_string("formspec", make_formspec(furnacedef, percent))
return
end
local fuel = nil
local afterfuel
cooked = nil
local fuellist = inv:get_list("fuel")
srclist = inv:get_list("src")
if srclist then
cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
end
if fuellist then
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
end
if (not fuel) or (fuel.time <= 0) then
meta:set_string("infotext", S("@1 (out of fuel)", desc))
swap_node(pos, nname..locked)
meta:set_string("formspec", make_formspec(furnacedef, 0))
return
end
if cooked.item:is_empty() then
if was_active then
meta:set_string("infotext", S("@1 (empty)", desc))
swap_node(pos, nname..locked)
meta:set_string("formspec", make_formspec(furnacedef, 0))
end
return
end
if not inv:room_for_item("dst", cooked.item) then
meta:set_string("infotext", S("@1 (output bins are full)", desc))
swap_node(pos, nname..locked)
meta:set_string("formspec", make_formspec(furnacedef, 0))
return
end
meta:set_string("fuel_totaltime", fuel.time)
meta:set_string("fuel_time", 0)
inv:set_stack("fuel", 1, afterfuel.items[1])
end,
})
end

79
homedecor_common/init.lua Normal file
View File

@ -0,0 +1,79 @@
-- Home Decor API/functions, and common textures and models
-- by VanessaE
local modpath = minetest.get_modpath("homedecor_common")
local S = homedecor_i18n.gettext
homedecor = {}
homedecor.modpath = modpath
-- Determine if the item being pointed at is the underside of a node (e.g a ceiling)
function homedecor.find_ceiling(itemstack, placer, pointed_thing)
-- most of this is copied from the rotate-and-place function in builtin
local unode = core.get_node_or_nil(pointed_thing.under)
if not unode then
return
end
local undef = core.registered_nodes[unode.name]
if undef and undef.on_rightclick then
undef.on_rightclick(pointed_thing.under, unode, placer,
itemstack, pointed_thing)
return
end
local above = pointed_thing.above
local under = pointed_thing.under
local iswall = (above.y == under.y)
local isceiling = not iswall and (above.y < under.y)
local anode = core.get_node_or_nil(above)
if not anode then
return
end
local pos = pointed_thing.above
local node = anode
if undef and undef.buildable_to then
pos = pointed_thing.under
node = unode
end
if core.is_protected(pos, placer:get_player_name()) then
core.record_protection_violation(pos,
placer:get_player_name())
return
end
local ndef = core.registered_nodes[node.name]
if not ndef or not ndef.buildable_to then
return
end
return isceiling, pos
end
screwdriver = screwdriver or {}
homedecor.plain_wood = { name = "homedecor_generic_wood_plain.png", color = 0xffa76820 }
homedecor.mahogany_wood = { name = "homedecor_generic_wood_plain.png", color = 0xff7d2506 }
homedecor.white_wood = "homedecor_generic_wood_plain.png"
homedecor.dark_wood = { name = "homedecor_generic_wood_plain.png", color = 0xff39240f }
homedecor.lux_wood = { name = "homedecor_generic_wood_luxury.png", color = 0xff643f23 }
homedecor.color_black = 0xff303030
homedecor.color_dark_grey = 0xff606060
homedecor.color_med_grey = 0xffa0a0a0
-- load different handler subsystems
dofile(modpath.."/nodeboxes.lua")
dofile(modpath.."/expansion.lua")
dofile(modpath.."/furnaces.lua")
dofile(modpath.."/inventory.lua")
dofile(modpath.."/registration.lua")
dofile(modpath.."/water_particles.lua")
dofile(modpath.."/mt_game_beds_functions.lua")
dofile(modpath.."/sit.lua")
dofile(modpath.."/crafts.lua")
if minetest.settings:get_bool("log_mod") then
minetest.log("action", "[HomeDecor API] " .. S("Loaded!"))
end

View File

@ -0,0 +1,189 @@
local S = homedecor_i18n.gettext
local default_can_dig = function(pos,player)
local meta = minetest.get_meta(pos)
return meta:get_inventory():is_empty("main")
end
local background = default.gui_bg .. default.gui_bg_img .. default.gui_slots
local default_inventory_formspecs = {
["4"]="size[8,6]".. background ..
"list[context;main;2,0;4,1;]" ..
"list[current_player;main;0,2;8,4;]" ..
"listring[]",
["6"]="size[8,6]".. background ..
"list[context;main;1,0;6,1;]"..
"list[current_player;main;0,2;8,4;]" ..
"listring[]",
["8"]="size[8,6]".. background ..
"list[context;main;0,0;8,1;]"..
"list[current_player;main;0,2;8,4;]" ..
"listring[]",
["12"]="size[8,7]".. background ..
"list[context;main;1,0;6,2;]"..
"list[current_player;main;0,3;8,4;]" ..
"listring[]",
["16"]="size[8,7]".. background ..
"list[context;main;0,0;8,2;]"..
"list[current_player;main;0,3;8,4;]" ..
"listring[]",
["24"]="size[8,8]".. background ..
"list[context;main;0,0;8,3;]"..
"list[current_player;main;0,4;8,4;]" ..
"listring[]",
["32"]="size[8,9]".. background ..
"list[context;main;0,0.3;8,4;]"..
"list[current_player;main;0,4.85;8,1;]"..
"list[current_player;main;0,6.08;8,3;8]"..
"listring[context;main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85),
["50"]="size[10,10]".. background ..
"list[context;main;0,0;10,5;]"..
"list[current_player;main;1,6;8,4;]" ..
"listring[]",
}
local function get_formspec_by_size(size)
--TODO heuristic to use the "next best size"
local formspec = default_inventory_formspecs[tostring(size)]
return formspec or default_inventory_formspecs
end
----
-- handle inventory setting
-- inventory = {
-- size = 16,
-- formspec = …,
-- locked = false,
-- lockable = true,
-- }
--
function homedecor.handle_inventory(name, def, original_def)
local inventory = def.inventory
if not inventory then return end
def.inventory = nil
if inventory.size then
local on_construct = def.on_construct
def.on_construct = function(pos)
local size = inventory.size
local meta = minetest.get_meta(pos)
meta:get_inventory():set_size("main", size)
meta:set_string("formspec", inventory.formspec or get_formspec_by_size(size))
if on_construct then on_construct(pos) end
end
end
def.can_dig = def.can_dig or default_can_dig
def.on_metadata_inventory_move = def.on_metadata_inventory_move or function(pos, from_list, from_index, to_list, to_index, count, player)
minetest.log("action", S("@1 moves stuff in @2 at @3",
player:get_player_name(), name, minetest.pos_to_string(pos)
))
end
def.on_metadata_inventory_put = def.on_metadata_inventory_put or function(pos, listname, index, stack, player)
minetest.log("action", S("@1 moves @2 to @3 at @4",
player:get_player_name(), stack:get_name(), name, minetest.pos_to_string(pos)
))
end
def.on_metadata_inventory_take = def.on_metadata_inventory_take or function(pos, listname, index, stack, player)
minetest.log("action", S("@1 takes @2 from @3 at @4",
player:get_player_name(), stack:get_name(), name, minetest.pos_to_string(pos)
))
end
local locked = inventory.locked
if locked then
local after_place_node = def.after_place_node
def.after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local owner = placer:get_player_name() or ""
meta:set_string("owner", owner)
meta:set_string("infotext", S("@1 (owned by @2)", def.infotext or def.description, owner))
return after_place_node and after_place_node(pos, placer)
end
local allow_move = def.allow_metadata_inventory_move
def.allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
local playername = player:get_player_name()
if playername == owner or
minetest.check_player_privs(playername, "protection_bypass") then
return allow_move and
allow_move(pos, from_list, from_index, to_list, to_index, count, player) or
count
end
minetest.log("action", S("@1 tried to access a @2 belonging to @3 at @4",
playername, name, owner, minetest.pos_to_string(pos)
))
return 0
end
local allow_put = def.allow_metadata_inventory_put
def.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
local playername = player:get_player_name()
if playername == owner or
minetest.check_player_privs(playername, "protection_bypass") then
return allow_put and allow_put(pos, listname, index, stack, player) or
stack:get_count()
end
minetest.log("action", S("@1 tried to access a @2 belonging to @3 at @4",
playername, name, owner, minetest.pos_to_string(pos)
))
return 0
end
local allow_take = def.allow_metadata_inventory_take
def.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
local playername = player:get_player_name()
if playername == owner or
minetest.check_player_privs(playername, "protection_bypass") then
return allow_take and allow_take(pos, listname, index, stack, player) or
stack:get_count()
end
minetest.log("action", S("@1 tried to access a @2 belonging to @3 at @4",
playername, name, owner, minetest.pos_to_string(pos)
))
return 0
end
end
local lockable = inventory.lockable
if lockable then
local locked_def = table.copy(original_def)
locked_def.description = S("@1 (Locked)", def.description or name)
local locked_inventory = locked_def.inventory
locked_inventory.locked = true
locked_inventory.lockable = nil -- avoid loops of locked locked stuff
local locked_name = name .. "_locked"
homedecor.register(locked_name, locked_def)
minetest.register_craft({
type = "shapeless",
output = "homedecor:" .. locked_name,
recipe = { "homedecor:" .. name, "basic_materials:padlock" }
})
end
end

View File

@ -0,0 +1,23 @@
# Blender v2.73 (sub 0) OBJ File: 'cobe+1.001.blend'
# www.blender.org
o Cylinder
v -0.499500 -0.499500 0.499500
v -0.499500 -0.499500 -0.499500
v 0.499500 -0.499500 -0.499500
v 0.499500 -0.499500 0.499500
v -0.499500 0.499500 0.499500
v -0.499500 0.499500 -0.499500
v 0.499500 0.499500 -0.499500
v 0.499500 0.499500 0.499500
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
g Cylinder_Cylinder_None
s off
f 5/1 6/2 2/3 1/4
f 6/1 7/2 3/3 2/4
f 7/1 8/2 4/3 3/4
f 8/1 5/2 1/3 4/4
f 1/1 2/2 3/3 4/4
f 8/1 7/2 6/3 5/4

View File

@ -0,0 +1,26 @@
# Blender v2.73 (sub 0) OBJ File: 'slope_test_slope_onetexture.blend'
# www.blender.org
o Cube_Cube.002
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 0.500000
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vn 0.000000 -0.000000 1.000000
vn 0.000000 -1.000000 -0.000000
vn 0.000000 0.707100 -0.707100
vn -1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
g Cube_Cube.002_Cube_Cube.002_front-back-bottom
s off
f 1/1/1 2/2/1 3/3/1 4/4/1
f 4/3/2 3/4/2 5/1/2 6/2/2
f 2/1/3 1/2/3 6/3/3 5/4/3
g Cube_Cube.002_Cube_Cube.002_sides
f 2/1/4 5/3/4 3/4/4
f 1/2/5 4/3/5 6/4/5

View File

@ -0,0 +1,34 @@
# Blender v2.73 (sub 0) OBJ File: 'slope_test_icorner_onetexture.blend'
# www.blender.org
o Cube_Cube.000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 0.500000
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vn 1.000000 -0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 0.707100 -0.707100
vn 0.000000 -0.000000 -1.000000
vn -0.000000 -1.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn -0.707100 0.707100 -0.000000
g Cube_Cube.000_Cube_Cube.000_None
s off
f 6/1/1 1/2/1 7/3/1 8/4/1
f 2/1/2 5/3/2 3/4/2
f 2/1/3 1/2/3 5/4/3
f 6/2/4 8/3/4 9/4/4
f 9/1/5 8/2/5 7/3/5 3/4/5
f 3/3/6 7/4/6 1/1/6 2/2/6
f 1/1/7 6/2/7 9/3/7
l 1 4
l 3 4

View File

@ -0,0 +1,24 @@
# Blender v2.73 (sub 0) OBJ File: 'slope_test_ocorner_onetexture.blend'
# www.blender.org
o Cube_Cube.002
v 0.500000 0.500000 0.500000
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vn 0.000000 -1.000000 -0.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 -0.000000 1.000000
vn -0.707100 0.707100 0.000000
vn 0.000000 0.707100 -0.707100
g Cube_Cube.002_Cube_Cube.002_None
s off
f 3/1/1 2/2/1 4/3/1 5/4/1
f 1/2/2 3/3/2 5/4/2
f 1/1/3 2/3/3 3/4/3
f 1/1/4 4/3/4 2/4/4
f 1/2/5 5/3/5 4/4/5

View File

@ -0,0 +1,175 @@
-- This file is a partial copy of functions.lua from minetest_game's beds mod
-- with changes needed for homedecor's beds.
local pi = math.pi
local is_sp = minetest.is_singleplayer()
local enable_respawn = minetest.settings:get_bool("enable_bed_respawn")
if enable_respawn == nil then
enable_respawn = true
end
-- Helper functions
local function get_look_yaw(pos)
local n = minetest.get_node(pos)
local fdir = n.param2 % 4
if fdir == 0 then
return pi / 2, fdir
elseif fdir == 1 then
return -pi / 2, fdir
elseif fdir == 3 then
return pi, fdir
else
return 0, fdir
end
end
local function is_night_skip_enabled()
local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip")
if enable_night_skip == nil then
enable_night_skip = true
end
return enable_night_skip
end
local function check_in_beds(players)
local in_bed = beds.player
if not players then
players = minetest.get_connected_players()
end
for n, player in ipairs(players) do
local name = player:get_player_name()
if not in_bed[name] then
return false
end
end
return #players > 0
end
local function get_player_in_bed()
local player_in_bed = 0
for k,v in pairs(beds.player) do
player_in_bed = player_in_bed + 1
end
return player_in_bed
end
local function lay_down(player, pos, bed_pos, state, skip)
local name = player:get_player_name()
local hud_flags = player:hud_get_flags()
if not player or not name then
return
end
-- stand up
if state ~= nil and not state then
local p = beds.pos[name] or nil
if beds.player[name] ~= nil then
beds.player[name] = nil
end
-- skip here to prevent sending player specific changes (used for leaving players)
if skip then
return
end
if p then
player:setpos(p)
end
-- physics, eye_offset, etc
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
player:set_look_horizontal(math.random(1, 180) / 100)
default.player_attached[name] = false
player:set_physics_override(1, 1, 1)
hud_flags.wielditem = true
default.player_set_animation(player, "stand" , 30)
-- lay down
else
beds.player[name] = 1
beds.pos[name] = pos
-- physics, eye_offset, etc
player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0})
local yaw, fdir = get_look_yaw(bed_pos)
player:set_look_horizontal(yaw)
local offsets = {
[0] = {0.5, 0},
[1] = {-0.5, 0},
[2] = {0, -0.5},
[3] = {0, 0.5}
}
local p = {x = bed_pos.x + offsets[fdir][1], y = bed_pos.y, z = bed_pos.z + offsets[fdir][2]}
player:set_physics_override(0, 0, 0)
player:setpos(p)
default.player_attached[name] = true
hud_flags.wielditem = false
default.player_set_animation(player, "lay" , 0)
end
player:hud_set_flags(hud_flags)
end
local function update_formspecs(finished)
local ges = #minetest.get_connected_players()
local player_in_bed = get_player_in_bed()
local form_n
local is_majority = (ges / 2) < player_in_bed
if finished then
form_n = beds.formspec .. "label[2.7,11; Good morning.]"
else
form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) ..
" of " .. tostring(ges) .. " players are in bed]"
if is_majority and is_night_skip_enabled() then
form_n = form_n .. "button_exit[2,8;4,0.75;force;Force night skip]"
end
end
for name,_ in pairs(beds.player) do
minetest.show_formspec(name, "beds_form", form_n)
end
end
-- Public functions
function homedecor.beds_on_rightclick(pos, node, player)
local name = player:get_player_name()
local ppos = player:getpos()
local tod = minetest.get_timeofday()
if tod > 0.2 and tod < 0.805 then
if beds.player[name] then
lay_down(player, nil, nil, false)
end
minetest.chat_send_player(name, "You can only sleep at night.")
return
end
-- move to bed
if not beds.player[name] then
lay_down(player, ppos, pos)
beds.set_spawns() -- save respawn positions when entering bed
else
lay_down(player, nil, nil, false)
end
if not is_sp then
update_formspecs(false)
end
-- skip the night and let all players stand up
if check_in_beds() then
minetest.after(2, function()
if not is_sp then
update_formspecs(is_night_skip_enabled())
end
if is_night_skip_enabled() then
beds.skip_night()
beds.kick_players()
end
end)
end
end

View File

@ -0,0 +1,59 @@
-- please keep any non-generic nodeboxe with its node definition
-- this file should not accumulate any left over nodeboxes
-- but is meant to host any abstractions or calculations based on nodeboxes
-- a box is defined as {x1, y1, z1, x2, y2, z2}
homedecor.box = {
-- slab starting from -x (after rotation: left)
slab_x = function(depth) return { -0.5, -0.5, -0.5, -0.5+depth, 0.5, 0.5 } end,
-- bottom slab (starting from -y) with height optionally shifted upwards
slab_y = function(height, shift) return { -0.5, -0.5+(shift or 0), -0.5, 0.5, -0.5+height+(shift or 0), 0.5 } end,
-- slab starting from -z (+z with negative depth)
slab_z = function(depth)
-- for consistency with the other functions here, we have to assume that a "z" slab starts from -z and extends by depth,
-- but since conventionally a lot of nodes place slabs against +z for player convenience, we define
-- a "negative" depth as a depth extending from the other side, i.e. +z
if depth > 0 then
-- slab starting from -z
return { -0.5, -0.5, -0.5, 0.5, 0.5, -0.5+depth }
else
-- slab starting from +z (z1=0.5-(-depth))
return { -0.5, -0.5, 0.5+depth, 0.5, 0.5, 0.5 }
end
end,
bar_y = function(radius) return {-radius, -0.5, -radius, radius, 0.5, radius} end,
cuboid = function(radius_x, radius_y, radius_z) return {-radius_x, -radius_y, -radius_z, radius_x, radius_y, radius_z} end,
}
homedecor.nodebox = {
-- { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
-- can be used in-place as:
-- { type="regular" },
regular = { type="regular" },
null = { type = "fixed", fixed = { 0, 0, 0, 0, 0, 0 } },
corner_xz = function(depth_x, depth_z) return {
type="fixed",
fixed={
homedecor.box.slab_x(depth_x),
homedecor.box.slab_z(depth_z),
-- { -0.5, -0.5, -0.5, 0.5-depth, 0.5, -0.5+depth } -- slab_x without the overlap, but actually looks a bit worse
}
} end,
}
local mt = {}
mt.__index = function(table, key)
local ref = homedecor.box[key]
local ref_type = type(ref)
if ref_type == "function" then
return function(...)
return { type = "fixed", fixed = ref(...) }
end
elseif ref_type == "table" then
return { type = "fixed", fixed = ref }
elseif ref_type == "nil" then
error(key .. "could not be found among nodebox presets and functions")
end
error("unexpected datatype " .. tostring(type(ref)) .. " while looking for " .. key)
end
setmetatable(homedecor.nodebox, mt)

View File

@ -0,0 +1,95 @@
homedecor = homedecor or {}
local placeholder_node = "homedecor:expansion_placeholder"
--wrapper around minetest.register_node that sets sane defaults and interprets some specialized settings
function homedecor.register(name, original_def)
local def = table.copy(original_def)
def.drawtype = def.drawtype
or (def.mesh and "mesh")
or (def.node_box and "nodebox")
def.paramtype = def.paramtype or "light"
-- avoid facedir for some drawtypes as they might be used internally for something else
-- even if undocumented
if not (def.drawtype == "glasslike_framed"
or def.drawtype == "raillike"
or def.drawtype == "plantlike"
or def.drawtype == "firelike") then
def.paramtype2 = def.paramtype2 or "facedir"
end
homedecor.handle_inventory(name, def, original_def)
local infotext = def.infotext
--def.infotext = nil -- currently used to set locked refrigerator infotexts
if infotext then
local on_construct = def.on_construct
def.on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", infotext)
if on_construct then on_construct(pos) end
end
end
local expand = def.expand
def.expand = nil
local after_unexpand = def.after_unexpand
def.after_unexpand = nil
if expand then
-- dissallow rotating only half the expanded node by default
-- unless we know better
def.on_rotate = def.on_rotate
or (def.mesh and expand.top and screwdriver.rotate_simple)
or screwdriver.disallow
def.on_place = def.on_place or function(itemstack, placer, pointed_thing)
if expand.top then
return homedecor.stack_vertically(itemstack, placer, pointed_thing, itemstack:get_name(), expand.top)
elseif expand.right then
return homedecor.stack_sideways(itemstack, placer, pointed_thing, itemstack:get_name(), expand.right, true)
elseif expand.forward then
return homedecor.stack_sideways(itemstack, placer, pointed_thing, itemstack:get_name(), expand.forward, false)
end
end
def.after_dig_node = def.after_dig_node or function(pos, oldnode, oldmetadata, digger)
if expand.top and expand.forward ~= "air" then
local top_pos = { x=pos.x, y=pos.y+1, z=pos.z }
local node = minetest.get_node(top_pos).name
if node == expand.top or node == placeholder_node then
minetest.remove_node(top_pos)
end
end
local fdir = oldnode.param2
if not fdir or fdir > 3 then return end
if expand.right and expand.forward ~= "air" then
local right_pos = { x=pos.x+homedecor.fdir_to_right[fdir+1][1], y=pos.y, z=pos.z+homedecor.fdir_to_right[fdir+1][2] }
local node = minetest.get_node(right_pos).name
if node == expand.right or node == placeholder_node then
minetest.remove_node(right_pos)
end
end
if expand.forward and expand.forward ~= "air" then
local forward_pos = { x=pos.x+homedecor.fdir_to_fwd[fdir+1][1], y=pos.y, z=pos.z+homedecor.fdir_to_fwd[fdir+1][2] }
local node = minetest.get_node(forward_pos).name
if node == expand.forward or node == placeholder_node then
minetest.remove_node(forward_pos)
end
end
if after_unexpand then
after_unexpand(pos)
end
end
end
-- register the actual minetest node
minetest.register_node(":homedecor:" .. name, def)
end

34
homedecor_common/sit.lua Normal file
View File

@ -0,0 +1,34 @@
function homedecor.sit(pos, node, clicker)
return -- delete it when the engine is stabler for the player's physics
--[[
local meta = minetest.get_meta(pos)
local param2 = node.param2
local name = clicker:get_player_name()
if name == meta:get_string("is_sit") then
meta:set_string("is_sit", "")
pos.y = pos.y-0.5
clicker:setpos(pos)
clicker:set_eye_offset({x=0,y=0,z=0}, {x=0,y=0,z=0})
clicker:set_physics_override(1, 1, 1)
default.player_attached[name] = false
default.player_set_animation(clicker, "stand", 30)
else
meta:set_string("is_sit", clicker:get_player_name())
clicker:set_eye_offset({x=0,y=-7,z=2}, {x=0,y=0,z=0})
clicker:set_physics_override(0, 0, 0)
clicker:setpos(pos)
default.player_attached[name] = true
default.player_set_animation(clicker, "sit", 30)
if param2 == 0 then
clicker:set_look_yaw(3.15)
elseif param2 == 1 then
clicker:set_look_yaw(7.9)
elseif param2 == 2 then
clicker:set_look_yaw(6.28)
elseif param2 == 3 then
clicker:set_look_yaw(4.75)
else return end
end
--]]
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

View File

@ -0,0 +1,115 @@
-- variables taken by the start... function
--
-- pos and node are as usual, from e.g. on_rightclick.
--
-- in the { particledef } table:
--
-- outletx/y/z are the exact coords of the starting point
-- for the spawner, relative to the center of the node
--
-- velocityx/y/z are the speed of the particles,
-- (x and z are relative to a node placed while looking north/facedir 0)
-- negative Y values flow downward.
--
-- spread is the radius from the starting point,
-- along X and Z only, to randomly spawn particles.
--
-- soundname is the filename (without .ogg) of the sound file
-- to be played along with the particle stream
function homedecor.start_particle_spawner(pos, node, particledef, soundname)
local this_spawner_meta = minetest.get_meta(pos)
local id = this_spawner_meta:get_int("active")
local s_handle = this_spawner_meta:get_int("sound")
if id ~= 0 then
if s_handle then
minetest.after(0, function(handle)
minetest.sound_stop(handle)
end, s_handle)
end
minetest.delete_particlespawner(id)
this_spawner_meta:set_int("active", 0)
this_spawner_meta:set_int("sound", 0)
return
end
local fdir = node.param2
if fdir and fdir < 4 and (not id or id == 0) then
local outletx = particledef.outlet.x
local outlety = particledef.outlet.y
local outletz = particledef.outlet.z
local velocityx = particledef.velocity_x
local velocityy = particledef.velocity_y
local velocityz = particledef.velocity_z
local spread = particledef.spread
local minx_t = { outletx - spread, -outletz - spread, outletx - spread, outletz - spread }
local maxx_t = { outletx + spread, -outletz + spread, outletx + spread, outletz + spread }
local minz_t = { -outletz - spread, outletx - spread, outletz - spread, outletx - spread }
local maxz_t = { -outletz + spread, outletx + spread, outletz + spread, outletx + spread }
local minvelx_t = { velocityx.min, velocityz.min, -velocityx.max, -velocityz.max }
local maxvelx_t = { velocityx.max, velocityz.max, -velocityx.min, -velocityz.min }
local minvelz_t = { velocityz.min, velocityx.min, -velocityz.max, velocityx.min }
local maxvelz_t = { velocityz.max, velocityx.max, -velocityz.min, velocityx.max }
local minx = minx_t[fdir + 1]
local maxx = maxx_t[fdir + 1]
local minz = minz_t[fdir + 1]
local maxz = maxz_t[fdir + 1]
local minvelx = minvelx_t[fdir + 1]
local minvelz = minvelz_t[fdir + 1]
local maxvelx = maxvelx_t[fdir + 1]
local maxvelz = maxvelz_t[fdir + 1]
id = minetest.add_particlespawner({
amount = 60,
time = 0,
collisiondetection = true,
collision_removal = particledef.die_on_collision,
minpos = {x=pos.x - minx, y=pos.y + outlety, z=pos.z - minz},
maxpos = {x=pos.x - maxx, y=pos.y + outlety, z=pos.z - maxz},
minvel = {x = minvelx, y = velocityy, z = minvelz},
maxvel = {x = maxvelx, y = velocityy, z = maxvelz},
minacc = {x=0, y=0, z=0},
maxacc = {x=0, y=-0.05, z=0},
minexptime = 2,
maxexptime = 4,
minsize = 0.5,
maxsize = 1,
texture = "homedecor_water_particle.png",
})
s_handle = minetest.sound_play(soundname, {
pos = pos,
max_hear_distance = 5,
loop = true
})
this_spawner_meta:set_int("active", id)
this_spawner_meta:set_int("sound", s_handle)
return
end
end
function homedecor.stop_particle_spawner(pos)
local this_spawner_meta = minetest.get_meta(pos)
local id = this_spawner_meta:get_int("active")
local s_handle = this_spawner_meta:get_int("sound")
if id ~= 0 then
minetest.delete_particlespawner(id)
end
if s_handle then
minetest.after(0, function(handle)
minetest.sound_stop(handle)
end, s_handle)
end
this_spawner_meta:set_int("active", 0)
this_spawner_meta:set_int("sound", 0)
end