]> git.lizzy.rs Git - xdecor.git/commitdiff
Remove the crafting guide and minor file reorganizing
authorJP Guerrero <jeanpatrick.guerrero@gmail.com>
Wed, 30 Nov 2016 14:54:05 +0000 (15:54 +0100)
committerJP Guerrero <jeanpatrick.guerrero@gmail.com>
Wed, 30 Nov 2016 14:54:05 +0000 (15:54 +0100)
27 files changed:
chess.lua [deleted file]
cooking.lua [deleted file]
craftguide.lua [deleted file]
craftitems.lua [deleted file]
enchanting.lua [deleted file]
hive.lua [deleted file]
init.lua
itemframe.lua [deleted file]
mailbox.lua [deleted file]
mechanisms.lua [deleted file]
nodes.lua [deleted file]
recipes.lua [deleted file]
rope.lua [deleted file]
src/chess.lua [new file with mode: 0644]
src/cooking.lua [new file with mode: 0644]
src/craftitems.lua [new file with mode: 0644]
src/enchanting.lua [new file with mode: 0644]
src/hive.lua [new file with mode: 0644]
src/itemframe.lua [new file with mode: 0644]
src/mailbox.lua [new file with mode: 0644]
src/mechanisms.lua [new file with mode: 0644]
src/nodes.lua [new file with mode: 0644]
src/recipes.lua [new file with mode: 0644]
src/rope.lua [new file with mode: 0644]
src/workbench.lua [new file with mode: 0644]
textures/xdecor_crafting_guide.png [deleted file]
workbench.lua [deleted file]

diff --git a/chess.lua b/chess.lua
deleted file mode 100644 (file)
index 6de09cc..0000000
--- a/chess.lua
+++ /dev/null
@@ -1,628 +0,0 @@
-local realchess = {}
-screwdriver = screwdriver or {}
-
-local function index_to_xy(idx)
-       idx = idx - 1
-       local x = idx % 8
-       local y = (idx - x) / 8
-       return x, y
-end
-
-local function xy_to_index(x, y)
-       return x + y * 8 + 1
-end
-
-function realchess.init(pos)
-       local meta = minetest.get_meta(pos)
-       local inv = meta:get_inventory()
-       
-       local formspec = [[ size[8,8.6;]
-                       bgcolor[#080808BB;true]
-                       background[0,0;8,8;chess_bg.png]
-                       button[3.1,7.8;2,2;new;New game]
-                       list[context;board;0,0;8,8;]
-                       listcolors[#00000000;#00000000;#00000000;#30434C;#FFF] ]]
-
-       meta:set_string("formspec", formspec)
-       meta:set_string("infotext", "Chess Board")
-       meta:set_string("playerBlack", "")
-       meta:set_string("playerWhite", "")
-       meta:set_string("lastMove", "")
-       meta:set_string("winner", "")
-
-       meta:set_int("lastMoveTime", 0)
-       meta:set_int("castlingBlackL", 1)
-       meta:set_int("castlingBlackR", 1)
-       meta:set_int("castlingWhiteL", 1)
-       meta:set_int("castlingWhiteR", 1)
-
-       inv:set_list("board", {
-               "realchess:rook_black_1",
-               "realchess:knight_black_1",
-               "realchess:bishop_black_1",
-               "realchess:queen_black",
-               "realchess:king_black",
-               "realchess:bishop_black_2",
-               "realchess:knight_black_2",
-               "realchess:rook_black_2",
-               "realchess:pawn_black_1",
-               "realchess:pawn_black_2",
-               "realchess:pawn_black_3",
-               "realchess:pawn_black_4",
-               "realchess:pawn_black_5",
-               "realchess:pawn_black_6",
-               "realchess:pawn_black_7",
-               "realchess:pawn_black_8",
-               '','','','','','','','','','','','','','','','',
-               '','','','','','','','','','','','','','','','',
-               "realchess:pawn_white_1",
-               "realchess:pawn_white_2",
-               "realchess:pawn_white_3",
-               "realchess:pawn_white_4",
-               "realchess:pawn_white_5",
-               "realchess:pawn_white_6",
-               "realchess:pawn_white_7",
-               "realchess:pawn_white_8",
-               "realchess:rook_white_1",
-               "realchess:knight_white_1",
-               "realchess:bishop_white_1",
-               "realchess:queen_white",
-               "realchess:king_white",
-               "realchess:bishop_white_2",
-               "realchess:knight_white_2",
-               "realchess:rook_white_2"
-       })
-
-       inv:set_size("board", 64)
-end
-
-function realchess.move(pos, from_list, from_index, to_list, to_index, _, player)
-       if from_list ~= "board" and to_list ~= "board" then
-               return 0
-       end
-
-       local playerName = player:get_player_name()
-       local meta = minetest.get_meta(pos)
-
-       if meta:get_string("winner") ~= "" then
-               minetest.chat_send_player(playerName, "This game is over.")
-               return 0
-       end
-
-       local inv = meta:get_inventory()
-       local pieceFrom = inv:get_stack(from_list, from_index):get_name()
-       local pieceTo = inv:get_stack(to_list, to_index):get_name()
-       local lastMove = meta:get_string("lastMove")
-       local thisMove -- will replace lastMove when move is legal
-       local playerWhite = meta:get_string("playerWhite")
-       local playerBlack = meta:get_string("playerBlack")
-
-       if pieceFrom:find("white") then
-               if playerWhite ~= "" and playerWhite ~= playerName then
-                       minetest.chat_send_player(playerName, "Someone else plays white pieces!")
-                       return 0
-               end             
-               if lastMove ~= "" and lastMove ~= "black" then
-                       minetest.chat_send_player(playerName, "It's not your turn, wait for your opponent to play.")
-                       return 0
-               end
-               if pieceTo:find("white") then
-                       -- Don't replace pieces of same color
-                       return 0
-               end
-               playerWhite = playerName
-               thisMove = "white"
-       elseif pieceFrom:find("black") then
-               if playerBlack ~= "" and playerBlack ~= playerName then
-                       minetest.chat_send_player(playerName, "Someone else plays black pieces!")
-                       return 0
-               end
-               if lastMove ~= "" and lastMove ~= "white" then
-                       minetest.chat_send_player(playerName, "It's not your turn, wait for your opponent to play.")
-                       return 0
-               end
-               if pieceTo:find("black") then
-                       -- Don't replace pieces of same color
-                       return 0
-               end
-               playerBlack = playerName
-               thisMove = "black"
-       end
-
-       -- DETERMINISTIC MOVING
-
-       local from_x, from_y = index_to_xy(from_index)
-       local to_x, to_y = index_to_xy(to_index)
-
-       if pieceFrom:sub(11,14) == "pawn" then
-               if thisMove == "white" then
-                       local pawnWhiteMove = inv:get_stack(from_list, xy_to_index(from_x, from_y - 1)):get_name()
-                       -- white pawns can go up only
-                       if from_y - 1 == to_y then
-                               if from_x == to_x then
-                                       if pieceTo ~= "" then
-                                               return 0
-                                       elseif to_index >= 1 and to_index <= 8 then
-                                               inv:set_stack(from_list, from_index, "realchess:queen_white")
-                                       end
-                               elseif from_x - 1 == to_x or from_x + 1 == to_x then
-                                       if not pieceTo:find("black") then
-                                               return 0
-                                       elseif to_index >= 1 and to_index <= 8 then
-                                               inv:set_stack(from_list, from_index, "realchess:queen_white")
-                                       end
-                               else
-                                       return 0
-                               end
-                       elseif from_y - 2 == to_y then
-                               if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then
-                                       return 0
-                               end
-                       else
-                               return 0
-                       end
-               elseif thisMove == "black" then
-                       local pawnBlackMove = inv:get_stack(from_list, xy_to_index(from_x, from_y + 1)):get_name()
-                       -- black pawns can go down only
-                       if from_y + 1 == to_y then
-                               if from_x == to_x then
-                                       if pieceTo ~= "" then
-                                               return 0
-                                       elseif to_index >= 57 and to_index <= 64 then
-                                               inv:set_stack(from_list, from_index, "realchess:queen_black")
-                                       end
-                               elseif from_x - 1 == to_x or from_x + 1 == to_x then
-                                       if not pieceTo:find("white") then
-                                               return 0
-                                       elseif to_index >= 57 and to_index <= 64 then
-                                               inv:set_stack(from_list, from_index, "realchess:queen_black")
-                                       end
-                               else
-                                       return 0
-                               end
-                       elseif from_y + 2 == to_y then
-                               if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then
-                                       return 0
-                               end
-                       else
-                               return 0
-                       end
-
-                       -- if x not changed,
-                       --   ensure that destination cell is empty
-                       -- elseif x changed one unit left or right
-                       --   ensure the pawn is killing opponent piece
-                       -- else
-                       --   move is not legal - abort
-
-                       if from_x == to_x then
-                               if pieceTo ~= "" then
-                                       return 0
-                               end
-                       elseif from_x - 1 == to_x or from_x + 1 == to_x then
-                               if not pieceTo:find("white") then
-                                       return 0
-                               end
-                       else
-                               return 0
-                       end
-               else
-                       return 0
-               end
-
-       elseif pieceFrom:sub(11,14) == "rook" then
-               if from_x == to_x then
-                       -- moving vertically
-                       if from_y < to_y then
-                               -- moving down
-                               -- ensure that no piece disturbs the way
-                               for i = from_y + 1, to_y - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- mocing up
-                               -- ensure that no piece disturbs the way
-                               for i = to_y + 1, from_y - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end
-               elseif from_y == to_y then
-                       -- mocing horizontally
-                       if from_x < to_x then
-                               -- mocing right
-                               -- ensure that no piece disturbs the way
-                               for i = from_x + 1, to_x - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- mocing left
-                               -- ensure that no piece disturbs the way
-                               for i = to_x + 1, from_x - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end
-               else
-                       -- attempt to move arbitrarily -> abort
-                       return 0
-               end
-
-               if thisMove == "white" or thisMove == "black" then
-                       if pieceFrom:sub(-1) == "1" then
-                               meta:set_int("castlingWhiteL", 0)
-                       elseif pieceFrom:sub(-1) == "2" then
-                               meta:set_int("castlingWhiteR", 0)
-                       end
-               end
-
-       elseif pieceFrom:sub(11,16) == "knight" then
-               -- get relative pos
-               local dx = from_x - to_x
-               local dy = from_y - to_y
-
-               -- get absolute values
-               if dx < 0 then dx = -dx end
-               if dy < 0 then dy = -dy end
-
-               -- sort x and y
-               if dx > dy then dx, dy = dy, dx end
-
-               -- ensure that dx == 1 and dy == 2
-               if dx ~= 1 or dy ~= 2 then
-                       return 0
-               end
-               -- just ensure that destination cell does not contain friend piece
-               -- ^ it was done already thus everything ok
-
-       elseif pieceFrom:sub(11,16) == "bishop" then
-               -- get relative pos
-               local dx = from_x - to_x
-               local dy = from_y - to_y
-
-               -- get absolute values
-               if dx < 0 then dx = -dx end
-               if dy < 0 then dy = -dy end
-
-               -- ensure dx and dy are equal
-               if dx ~= dy then return 0 end
-
-               if from_x < to_x then
-                       if from_y < to_y then
-                               -- moving right-down
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y + i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- moving right-up
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y - i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end
-               else
-                       if from_y < to_y then
-                               -- moving left-down
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y + i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- moving left-up
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y - i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end
-               end
-
-       elseif pieceFrom:sub(11,15) == "queen" then
-               local dx = from_x - to_x
-               local dy = from_y - to_y
-
-               -- get absolute values
-               if dx < 0 then dx = -dx end
-               if dy < 0 then dy = -dy end
-
-               -- ensure valid relative move
-               if dx ~= 0 and dy ~= 0 and dx ~= dy then
-                       return 0
-               end
-
-               if from_x == to_x then
-                       if from_y < to_y then
-                               -- goes down
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x, from_y + i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- goes up
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x, from_y - i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end             
-               elseif from_x < to_x then
-                       if from_y == to_y then
-                               -- goes right
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       elseif from_y < to_y then
-                               -- goes right-down
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y + i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- goes right-up
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y - i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end                             
-               else
-                       if from_y == to_y then
-                               -- goes left
-                               -- ensure that no piece disturbs the way and destination cell does
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       elseif from_y < to_y then
-                               -- goes left-down
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y + i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       else
-                               -- goes left-up
-                               -- ensure that no piece disturbs the way
-                               for i = 1, dx - 1 do
-                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y - i)):get_name() ~= "" then
-                                               return 0
-                                       end
-                               end
-                       end             
-               end
-
-       elseif pieceFrom:sub(11,14) == "king" then
-               local dx = from_x - to_x
-               local dy = from_y - to_y
-               local check = true
-               
-               if thisMove == "white" then
-                       if from_y == 7 and to_y == 7 then
-                               if to_x == 1 then
-                                       local castlingWhiteL = meta:get_int("castlingWhiteL")
-                                       local idx57 = inv:get_stack(from_list, 57):get_name()
-
-                                       if castlingWhiteL == 1 and idx57 == "realchess:rook_white_1" then
-                                               for i = 58, from_index - 1 do
-                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
-                                                               return 0
-                                                       end
-                                               end
-                                               inv:set_stack(from_list, 57, "")
-                                               inv:set_stack(from_list, 59, "realchess:rook_white_1")
-                                               check = false
-                                       end
-                               elseif to_x == 6 then
-                                       local castlingWhiteR = meta:get_int("castlingWhiteR")
-                                       local idx64 = inv:get_stack(from_list, 64):get_name()
-
-                                       if castlingWhiteR == 1 and idx64 == "realchess:rook_white_2" then
-                                               for i = from_index + 1, 63 do
-                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
-                                                               return 0
-                                                       end
-                                               end
-                                               inv:set_stack(from_list, 62, "realchess:rook_white_2")
-                                               inv:set_stack(from_list, 64, "")
-                                               check = false
-                                       end
-                               end
-                       end
-               elseif thisMove == "black" then
-                       if from_y == 0 and to_y == 0 then
-                               if to_x == 1 then
-                                       local castlingBlackL = meta:get_int("castlingBlackL")
-                                       local idx1 = inv:get_stack(from_list, 1):get_name()
-
-                                       if castlingBlackL == 1 and idx1 == "realchess:rook_black_1" then
-                                               for i = 2, from_index - 1 do
-                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
-                                                               return 0
-                                                       end
-                                               end
-                                               inv:set_stack(from_list, 1, "")
-                                               inv:set_stack(from_list, 3, "realchess:rook_black_1")
-                                               check = false
-                                       end
-                               elseif to_x == 6 then
-                                       local castlingBlackR = meta:get_int("castlingBlackR")
-                                       local idx8 = inv:get_stack(from_list, 1):get_name()
-
-                                       if castlingBlackR == 1 and idx8 == "realchess:rook_black_2" then
-                                               for i = from_index + 1, 7 do
-                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
-                                                               return 0
-                                                       end
-                                               end
-                                               inv:set_stack(from_list, 6, "realchess:rook_black_2")
-                                               inv:set_stack(from_list, 8, "")
-                                               check = false
-                                       end
-                               end
-                       end
-               end
-
-               if check then
-                       if dx < 0 then dx = -dx end
-                       if dy < 0 then dy = -dy end
-                       if dx > 1 or dy > 1 then return 0 end
-               end
-               
-               if thisMove == "white" then
-                       meta:set_int("castlingWhiteL", 0)
-                       meta:set_int("castlingWhiteR", 0)
-               elseif thisMove == "black" then
-                       meta:set_int("castlingBlackL", 0)               
-                       meta:set_int("castlingBlackR", 0)
-               end
-       end
-
-       meta:set_string("playerWhite", playerWhite)
-       meta:set_string("playerBlack", playerBlack)
-       lastMove = thisMove
-       meta:set_string("lastMove", lastMove)
-       meta:set_int("lastMoveTime", minetest.get_gametime())
-
-       if lastMove == "black" then
-               minetest.chat_send_player(playerWhite, "["..os.date("%H:%M:%S").."] "..
-                               playerName.." moved a "..pieceFrom:match(":(%a+)")..", it's now your turn.")
-       elseif lastMove == "white" then
-               minetest.chat_send_player(playerBlack, "["..os.date("%H:%M:%S").."] "..
-                               playerName.." moved a "..pieceFrom:match(":(%a+)")..", it's now your turn.")
-       end
-
-       if pieceTo:sub(11,14) == "king" then
-               minetest.chat_send_player(playerBlack, playerName.." won the game.")
-               minetest.chat_send_player(playerWhite, playerName.." won the game.")
-               meta:set_string("winner", thisMove)
-       end
-
-       return 1
-end
-
-local function timeout_format(timeout_limit)
-       local time_remaining = timeout_limit - minetest.get_gametime()
-       local minutes = math.floor(time_remaining / 60)
-       local seconds = time_remaining % 60
-
-       if minutes == 0 then return seconds.." sec." end
-       return minutes.." min. "..seconds.." sec."
-end
-
-function realchess.fields(pos, _, fields, sender)
-       local playerName = sender:get_player_name()
-       local meta = minetest.get_meta(pos)
-       local timeout_limit = meta:get_int("lastMoveTime") + 300
-       local playerWhite = meta:get_string("playerWhite")
-       local playerBlack = meta:get_string("playerBlack")
-       local lastMoveTime = meta:get_int("lastMoveTime")
-       if fields.quit then return end
-
-       -- timeout is 5 min. by default for resetting the game (non-players only)
-       if fields.new and (playerWhite == playerName or playerBlack == playerName) then
-               realchess.init(pos)
-       elseif fields.new and lastMoveTime ~= 0 and minetest.get_gametime() >= timeout_limit and
-                       (playerWhite ~= playerName or playerBlack ~= playerName) then
-               realchess.init(pos)
-       else
-               minetest.chat_send_player(playerName, "[!] You can't reset the chessboard, a game has been started.\n"..
-                               "If you are not a current player, try again in "..timeout_format(timeout_limit))
-       end
-end
-
-function realchess.dig(pos, player)
-       if not player then
-               return false
-       end
-       local meta = minetest.get_meta(pos)
-       local playerName = player:get_player_name()
-       local timeout_limit = meta:get_int("lastMoveTime") + 300
-       local lastMoveTime = meta:get_int("lastMoveTime")
-
-       -- timeout is 5 min. by default for digging the chessboard (non-players only)
-       return (lastMoveTime == 0 and minetest.get_gametime() > timeout_limit) or
-               minetest.chat_send_player(playerName, "[!] You can't dig the chessboard, a game has been started.\n"..
-                               "Reset it first if you're a current player, or dig again in "..timeout_format(timeout_limit))
-end
-
-function realchess.on_move(pos, from_list, from_index)
-       local inv = minetest.get_meta(pos):get_inventory()
-       inv:set_stack(from_list, from_index, '')
-       return false
-end
-
-minetest.register_node(":realchess:chessboard", {
-       description = "Chess Board",
-       drawtype = "nodebox",
-       paramtype = "light",
-       paramtype2 = "facedir",
-       inventory_image = "chessboard_top.png",
-       wield_image = "chessboard_top.png",
-       tiles = {"chessboard_top.png", "chessboard_top.png", "chessboard_sides.png"},
-       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
-       sounds = default.node_sound_wood_defaults(),
-       node_box = {type = "fixed", fixed = {-.375, -.5, -.375, .375, -.4375, .375}},
-       sunlight_propagates = true,
-       on_rotate = screwdriver.rotate_simple,
-       can_dig = realchess.dig,
-       on_construct = realchess.init,
-       on_receive_fields = realchess.fields,
-       allow_metadata_inventory_move = realchess.move,
-       on_metadata_inventory_move = realchess.on_move,
-       allow_metadata_inventory_take = function() return 0 end
-})
-
-local function register_piece(name, count)
-       for _, color in pairs({"black", "white"}) do
-       if not count then
-               minetest.register_craftitem(":realchess:"..name.."_"..color, {
-                       description = color:gsub("^%l", string.upper).." "..name:gsub("^%l", string.upper),
-                       inventory_image = name.."_"..color..".png",
-                       stack_max = 1,
-                       groups = {not_in_creative_inventory=1}
-               })
-       else
-               for i = 1, count do
-                       minetest.register_craftitem(":realchess:"..name.."_"..color.."_"..i, {
-                               description = color:gsub("^%l", string.upper).." "..name:gsub("^%l", string.upper),
-                               inventory_image = name.."_"..color..".png",
-                               stack_max = 1,
-                               groups = {not_in_creative_inventory=1}
-                       })
-               end
-       end
-       end
-end
-
-register_piece("pawn", 8)
-register_piece("rook", 2)
-register_piece("knight", 2)
-register_piece("bishop", 2)
-register_piece("queen")
-register_piece("king")
-
diff --git a/cooking.lua b/cooking.lua
deleted file mode 100644 (file)
index 46629ec..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-local cauldron, sounds = {}, {}
-
--- Add more ingredients here that make a soup.
-local ingredients_list = {
-       "apple", "mushroom", "honey", "pumpkin", "egg", "bread", "meat",
-       "chicken", "carrot", "potato", "melon", "rhubarb", "cucumber",
-       "corn", "beans", "berries", "grapes", "tomato", "wheat"
-}
-
-cauldron.cbox = {
-       {0,  0, 0,  16, 16, 0},
-       {0,  0, 16, 16, 16, 0},
-       {0,  0, 0,  0,  16, 16},
-       {16, 0, 0,  0,  16, 16},
-       {0,  0, 0,  16, 8,  16}
-}
-
-function cauldron.stop_sound(pos)
-       local spos = minetest.hash_node_position(pos)
-       if sounds[spos] then minetest.sound_stop(sounds[spos]) end
-end
-
-function cauldron.idle_construct(pos)
-       local timer = minetest.get_node_timer(pos)
-       timer:start(10.0)
-       cauldron.stop_sound(pos)
-end
-
-function cauldron.boiling_construct(pos)
-       local spos = minetest.hash_node_position(pos)
-       sounds[spos] = minetest.sound_play("xdecor_boiling_water", {
-               pos=pos, max_hear_distance=5, gain=0.8, loop=true
-       })
-
-       local meta = minetest.get_meta(pos)
-       meta:set_string("infotext", "Cauldron (active) - Drop some foods inside to make a soup")
-
-       local timer = minetest.get_node_timer(pos)
-       timer:start(5.0)
-end
-
-function cauldron.filling(pos, node, clicker, itemstack)
-       local inv = clicker:get_inventory()
-       local wield_item = clicker:get_wielded_item():get_name()
-
-       if wield_item:sub(1,7) == "bucket:" then
-               if wield_item:sub(-6) == "_empty" and not (node.name:sub(-6) == "_empty") then
-                       if itemstack:get_count() > 1 then
-                               if inv:room_for_item("main", "bucket:bucket_water 1") then
-                                       itemstack:take_item()
-                                       inv:add_item("main", "bucket:bucket_water 1")
-                               else
-                                       minetest.chat_send_player(clicker:get_player_name(),
-                                               "No room in your inventory to add a bucket of water.")
-                                       return itemstack
-                               end
-                       else
-                               itemstack:replace("bucket:bucket_water")
-                       end
-                       minetest.set_node(pos, {name="xdecor:cauldron_empty", param2=node.param2})
-               elseif wield_item:sub(-6) == "_water" and node.name:sub(-6) == "_empty" then
-                       minetest.set_node(pos, {name="xdecor:cauldron_idle", param2=node.param2})
-                       itemstack:replace("bucket:bucket_empty")
-               end
-               return itemstack
-       end
-end
-
-function cauldron.idle_timer(pos)
-       local below_node = {x=pos.x, y=pos.y-1, z=pos.z}
-       if not minetest.get_node(below_node).name:find("fire") then
-               return true
-       end
-
-       local node = minetest.get_node(pos)
-       minetest.set_node(pos, {name="xdecor:cauldron_boiling", param2=node.param2})
-       return true
-end
-
--- Ugly hack to determine if an item has `minetest.item_eat` in its definition.
-local function eatable(itemstring)
-       local item = itemstring:match("[%w_:]+")
-       local on_use_def = minetest.registered_items[item].on_use
-       if not on_use_def then return end
-       return string.format("%q", string.dump(on_use_def)):find("item_eat")
-end
-
-function cauldron.boiling_timer(pos)
-       local node = minetest.get_node(pos)
-       local objs = minetest.get_objects_inside_radius(pos, 0.5)
-       if objs == {} then return true end
-
-       local ingredients = {}
-       for _, obj in pairs(objs) do
-               if obj and not obj:is_player() and obj:get_luaentity().itemstring then
-                       local itemstring = obj:get_luaentity().itemstring
-                       local food = itemstring:match(":([%w_]+)")
-
-                       for _, ingredient in pairs(ingredients_list) do
-                               if food and (eatable(itemstring) or food:find(ingredient)) then
-                                       ingredients[#ingredients+1] = food break
-                               end
-                       end
-               end
-       end
-
-       if #ingredients >= 2 then
-               for _, obj in pairs(objs) do obj:remove() end
-               minetest.set_node(pos, {name="xdecor:cauldron_soup", param2=node.param2})
-       end
-
-       local node_under = {x=pos.x, y=pos.y-1, z=pos.z}
-       if not minetest.get_node(node_under).name:find("fire") then
-               minetest.set_node(pos, {name="xdecor:cauldron_idle", param2=node.param2})
-       end
-       return true
-end
-
-function cauldron.take_soup(pos, node, clicker, itemstack)
-       local inv = clicker:get_inventory()
-       local wield_item = clicker:get_wielded_item()
-
-       if wield_item:get_name() == "xdecor:bowl" then
-               if wield_item:get_count() > 1 then
-                       if inv:room_for_item("main", "xdecor:bowl_soup 1") then
-                               itemstack:take_item()
-                               inv:add_item("main", "xdecor:bowl_soup 1")
-                       else
-                               minetest.chat_send_player(clicker:get_player_name(),
-                                       "No room in your inventory to add a bowl of soup.")
-                               return itemstack
-                       end
-               else
-                       itemstack:replace("xdecor:bowl_soup 1")
-               end
-
-               minetest.set_node(pos, {name="xdecor:cauldron_empty", param2=node.param2})
-       end
-       return itemstack
-end
-
-xdecor.register("cauldron_empty", {
-       description = "Cauldron",
-       groups = {cracky=2, oddly_breakable_by_hand=1},
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"xdecor_cauldron_top_empty.png", "xdecor_cauldron_sides.png"},
-       infotext = "Cauldron (empty)",
-       on_construct = function(pos)
-               cauldron.stop_sound(pos)
-       end,
-       on_rightclick = cauldron.filling,
-       collision_box = xdecor.pixelbox(16, cauldron.cbox)
-})
-
-xdecor.register("cauldron_idle", {
-       groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1},
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"xdecor_cauldron_top_idle.png", "xdecor_cauldron_sides.png"},
-       drop = "xdecor:cauldron_empty",
-       infotext = "Cauldron (idle)",
-       collision_box = xdecor.pixelbox(16, cauldron.cbox),
-       on_rightclick = cauldron.filling,
-       on_construct = cauldron.idle_construct,
-       on_timer = cauldron.idle_timer
-})
-
-xdecor.register("cauldron_boiling", {
-       groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1},
-       on_rotate = screwdriver.rotate_simple,
-       drop = "xdecor:cauldron_empty",
-       infotext = "Cauldron (active) - Drop foods inside to make a soup",
-       damage_per_second = 2,
-       tiles = {{name="xdecor_cauldron_top_anim_boiling_water.png",
-                       animation={type="vertical_frames", length=3.0}},
-               "xdecor_cauldron_sides.png"},
-       collision_box = xdecor.pixelbox(16, cauldron.cbox),
-       on_rightclick = cauldron.filling,
-       on_construct = cauldron.boiling_construct,
-       on_destruct = function(pos)
-               cauldron.stop_sound(pos)
-       end,
-       on_timer = cauldron.boiling_timer
-})
-
-xdecor.register("cauldron_soup", {
-       groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1},
-       on_rotate = screwdriver.rotate_simple,
-       drop = "xdecor:cauldron_empty",
-       infotext = "Cauldron (active) - Use a bowl to eat the soup",
-       damage_per_second = 2,
-       tiles = {{name="xdecor_cauldron_top_anim_soup.png",
-                       animation={type="vertical_frames", length=3.0}},
-               "xdecor_cauldron_sides.png"},
-       collision_box = xdecor.pixelbox(16, cauldron.cbox),
-       on_rightclick = cauldron.take_soup,
-       on_destruct = function(pos)
-               cauldron.stop_sound(pos)
-       end
-})
-
diff --git a/craftguide.lua b/craftguide.lua
deleted file mode 100644 (file)
index dd59327..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-local craftguide, datas, npp = {}, {}, 8*3
-
-function craftguide:get_recipe(item)
-       if item:sub(1,6) == "group:" then
-               if item:sub(-4) == "wool" or item:sub(-3) == "dye" then
-                       item = item:sub(7)..":white"
-               elseif minetest.registered_items["default:"..item:sub(7)] then
-                       item = item:gsub("group:", "default:")
-               else for node, def in pairs(minetest.registered_items) do
-                        if def.groups[item:match("[^,:]+$")] then item = node end
-                    end
-               end
-       end
-       return item
-end
-
-function craftguide:set_formspec(player_name, pagenum, recipe_num)
-       local data = datas[player_name]
-       local formspec = [[ size[8,6.6;]
-                       tablecolumns[color;text;color;text]
-                       tableoptions[background=#00000000;highlight=#00000000;border=false]
-                       button[5.4,0;0.8,0.95;prev;<]
-                       button[7.2,0;0.8,0.95;next;>]
-                       button[2.5,0.2;0.8,0.5;search;?]
-                       button[3.2,0.2;0.8,0.5;clear;X]
-                       tooltip[search;Search]
-                       tooltip[clear;Reset]
-                       table[6,0.18;1.1,0.5;pagenum;#FFFF00,]]..
-                       pagenum..",#FFFFFF,/ "..data.pagemax.."]"..
-                       "field[0.3,0.32;2.6,1;filter;;"..data.filter.."]"..
-                       default.gui_bg..default.gui_bg_img
-
-       local first_item = (pagenum - 1) * npp
-       for i = first_item, first_item + npp - 1 do
-               local name = data.items[i + 1]
-               if not name then break end -- last page
-
-               local X = i % 8
-               local Y = ((i % npp - X) / 8) + 1
-
-               formspec = formspec.."item_image_button["..X..","..Y..";1,1;"..
-                                       name..";"..name..";]"
-       end
-
-       if data.item and minetest.registered_items[data.item] then
-               local recipes = minetest.get_all_craft_recipes(data.item)
-               if recipe_num > #recipes then recipe_num = 1 end
-
-               if #recipes > 1 then formspec = formspec..
-                       [[ button[0,6;1.6,1;alternate;Alternate]
-                       label[0,5.5;Recipe ]]..recipe_num.." of "..#recipes.."]"
-               end
-
-               local type = recipes[recipe_num].type
-               if type == "cooking" then formspec = formspec..
-                       "image[3.75,4.6;0.5,0.5;default_furnace_front.png]"
-               end
-
-               local items = recipes[recipe_num].items
-               local width = recipes[recipe_num].width
-               if width == 0 then width = math.min(3, #items) end
-               -- Lua 5.3 removed `table.maxn`, use `xdecor.maxn` in case of breakage.
-               local rows = math.ceil(table.maxn(items) / width)
-
-               for i, v in pairs(items) do
-                       local X = (i-1) % width + 4.5
-                       local Y = math.floor((i-1) / width + (6 - math.min(2, rows)))
-                       local label = ""
-                       if v:sub(1,6) == "group:" then label = "\nG" end
-
-                       formspec = formspec.."item_image_button["..X..","..Y..";1,1;"..
-                                            self:get_recipe(v)..";"..self:get_recipe(v)..";"..label.."]"
-               end
-
-               local output = recipes[recipe_num].output
-               formspec = formspec..[[ image[3.5,5;1,1;gui_furnace_arrow_bg.png^[transformR90]
-                                       item_image_button[2.5,5;1,1;]]..output..";"..data.item..";]"                 
-       end
-
-       data.formspec = formspec
-       minetest.show_formspec(player_name, "xdecor:craftguide", formspec)
-end
-
-function craftguide:get_items(player_name)
-       local items_list, data = {}, datas[player_name]
-       for name, def in pairs(minetest.registered_items) do
-               if not (def.groups.not_in_creative_inventory == 1) and
-                               minetest.get_craft_recipe(name).items and
-                               def.description and def.description ~= "" and
-                               (def.name:find(data.filter, 1, true) or
-                                       def.description:lower():find(data.filter, 1, true)) then
-                       items_list[#items_list+1] = name
-               end
-       end
-
-       table.sort(items_list)
-       data.items = items_list
-       data.size = #items_list
-       data.pagemax = math.ceil(data.size / npp)
-end
-
-minetest.register_on_player_receive_fields(function(player, formname, fields)
-       if formname ~= "xdecor:craftguide" then return end
-       local player_name = player:get_player_name()
-       local data = datas[player_name]
-       local formspec = data.formspec
-       local pagenum = tonumber(formspec:match("#FFFF00,(%d+)")) or 1
-
-       if fields.clear then
-               data.filter, data.item = "", nil
-               craftguide:get_items(player_name)
-               craftguide:set_formspec(player_name, 1, 1)
-       elseif fields.alternate then
-               local recipe_num = tonumber(formspec:match("Recipe%s(%d+)")) or 1
-               recipe_num = recipe_num + 1
-               craftguide:set_formspec(player_name, pagenum, recipe_num)
-       elseif fields.search then
-               data.filter = fields.filter:lower()
-               craftguide:get_items(player_name)
-               craftguide:set_formspec(player_name, 1, 1)
-       elseif fields.prev or fields.next then
-               if fields.prev then pagenum = pagenum - 1
-               else pagenum = pagenum + 1 end
-               if     pagenum > data.pagemax then pagenum = 1
-               elseif pagenum == 0           then pagenum = data.pagemax end
-               craftguide:set_formspec(player_name, pagenum, 1)
-       else for item in pairs(fields) do
-                if minetest.get_craft_recipe(item).items then
-                       data.item = item
-                       craftguide:set_formspec(player_name, pagenum, 1)
-                end
-            end
-       end
-end)
-
-minetest.register_craftitem("xdecor:crafting_guide", {
-       description = "Crafting Guide",
-       inventory_image = "xdecor_crafting_guide.png",
-       wield_image = "xdecor_crafting_guide.png",
-       stack_max = 1,
-       groups = {book=1},
-       on_use = function(itemstack, user)
-               local player_name = user:get_player_name()
-               if not datas[player_name] then
-                       datas[player_name] = {}
-                       datas[player_name].filter = ""
-                       craftguide:get_items(player_name)
-                       craftguide:set_formspec(player_name, 1, 1)
-               else
-                       minetest.show_formspec(player_name, "xdecor:craftguide", datas[player_name].formspec)
-               end
-       end
-})
-
diff --git a/craftitems.lua b/craftitems.lua
deleted file mode 100644 (file)
index a1eadb1..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-minetest.register_craftitem("xdecor:bowl", {
-       description = "Bowl",
-       inventory_image = "xdecor_bowl.png",
-       wield_image = "xdecor_bowl.png"
-})
-
-minetest.register_craftitem("xdecor:bowl_soup", {
-       description = "Bowl of soup",
-       inventory_image = "xdecor_bowl_soup.png",
-       wield_image = "xdecor_bowl_soup.png",
-       groups = {not_in_creative_inventory=1},
-       stack_max = 1,
-       on_use = function(itemstack, user)
-               itemstack:replace("xdecor:bowl 1")
-               if rawget(_G, "hunger") then
-                       minetest.item_eat(20)
-               else
-                       user:set_hp(20)
-               end
-               return itemstack
-       end
-})
-
-minetest.register_tool("xdecor:hammer", {
-       description = "Hammer",
-       inventory_image = "xdecor_hammer.png",
-       wield_image = "xdecor_hammer.png",
-       on_use = function() do return end end
-})
-
-minetest.register_craftitem("xdecor:honey", {
-       description = "Honey",
-       inventory_image = "xdecor_honey.png",
-       wield_image = "xdecor_honey.png",
-       groups = {not_in_creative_inventory=1},
-       on_use = minetest.item_eat(2)
-})
-
diff --git a/enchanting.lua b/enchanting.lua
deleted file mode 100644 (file)
index 028a5b4..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-local enchanting = {}
-screwdriver = screwdriver or {}
-
--- Cost in Mese crystal(s) for enchanting.
-local mese_cost = 1
-
--- Force of the enchantments.
-enchanting.uses     = 1.2  -- Durability
-enchanting.times    = 0.1  -- Efficiency
-enchanting.damages  = 1    -- Sharpness
-enchanting.strength = 1.2  -- Armor strength (3d_armor only)
-enchanting.speed    = 0.2  -- Player speed (3d_armor only)
-enchanting.jump     = 0.2  -- Player jumping (3d_armor only)
-
-function enchanting.formspec(pos, num)
-       local meta = minetest.get_meta(pos)
-       local formspec = [[ size[9,9;]
-                       bgcolor[#080808BB;true]
-                       background[0,0;9,9;ench_ui.png]
-                       list[context;tool;0.9,2.9;1,1;]
-                       list[context;mese;2,2.9;1,1;]
-                       list[current_player;main;0.5,4.5;8,4;]
-                       image[2,2.9;1,1;mese_layout.png]
-                       tooltip[sharp;Your weapon inflicts more damages]
-                       tooltip[durable;Your tool last longer]
-                       tooltip[fast;Your tool digs faster]
-                       tooltip[strong;Your armor is more resistant]
-                       tooltip[speed;Your speed is increased] ]]
-                       ..default.gui_slots..default.get_hotbar_bg(0.5,4.5)
-
-       local enchant_buttons = {
-               [[ image_button[3.9,0.85;4,0.92;bg_btn.png;fast;Efficiency]
-               image_button[3.9,1.77;4,1.12;bg_btn.png;durable;Durability] ]],
-               "image_button[3.9,0.85;4,0.92;bg_btn.png;strong;Strength]",
-               "image_button[3.9,2.9;4,0.92;bg_btn.png;sharp;Sharpness]",
-               [[ image_button[3.9,0.85;4,0.92;bg_btn.png;strong;Strength]
-               image_button[3.9,1.77;4,1.12;bg_btn.png;speed;Speed] ]]
-       }
-
-       formspec = formspec..(enchant_buttons[num] or "")
-       meta:set_string("formspec", formspec)
-end
-
-function enchanting.on_put(pos, listname, _, stack)
-       if listname == "tool" then
-               local stackname = stack:get_name()
-               local tool_groups = {
-                       "axe, pick, shovel",
-                       "chestplate, leggings, helmet",
-                       "sword", "boots"
-               }
-
-               for idx, tools in pairs(tool_groups) do
-                       if tools:find(stackname:match(":(%w+)")) then
-                               enchanting.formspec(pos, idx)
-                       end
-               end
-       end
-end
-
-function enchanting.fields(pos, _, fields, sender)
-       if not next(fields) or fields.quit then
-               return
-       end
-       local inv = minetest.get_meta(pos):get_inventory()
-       local tool = inv:get_stack("tool", 1)
-       local mese = inv:get_stack("mese", 1)
-       local orig_wear = tool:get_wear()
-       local mod, name = tool:get_name():match("(.*):(.*)")
-       local enchanted_tool = (mod or "")..":enchanted_"..(name or "").."_"..next(fields)
-
-       if mese:get_count() >= mese_cost and minetest.registered_tools[enchanted_tool] then
-               minetest.sound_play("xdecor_enchanting", {to_player=sender:get_player_name(), gain=0.8})
-               tool:replace(enchanted_tool)
-               tool:add_wear(orig_wear)
-               mese:take_item(mese_cost)
-               inv:set_stack("mese", 1, mese)
-               inv:set_stack("tool", 1, tool)
-       end
-end
-
-function enchanting.dig(pos)
-       local inv = minetest.get_meta(pos):get_inventory()
-       return inv:is_empty("tool") and inv:is_empty("mese")
-end
-
-local function allowed(tool)
-       if not tool then
-               return false
-       end
-       for item in pairs(minetest.registered_tools) do
-               if item:find("enchanted_"..tool) then return true end
-       end
-       return false
-end
-
-function enchanting.put(_, listname, _, stack)
-       local item = stack:get_name():match("[^:]+$")
-       if listname == "mese" and item == "mese_crystal" then
-               return stack:get_count()
-       elseif listname == "tool" and allowed(item) then
-               return 1 
-       end
-       return 0
-end
-
-function enchanting.on_take(pos, listname)
-       if listname == "tool" then enchanting.formspec(pos, nil) end
-end
-
-function enchanting.construct(pos)
-       local meta = minetest.get_meta(pos)
-       meta:set_string("infotext", "Enchantment Table")
-       enchanting.formspec(pos, nil)
-
-       local inv = meta:get_inventory()
-       inv:set_size("tool", 1)
-       inv:set_size("mese", 1)
-
-       minetest.add_entity({x=pos.x, y=pos.y+0.85, z=pos.z}, "xdecor:book_open")
-       local timer = minetest.get_node_timer(pos)
-       timer:start(5.0)
-end
-
-function enchanting.destruct(pos)
-       for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do
-               if obj and obj:get_luaentity() and
-                               obj:get_luaentity().name == "xdecor:book_open" then
-                       obj:remove() break
-               end
-       end
-end
-
-function enchanting.timer(pos)
-       local num = #minetest.get_objects_inside_radius(pos, 0.9)
-
-       if num == 0 then
-               minetest.add_entity({x=pos.x, y=pos.y+0.85, z=pos.z}, "xdecor:book_open")
-       end
-
-       local minp = {x=pos.x-2, y=pos.y, z=pos.z-2}
-       local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
-       local bookshelves = minetest.find_nodes_in_area(minp, maxp, "default:bookshelf")
-       if #bookshelves == 0 then return true end
-
-       local bookshelf_pos = bookshelves[math.random(1, #bookshelves)]
-       local x = pos.x - bookshelf_pos.x
-       local y = bookshelf_pos.y - pos.y
-       local z = pos.z - bookshelf_pos.z
-
-       if tostring(x..z):find(2) then
-               minetest.add_particle({
-                       pos = bookshelf_pos,
-                       velocity = {x=x, y=2-y, z=z},
-                       acceleration = {x=0, y=-2.2, z=0},
-                       expirationtime = 1,
-                       size = 2,
-                       texture = "xdecor_glyph"..math.random(1,18)..".png"
-               })
-       end
-       return true
-end
-
-xdecor.register("enchantment_table", {
-       description = "Enchantment Table",
-       tiles = {"xdecor_enchantment_top.png",  "xdecor_enchantment_bottom.png",
-                "xdecor_enchantment_side.png", "xdecor_enchantment_side.png",
-                "xdecor_enchantment_side.png", "xdecor_enchantment_side.png"},
-       groups = {cracky=1, level=1},
-       sounds = default.node_sound_stone_defaults(),
-       on_rotate = screwdriver.rotate_simple,
-       can_dig = enchanting.dig,
-       on_timer = enchanting.timer,
-       on_construct = enchanting.construct,
-       on_destruct = enchanting.destruct,
-       on_receive_fields = enchanting.fields,
-       on_metadata_inventory_put = enchanting.on_put,
-       on_metadata_inventory_take = enchanting.on_take,
-       allow_metadata_inventory_put = enchanting.put,
-       allow_metadata_inventory_move = function() return 0 end
-})
-
-minetest.register_entity("xdecor:book_open", {
-       visual = "sprite",
-       visual_size = {x=0.75, y=0.75},
-       collisionbox = {0},
-       physical = false,
-       textures = {"xdecor_book_open.png"},
-       on_activate = function(self)
-               local pos = self.object:getpos()
-               local pos_under = {x=pos.x, y=pos.y-1, z=pos.z}
-
-               if minetest.get_node(pos_under).name ~= "xdecor:enchantment_table" then
-                       self.object:remove()
-               end
-       end
-})
-
-local function cap(S) return S:gsub("^%l", string.upper) end
-
-function enchanting:register_tools(mod, def)
-       for tool in pairs(def.tools) do
-       for material in def.materials:gmatch("[%w_]+") do
-       for enchant in def.tools[tool].enchants:gmatch("[%w_]+") do
-               local original_tool = minetest.registered_tools[mod..":"..tool.."_"..material]
-               if not original_tool then break end
-
-               if original_tool.tool_capabilities then
-                       local original_damage_groups = original_tool.tool_capabilities.damage_groups
-                       local original_groupcaps = original_tool.tool_capabilities.groupcaps
-                       local groupcaps = table.copy(original_groupcaps)
-                       local fleshy = original_damage_groups.fleshy
-                       local full_punch_interval = original_tool.tool_capabilities.full_punch_interval
-                       local max_drop_level = original_tool.tool_capabilities.max_drop_level
-                       local group = next(original_groupcaps)
-
-                       if enchant == "durable" then
-                               groupcaps[group].uses = math.ceil(original_groupcaps[group].uses * enchanting.uses)
-                       elseif enchant == "fast" then
-                               for i, time in pairs(original_groupcaps[group].times) do
-                                       groupcaps[group].times[i] = time - enchanting.times
-                               end
-                       elseif enchant == "sharp" then
-                               fleshy = fleshy + enchanting.damages
-                       end
-
-                       minetest.register_tool(":"..mod..":enchanted_"..tool.."_"..material.."_"..enchant, {
-                               description = "Enchanted "..cap(material).." "..cap(tool).." ("..cap(enchant)..")",
-                               inventory_image = original_tool.inventory_image.."^[colorize:violet:50",
-                               wield_image = original_tool.wield_image,
-                               groups = {not_in_creative_inventory=1},
-                               tool_capabilities = {
-                                       groupcaps = groupcaps, damage_groups = {fleshy = fleshy},
-                                       full_punch_interval = full_punch_interval, max_drop_level = max_drop_level
-                               }
-                       })
-               end
-
-               if mod == "3d_armor" then
-                       local original_armor_groups = original_tool.groups
-                       local armorcaps = {}
-                       armorcaps.not_in_creative_inventory = 1
-
-                       for armor_group, value in pairs(original_armor_groups) do
-                               if enchant == "strong" then
-                                       armorcaps[armor_group] = math.ceil(value * enchanting.strength)
-                               elseif enchant == "speed" then
-                                       armorcaps[armor_group] = value
-                                       armorcaps.physics_speed = enchanting.speed
-                                       armorcaps.physics_jump = enchanting.jump
-                               end
-                       end
-
-                       minetest.register_tool(":"..mod..":enchanted_"..tool.."_"..material.."_"..enchant, {
-                               description = "Enchanted "..cap(material).." "..cap(tool).." ("..cap(enchant)..")",
-                               inventory_image = original_tool.inventory_image,
-                               texture = "3d_armor_"..tool.."_"..material,
-                               wield_image = original_tool.wield_image,
-                               groups = armorcaps,
-                               wear = 0
-                       })
-               end
-       end
-       end
-       end
-end
-
-enchanting:register_tools("default", {
-       materials = "steel, bronze, mese, diamond",
-       tools = {
-               axe    = {enchants = "durable, fast"},
-               pick   = {enchants = "durable, fast"}, 
-               shovel = {enchants = "durable, fast"},
-               sword  = {enchants = "sharp"}
-       }
-})
-
-enchanting:register_tools("3d_armor", {
-       materials = "steel, bronze, gold, diamond",
-       tools = {
-               boots      = {enchants = "strong, speed"},
-               chestplate = {enchants = "strong"},
-               helmet     = {enchants = "strong"},
-               leggings   = {enchants = "strong"}
-       }
-})
-
diff --git a/hive.lua b/hive.lua
deleted file mode 100644 (file)
index 6043135..0000000
--- a/hive.lua
+++ /dev/null
@@ -1,69 +0,0 @@
-local hive = {}
-local honey_max = 16
-
-function hive.construct(pos)
-       local meta = minetest.get_meta(pos)
-       local inv = meta:get_inventory()
-
-       local formspec = [[ size[8,5;]
-                       label[0.5,0;Bees are busy making honey...]
-                       image[6,0;1,1;hive_bee.png]
-                       image[5,0;1,1;hive_layout.png]
-                       list[context;honey;5,0;1,1;]
-                       list[current_player;main;0,1.35;8,4;] ]]
-                       ..xbg..default.get_hotbar_bg(0,1.35)
-
-       meta:set_string("formspec", formspec)
-       meta:set_string("infotext", "Artificial Hive")
-       inv:set_size("honey", 1)
-
-       local timer = minetest.get_node_timer(pos)
-       timer:start(math.random(64, 128))
-end
-
-function hive.timer(pos)
-       local time = (minetest.get_timeofday() or 0) * 24000
-       if time < 5500 or time > 18500 then return true end
-
-       local inv = minetest.get_meta(pos):get_inventory()
-       local honeystack = inv:get_stack("honey", 1)
-       local honey = honeystack:get_count()
-
-       local radius = 4
-       local minp = vector.add(pos, -radius)
-       local maxp = vector.add(pos, radius)
-       local flowers = minetest.find_nodes_in_area_under_air(minp, maxp, "group:flower")
-
-       if #flowers > 2 and honey < honey_max then
-               inv:add_item("honey", "xdecor:honey")
-       elseif honey == honey_max then
-               local timer = minetest.get_node_timer(pos)
-               timer:stop() return true
-       end
-       return true
-end
-
-xdecor.register("hive", {
-       description = "Artificial Hive",
-       tiles = {"xdecor_hive_top.png", "xdecor_hive_top.png",
-                "xdecor_hive_side.png", "xdecor_hive_side.png",
-                "xdecor_hive_side.png", "xdecor_hive_front.png"},
-       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=1},
-       on_construct = hive.construct,
-       on_timer = hive.timer,
-       can_dig = function(pos)
-               local inv = minetest.get_meta(pos):get_inventory()
-               return inv:is_empty("honey")
-       end,
-       on_punch = function(_, _, puncher)
-               puncher:set_hp(puncher:get_hp() - 2)
-       end,
-       allow_metadata_inventory_put = function() return 0 end,
-       on_metadata_inventory_take = function(pos, _, _, stack)
-               if stack:get_count() == honey_max then
-                       local timer = minetest.get_node_timer(pos)
-                       timer:start(math.random(64, 128))
-               end
-       end
-})
-
index 4a194646cbdf2dd4ab57d5ff34b2a7a92b376d81..629daee3e4d58c7dabc480cc2ab6f9dd7e8c1c35 100644 (file)
--- a/init.lua
+++ b/init.lua
@@ -9,18 +9,16 @@ dofile(modpath.."/handlers/nodeboxes.lua")
 dofile(modpath.."/handlers/registration.lua")
 
 -- Item files.
-dofile(modpath.."/chess.lua")
-dofile(modpath.."/cooking.lua")
-dofile(modpath.."/craftguide.lua")
-dofile(modpath.."/craftitems.lua")
-dofile(modpath.."/enchanting.lua")
-dofile(modpath.."/hive.lua")
-dofile(modpath.."/itemframe.lua")
-dofile(modpath.."/mailbox.lua")
-dofile(modpath.."/mechanisms.lua")
-dofile(modpath.."/nodes.lua")
-dofile(modpath.."/recipes.lua")
-dofile(modpath.."/rope.lua")
-dofile(modpath.."/workbench.lua")
+dofile(modpath.."/src/chess.lua")
+dofile(modpath.."/src/cooking.lua")
+dofile(modpath.."/src/craftitems.lua")
+dofile(modpath.."/src/enchanting.lua")
+dofile(modpath.."/src/hive.lua")
+dofile(modpath.."/src/itemframe.lua")
+dofile(modpath.."/src/mailbox.lua")
+dofile(modpath.."/src/mechanisms.lua")
+dofile(modpath.."/src/nodes.lua")
+dofile(modpath.."/src/recipes.lua")
+dofile(modpath.."/src/rope.lua")
+dofile(modpath.."/src/workbench.lua")
 --print(string.format("[xdecor] loaded in %.2f ms", (os.clock()-t)*1000))
-
diff --git a/itemframe.lua b/itemframe.lua
deleted file mode 100644 (file)
index 02d83d6..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-local itemframe, tmp = {}, {}
-screwdriver = screwdriver or {}
-
-local function remove_item(pos, node)
-       local objs = minetest.get_objects_inside_radius(pos, 0.5)
-       if not objs then return end
-
-       for _, obj in pairs(objs) do
-               if obj and obj:get_luaentity() and
-                               obj:get_luaentity().name == "xdecor:f_item" then
-                       obj:remove() break
-               end
-       end
-end
-
-local facedir = {
-       [0] = {x=0, y=0, z=1}, {x=1, y=0, z=0}, {x=0, y=0, z=-1}, {x=-1, y=0, z=0}
-}
-
-local function update_item(pos, node)
-       remove_item(pos, node)
-       local meta = minetest.get_meta(pos)
-       local itemstring = meta:get_string("item")
-       local posad = facedir[node.param2]
-       if not posad or itemstring == "" then return end
-
-       pos = vector.add(pos, vector.multiply(posad, 6.5/16))
-       tmp.nodename = node.name
-       tmp.texture = ItemStack(itemstring):get_name()
-
-       local entity = minetest.add_entity(pos, "xdecor:f_item")
-       local yaw = math.pi*2 - node.param2 * math.pi/2
-       entity:setyaw(yaw)
-
-       local timer = minetest.get_node_timer(pos)
-       timer:start(15.0)
-end
-
-local function drop_item(pos, node)
-       local meta = minetest.get_meta(pos)
-       local item = meta:get_string("item")
-       if item == "" then return end
-
-       minetest.add_item(pos, item)
-       meta:set_string("item", "")
-       remove_item(pos, node)
-
-       local timer = minetest.get_node_timer(pos)
-       timer:stop()
-end
-
-function itemframe.after_place(pos, placer, itemstack)
-       local meta = minetest.get_meta(pos)
-       local name = placer:get_player_name()
-       meta:set_string("owner", name)
-       meta:set_string("infotext", "Item Frame (owned by "..name..")")
-end
-
-function itemframe.timer(pos)
-       local node = minetest.get_node(pos)
-       local meta = minetest.get_meta(pos)
-       local num = #minetest.get_objects_inside_radius(pos, 0.5)
-
-       if num == 0 and meta:get_string("item") ~= "" then
-               update_item(pos, node)
-       end
-       return true
-end
-
-function itemframe.rightclick(pos, node, clicker, itemstack)
-       local meta = minetest.get_meta(pos)
-       local player = clicker:get_player_name()
-       local owner = meta:get_string("owner")
-       if player ~= owner or not itemstack then
-               return itemstack
-       end
-
-       drop_item(pos, node)
-       local itemstring = itemstack:take_item():to_string()
-       meta:set_string("item", itemstring)
-       update_item(pos, node)
-
-       return itemstack
-end
-
-function itemframe.punch(pos, node, puncher)
-       local meta = minetest.get_meta(pos)
-       local player = puncher:get_player_name()
-       local owner = meta:get_string("owner")
-
-       if player ~= owner then return end
-       drop_item(pos, node)
-end
-
-function itemframe.dig(pos, player)
-       local meta = minetest.get_meta(pos)
-       local pname = player and player:get_player_name()
-       local owner = meta:get_string("owner")
-
-       return pname == owner
-end
-
-xdecor.register("itemframe", {
-       description = "Item Frame",
-       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
-       sounds = default.node_sound_wood_defaults(),
-       on_rotate = screwdriver.disallow,
-       sunlight_propagates = true,
-       inventory_image = "xdecor_itemframe.png",
-       node_box = xdecor.nodebox.slab_z(0.9375),
-       tiles = {"xdecor_wood.png", "xdecor_wood.png", "xdecor_wood.png",
-                "xdecor_wood.png", "xdecor_wood.png", "xdecor_itemframe.png"},
-       after_place_node = itemframe.after_place,
-       on_timer = itemframe.timer,
-       on_rightclick = itemframe.rightclick,
-       on_punch = itemframe.punch,
-       can_dig = itemframe.dig,
-       after_destruct = remove_item
-})
-
-minetest.register_entity("xdecor:f_item", {
-       visual = "wielditem",
-       visual_size = {x=0.33, y=0.33},
-       collisionbox = {0},
-       physical = false,
-       textures = {"air"},
-       on_activate = function(self, staticdata)
-               local pos = self.object:getpos()
-               if minetest.get_node(pos).name ~= "xdecor:itemframe" then
-                       self.object:remove()
-               end
-
-               if tmp.nodename and tmp.texture then
-                       self.nodename = tmp.nodename
-                       tmp.nodename = nil
-                       self.texture = tmp.texture
-                       tmp.texture = nil
-               elseif staticdata and staticdata ~= "" then
-                       local data = staticdata:split(";")
-                       if data and data[1] and data[2] then
-                               self.nodename = data[1]
-                               self.texture = data[2]
-                       end
-               end
-               if self.texture then
-                       self.object:set_properties({textures={self.texture}})
-               end
-       end,
-       get_staticdata = function(self)
-               if self.nodename and self.texture then
-                       return self.nodename..";"..self.texture
-               end
-               return ""
-       end
-})
-
diff --git a/mailbox.lua b/mailbox.lua
deleted file mode 100644 (file)
index cd9a03c..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-local mailbox = {}
-screwdriver = screwdriver or {}
-
-local function get_img(img)
-       local img_name = img:match("(.*)%.png")
-       if img_name then return img_name..".png" end
-end
-
-local function img_col(stack)
-       local def = minetest.registered_items[stack]
-       if not def then return "" end
-
-       if def.inventory_image ~= "" then
-               local img = get_img(def.inventory_image)
-               if img then return img end
-       end
-
-       if def.tiles then
-               local img
-               local tile = def.tiles[1]
-
-               if type(tile) == "table" then
-                       img = get_img(tile.name)
-               elseif type(tile) == "string" then
-                       img = get_img(tile)
-               end
-
-               if img then return img end
-       end
-
-       return ""
-end
-
-function mailbox:formspec(pos, owner, num)
-       local spos = pos.x..","..pos.y..","..pos.z
-       local meta = minetest.get_meta(pos)
-       local giver, img = "", ""
-
-       if num == 1 then
-               for i = 1, 7 do
-                       local giving = meta:get_string("giver"..i)
-                       if giving ~= "" then
-                               local stack = meta:get_string("stack"..i)
-                               local giver_name = giving:sub(1,12)
-                               local stack_name = stack:match("[%w_:]+")
-                               local stack_count = stack:match("%s(%d+)") or 1
-
-                               giver = giver.."#FFFF00,"..giver_name..","..i..",#FFFFFF,x "..stack_count..","
-                               -- Hack to force using a 16px resolution for images in formspec's tablecolumn.
-                               -- The engine doesn't scale them automatically yet.
-                               img = img..i.."="..img_col(stack_name).."^\\[resize:16x16,"
-                       end
-               end
-
-               return [[ size[9.5,9]
-                       label[0,0;Mailbox]
-                       label[6,0;Last donators]
-                       box[6,0.72;3.3,3.5;#555555]
-                       listring[current_player;main]
-                       list[current_player;main;0.75,5.25;8,4;]
-                       tableoptions[background=#00000000;highlight=#00000000;border=false] ]]
-                       .."tablecolumns[color;text;image,"..img.."0;color;text]"..
-                       "table[6,0.75;3.3,4;givers;"..giver.."]"..
-                       "list[nodemeta:"..spos..";mailbox;0,0.75;6,4;]"..
-                       "listring[nodemeta:"..spos..";mailbox]"..
-                       xbg..default.get_hotbar_bg(0.75,5.25)
-       else
-               return [[ size[8,5]
-                       list[current_player;main;0,1.25;8,4;]
-                       tablecolumns[color;text;color;text]
-                       tableoptions[background=#00000000;highlight=#00000000;border=false] ]]
-                       .."table[0,0;3,1;sendform;#FFFFFF,Send your goods to,,,#FFFF00,"..owner.."]"..
-                       "list[nodemeta:"..spos..";drop;3.5,0;1,1;]"..
-                       xbg..default.get_hotbar_bg(0,1.25)
-       end
-end
-
-function mailbox.dig(pos, player)
-       local meta = minetest.get_meta(pos)
-       local owner = meta:get_string("owner")
-       local player_name = player and player:get_player_name()
-       local inv = meta:get_inventory()
-
-       return inv:is_empty("mailbox") and player_name == owner
-end
-
-function mailbox.after_place_node(pos, placer)
-       local meta = minetest.get_meta(pos)
-       local player_name = placer:get_player_name()
-
-       meta:set_string("owner", player_name)
-       meta:set_string("infotext", player_name.."'s Mailbox")
-
-       local inv = meta:get_inventory()
-       inv:set_size("mailbox", 6*4)
-       inv:set_size("drop", 1)
-end
-
-function mailbox.rightclick(pos, node, clicker, itemstack, pointed_thing)
-       local meta = minetest.get_meta(pos)
-       local player = clicker:get_player_name()
-       local owner = meta:get_string("owner")
-
-       if player == owner then
-               minetest.show_formspec(player, "xdecor:mailbox", mailbox:formspec(pos, owner, 1))
-       else
-               minetest.show_formspec(player, "xdecor:mailbox", mailbox:formspec(pos, owner, 0))
-       end
-       return itemstack
-end
-
-function mailbox.put(pos, listname, _, stack, player)
-       if listname == "drop" then
-               local inv = minetest.get_meta(pos):get_inventory()
-               if inv:room_for_item("mailbox", stack) then
-                       return -1
-               else
-                       minetest.chat_send_player(player:get_player_name(), "The mailbox is full")
-               end
-       end
-       return 0
-end
-
-function mailbox.on_put(pos, listname, _, stack, player)
-       local meta = minetest.get_meta(pos)
-       local inv = meta:get_inventory()
-
-       if listname == "drop" and inv:room_for_item("mailbox", stack) then
-               inv:set_list("drop", {})
-               inv:add_item("mailbox", stack)
-
-               for i = 7, 2, -1 do
-                       meta:set_string("giver"..i, meta:get_string("giver"..(i-1)))
-                       meta:set_string("stack"..i, meta:get_string("stack"..(i-1)))
-               end
-
-               meta:set_string("giver1", player:get_player_name())
-               meta:set_string("stack1", stack:to_string())
-       end
-end
-
-xdecor.register("mailbox", {
-       description = "Mailbox",
-       tiles = {"xdecor_mailbox_top.png", "xdecor_mailbox_bottom.png",
-                "xdecor_mailbox_side.png", "xdecor_mailbox_side.png",
-                "xdecor_mailbox.png", "xdecor_mailbox.png"},
-       groups = {cracky=3, oddly_breakable_by_hand=1},
-       on_rotate = screwdriver.rotate_simple,
-       can_dig = mailbox.dig,
-       on_rightclick = mailbox.rightclick,
-       on_metadata_inventory_put = mailbox.on_put,
-       allow_metadata_inventory_put = mailbox.put,
-       after_place_node = mailbox.after_place_node
-})
diff --git a/mechanisms.lua b/mechanisms.lua
deleted file mode 100644 (file)
index 4686302..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
---[[ Thanks to sofar for helping with that code.
-Recommended setting in minetest.conf (requires 0.4.14 or newer) :
-       nodetimer_interval = 0.1
-]]
-
-local plate = {}
-screwdriver = screwdriver or {}
-
-local function door_toggle(pos_actuator, pos_door, player)
-       local actuator = minetest.get_node(pos_actuator)
-       local door = doors.get(pos_door)
-
-       if actuator.name:sub(-4) == "_off" then
-               minetest.set_node(pos_actuator,
-                       {name=actuator.name:gsub("_off", "_on"), param2=actuator.param2})
-       end
-       door:open(player)
-
-       minetest.after(2, function()
-               if minetest.get_node(pos_actuator).name:sub(-3) == "_on" then
-                       minetest.set_node(pos_actuator,
-                               {name=actuator.name, param2=actuator.param2})
-               end
-               door:close(player)
-       end)
-end
-
-function plate.construct(pos)
-       local timer = minetest.get_node_timer(pos)
-       timer:start(0.1)
-end
-
-function plate.timer(pos)
-       local objs = minetest.get_objects_inside_radius(pos, 0.8)
-       if objs == {} or not doors.get then return true end
-       local minp = {x=pos.x-2, y=pos.y, z=pos.z-2}
-       local maxp = {x=pos.x+2, y=pos.y, z=pos.z+2}
-       local doors = minetest.find_nodes_in_area(minp, maxp, "group:door")
-
-       for _, player in pairs(objs) do
-               if player:is_player() then
-                       for i = 1, #doors do
-                               door_toggle(pos, doors[i], player)
-                       end
-                       break
-               end
-       end
-       return true
-end
-
-function plate.register(material, desc, def)
-       xdecor.register("pressure_"..material.."_off", {
-               description = desc.." Pressure Plate",
-               tiles = {"xdecor_pressure_"..material..".png"},
-               drawtype = "nodebox",
-               node_box = xdecor.pixelbox(16, {{1, 0, 1, 14, 1, 14}}),
-               groups = def.groups,
-               sounds = def.sounds,
-               sunlight_propagates = true,
-               on_rotate = screwdriver.rotate_simple,
-               on_construct = plate.construct,
-               on_timer = plate.timer
-       })
-       xdecor.register("pressure_"..material.."_on", {
-               tiles = {"xdecor_pressure_"..material..".png"},
-               drawtype = "nodebox",
-               node_box = xdecor.pixelbox(16, {{1, 0, 1, 14, 0.4, 14}}),
-               groups = def.groups,
-               sounds = def.sounds,
-               drop = "xdecor:pressure_"..material.."_off",
-               sunlight_propagates = true,
-               on_rotate = screwdriver.rotate_simple
-       })
-end
-
-plate.register("wood", "Wooden", {
-       sounds = default.node_sound_wood_defaults(),
-       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2}
-})
-
-plate.register("stone", "Stone", {
-       sounds = default.node_sound_stone_defaults(),
-       groups = {cracky=3, oddly_breakable_by_hand=2}
-})
-
-xdecor.register("lever_off", {
-       description = "Lever",
-       tiles = {"xdecor_lever_off.png"},
-       drawtype = "nodebox",
-       node_box = xdecor.pixelbox(16, {{2, 1, 15, 12, 14, 1}}),
-       groups = {cracky=3, oddly_breakable_by_hand=2},
-       sounds = default.node_sound_stone_defaults(),
-       sunlight_propagates = true,
-       on_rotate = screwdriver.rotate_simple,
-       on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-               if not doors.get then
-                       return itemstack
-               end
-               local minp = {x=pos.x-2, y=pos.y-1, z=pos.z-2}
-               local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
-               local doors = minetest.find_nodes_in_area(minp, maxp, "group:door")
-
-               for i = 1, #doors do
-                       door_toggle(pos, doors[i], clicker)
-               end
-               return itemstack
-       end
-})
-
-xdecor.register("lever_on", {
-       tiles = {"xdecor_lever_on.png"},
-       drawtype = "nodebox",
-       node_box = xdecor.pixelbox(16, {{2, 1, 15, 12, 14, 1}}),
-       groups = {cracky=3, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
-       sounds = default.node_sound_stone_defaults(),
-       sunlight_propagates = true,
-       on_rotate = screwdriver.rotate_simple,
-       drop = "xdecor:lever_off"
-})
-
diff --git a/nodes.lua b/nodes.lua
deleted file mode 100644 (file)
index ba1a6b4..0000000
--- a/nodes.lua
+++ /dev/null
@@ -1,475 +0,0 @@
-screwdriver = screwdriver or {}
-
-function xdecor.register_pane(name, desc, def)
-       xpanes.register_pane(name, {
-               description = desc,
-               tiles = {"xdecor_"..name..".png"},
-               drawtype = "airlike",
-               paramtype = "light",
-               textures = {"xdecor_"..name..".png", "xdecor_"..name..".png", "xpanes_space.png"},
-               inventory_image = "xdecor_"..name..".png",
-               wield_image = "xdecor_"..name..".png",
-               groups = def.groups,
-               sounds = def.sounds or default.node_sound_defaults(),
-               recipe = def.recipe
-       })
-end
-
-xdecor.register_pane("bamboo_frame", "Bamboo Frame", {
-       groups = {choppy=3, oddly_breakable_by_hand=2, pane=1, flammable=2},
-       recipe = {{"default:papyrus", "default:papyrus", "default:papyrus"},
-                 {"default:papyrus", "farming:cotton",  "default:papyrus"},
-                 {"default:papyrus", "default:papyrus", "default:papyrus"}}
-})
-
-xdecor.register_pane("chainlink", "Chainlink", {
-       groups = {cracky=3, oddly_breakable_by_hand=2, pane=1},
-       recipe = {{"default:steel_ingot", "", "default:steel_ingot"},
-                 {"", "default:steel_ingot", ""},
-                 {"default:steel_ingot", "", "default:steel_ingot"}}
-})
-
-xdecor.register_pane("rusty_bar", "Rusty Iron Bars", {
-       sounds = default.node_sound_stone_defaults(),
-       groups = {cracky=2, pane=1},
-       recipe = {{"", "default:dirt", ""},
-                 {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
-                 {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}}
-})
-
-xdecor.register_pane("wood_frame", "Wood Frame", {
-       sounds = default.node_sound_wood_defaults(),
-       groups = {choppy=2, pane=1, flammable=2},
-       recipe = {{"group:wood", "group:stick", "group:wood"},
-                 {"group:stick", "group:stick", "group:stick"},
-                 {"group:wood", "group:stick", "group:wood"}}
-})
-
-xdecor.register("baricade", {
-       description = "Baricade",
-       drawtype = "plantlike",
-       paramtype2 = "facedir",
-       inventory_image = "xdecor_baricade.png",
-       tiles = {"xdecor_baricade.png"},
-       groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2},
-       damage_per_second = 4,
-       selection_box = xdecor.nodebox.slab_y(0.3),
-       collision_box = xdecor.pixelbox(2, {{0, 0, 1, 2, 2, 0}})
-})
-
-xdecor.register("barrel", {
-       description = "Barrel",
-       tiles = {"xdecor_barrel_top.png", "xdecor_barrel_top.png", "xdecor_barrel_sides.png"},
-       on_place = minetest.rotate_node,
-       groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2},
-       sounds = default.node_sound_wood_defaults()
-})
-
-function xdecor.register_storage(name, desc, def)
-       xdecor.register(name, {
-               description = desc,
-               inventory = {size=def.inv_size or 24},
-               infotext = desc,
-               tiles = def.tiles,
-               node_box = def.node_box,
-               on_rotate = def.on_rotate,
-               on_place = def.on_place,
-               groups = def.groups or {choppy=2, oddly_breakable_by_hand=1, flammable=2},
-               sounds = default.node_sound_wood_defaults()
-       })
-end
-
-xdecor.register_storage("cabinet", "Wooden Cabinet", {
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png",
-                "xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png",
-                "xdecor_cabinet_sides.png", "xdecor_cabinet_front.png"}
-})
-
-xdecor.register_storage("cabinet_half", "Half Wooden Cabinet", {
-       inv_size = 8,
-       node_box = xdecor.nodebox.slab_y(0.5, 0.5),
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png",
-                "xdecor_half_cabinet_sides.png", "xdecor_half_cabinet_sides.png",
-                "xdecor_half_cabinet_sides.png", "xdecor_half_cabinet_front.png"}
-})
-
-xdecor.register_storage("empty_shelf", "Empty Shelf", {
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"default_wood.png", "default_wood.png^xdecor_empty_shelf.png"}
-})
-
-xdecor.register_storage("multishelf", "Multi Shelf", {
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"default_wood.png", "default_wood.png^xdecor_multishelf.png"},
-})
-
-xdecor.register("candle", {
-       description = "Candle",
-       light_source = 12,
-       drawtype = "torchlike",
-       inventory_image = "xdecor_candle_inv.png",
-       wield_image = "xdecor_candle_wield.png",
-       paramtype2 = "wallmounted",
-       walkable = false,
-       groups = {dig_immediate=3, attached_node=1},
-       tiles = {{name = "xdecor_candle_floor.png",
-                       animation = {type="vertical_frames", length=1.5}},
-               {name = "xdecor_candle_floor.png",
-                       animation = {type="vertical_frames", length=1.5}},
-               {name = "xdecor_candle_wall.png",
-                       animation = {type="vertical_frames", length=1.5}}
-       },
-       selection_box = {
-               type = "wallmounted",
-               wall_top = {-0.25, -0.5, -0.25, 0.25, 0.1, 0.25},
-               wall_bottom = {-0.25, -0.5, -0.25, 0.25, 0.1, 0.25},
-               wall_side = {-0.5, -0.35, -0.15, -0.15, 0.4, 0.15}
-       }
-})
-
-xdecor.register("chair", {
-       description = "Chair",
-       tiles = {"xdecor_wood.png"},
-       sounds = default.node_sound_wood_defaults(),
-       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2},
-       on_rotate = screwdriver.rotate_simple,
-       node_box = xdecor.pixelbox(16, {
-               {3,  0, 11,   2, 16, 2}, {11, 0, 11,  2, 16, 2},
-               {5,  9, 11.5, 6,  6, 1}, {3,  0,  3,  2,  6, 2},
-               {11, 0,  3,   2,  6, 2}, {3,  6,  3, 10, 2, 8}
-       }),
-       can_dig = xdecor.sit_dig,
-       on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-               pos.y = pos.y + 0  -- Sitting position.
-               xdecor.sit(pos, node, clicker, pointed_thing)
-               return itemstack
-       end
-})
-
-xdecor.register("cobweb", {
-       description = "Cobweb",
-       drawtype = "plantlike",
-       tiles = {"xdecor_cobweb.png"},
-       inventory_image = "xdecor_cobweb.png",
-       liquid_viscosity = 8,
-       liquidtype = "source",
-       liquid_alternative_flowing = "xdecor:cobweb",
-       liquid_alternative_source = "xdecor:cobweb",
-       liquid_renewable = false,
-       liquid_range = 0,
-       walkable = false,
-       selection_box = {type = "regular"},
-       groups = {snappy=3, liquid=3, flammable=3},
-       sounds = default.node_sound_leaves_defaults()
-})
-
-for _, c in pairs({"red"}) do  -- Add more curtains colors simply here.
-       xdecor.register("curtain_"..c, {
-               description = c:gsub("^%l", string.upper).." Curtain",
-               walkable = false,
-               tiles = {"wool_white.png^[colorize:"..c..":170"},
-               inventory_image = "wool_white.png^[colorize:"..c..":170^xdecor_curtain_open_overlay.png^[makealpha:255,126,126",
-               wield_image = "wool_white.png^[colorize:"..c..":170",
-               drawtype = "signlike",
-               paramtype2 = "wallmounted",
-               groups = {dig_immediate=3, flammable=3},
-               selection_box = {type="wallmounted"},
-               on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-                       minetest.set_node(pos, {name="xdecor:curtain_open_"..c, param2=node.param2})
-                       return itemstack
-               end
-       })
-
-       xdecor.register("curtain_open_"..c, {
-               tiles = {"wool_white.png^[colorize:"..c..":170^xdecor_curtain_open_overlay.png^[makealpha:255,126,126"},
-               drawtype = "signlike",
-               paramtype2 = "wallmounted",
-               walkable = false,
-               groups = {dig_immediate=3, flammable=3, not_in_creative_inventory=1},
-               selection_box = {type="wallmounted"},
-               drop = "xdecor:curtain_"..c,
-               on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-                       minetest.set_node(pos, {name="xdecor:curtain_"..c, param2=node.param2})
-                       return itemstack
-               end
-       })
-
-       minetest.register_craft({
-               output = "xdecor:curtain_"..c.." 4",
-               recipe = { {"", "wool:"..c, ""},
-                          {"", "wool:"..c, ""} }
-       })
-end
-
-xdecor.register("cushion", {
-       description = "Cushion",
-       tiles = {"xdecor_cushion.png"},
-       groups = {snappy=3, flammable=3, fall_damage_add_percent=-50},
-       on_place = minetest.rotate_node,
-       node_box = xdecor.nodebox.slab_y(0.5),
-       can_dig = xdecor.sit_dig,
-       on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-               pos.y = pos.y + 0  -- Sitting position.
-               xdecor.sit(pos, node, clicker, pointed_thing)
-               return itemstack
-       end
-})
-
-xdecor.register("cushion_block", {
-       description = "Cushion Block",
-       tiles = {"xdecor_cushion.png"},
-       groups = {snappy=3, flammable=3, fall_damage_add_percent=-75, not_in_creative_inventory=1}
-})
-
-local function door_access(name) return name:find("prison") end
-local xdecor_doors = {
-       japanese = {
-               {"group:wood", "default:paper"},
-               {"default:paper", "group:wood"},
-               {"group:wood", "default:paper"} },
-       prison = {
-               {"xpanes:bar_flat", "xpanes:bar_flat",},
-               {"xpanes:bar_flat", "xpanes:bar_flat",},
-               {"xpanes:bar_flat", "xpanes:bar_flat"} },
-       rusty_prison = {
-               {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat",},
-               {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat",},
-               {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat"} },
-       screen = {
-               {"group:wood", "group:wood"},
-               {"xpanes:chainlink_flat", "xpanes:chainlink_flat"},
-               {"group:wood", "group:wood"} },
-       slide = {
-               {"default:paper", "default:paper"},
-               {"default:paper", "default:paper"},
-               {"group:wood", "group:wood"} },
-       woodglass = {
-               {"default:glass", "default:glass"},
-               {"group:wood", "group:wood"},
-               {"group:wood", "group:wood"} }
-}
-
-for name, recipe in pairs(xdecor_doors) do
-       if not doors.register then break end
-       doors.register(name.."_door", {
-               tiles = {{name = "xdecor_"..name.."_door.png", backface_culling=true}},
-               description = name:gsub("%f[%w]%l", string.upper):gsub("_", " ").." Door",
-               inventory_image = "xdecor_"..name.."_door_inv.png",
-               protected = door_access(name),
-               groups = {choppy=2, cracky=2, oddly_breakable_by_hand=1, door=1},
-               recipe = recipe
-       })
-end
-
-xdecor.register("enderchest", {
-       description = "Ender Chest",
-       tiles = {"xdecor_enderchest_top.png", "xdecor_enderchest_top.png",
-                "xdecor_enderchest_side.png", "xdecor_enderchest_side.png",
-                "xdecor_enderchest_side.png", "xdecor_enderchest_front.png"},
-       groups = {cracky=1, choppy=1},
-       sounds = default.node_sound_stone_defaults(),
-       on_rotate = screwdriver.rotate_simple,
-       on_construct = function(pos)
-               local meta = minetest.get_meta(pos)
-               meta:set_string("formspec", [[ size[8,9]
-                               list[current_player;enderchest;0,0;8,4;]
-                               list[current_player;main;0,5;8,4;]
-                               listring[current_player;enderchest]
-                               listring[current_player;main] ]]
-                               ..xbg..default.get_hotbar_bg(0,5))
-               meta:set_string("infotext", "Ender Chest")
-       end
-})
-
-minetest.register_on_joinplayer(function(player)
-       local inv = player:get_inventory()
-       inv:set_size("enderchest", 8*4)
-end)
-
-xdecor.register("ivy", {
-       description = "Ivy",
-       drawtype = "signlike",
-       walkable = false,
-       climbable = true,
-       groups = {snappy=3, flora=1, attached_node=1, plant=1, flammable=3},
-       paramtype2 = "wallmounted",
-       selection_box = {type="wallmounted"},
-       tiles = {"xdecor_ivy.png"},
-       inventory_image = "xdecor_ivy.png",
-       wield_image = "xdecor_ivy.png",
-       sounds = default.node_sound_leaves_defaults()
-})
-
-xdecor.register("lantern", {
-       description = "Lantern",
-       light_source = 13,
-       drawtype = "plantlike",
-       inventory_image = "xdecor_lantern_inv.png",
-       wield_image = "xdecor_lantern_inv.png",
-       paramtype2 = "wallmounted",
-       walkable = false,
-       groups = {snappy=3, attached_node=1},
-       tiles = {{name = "xdecor_lantern.png", animation = {type="vertical_frames", length=1.5}}},
-       selection_box = xdecor.pixelbox(16, {{4, 0, 4, 8, 16, 8}})
-})
-
-for _, l in pairs({"iron", "wooden"}) do
-       xdecor.register(l.."_lightbox", {
-               description = l:gsub("^%l", string.upper).." Light Box",
-               tiles = {"xdecor_"..l.."_lightbox.png"},
-               groups = {cracky=3, choppy=3, oddly_breakable_by_hand=2},
-               light_source = 13,
-               sounds = default.node_sound_glass_defaults()
-       })
-end
-
-for _, f in pairs({"dandelion_white", "dandelion_yellow", "geranium",
-               "rose", "tulip", "viola"}) do
-       xdecor.register("potted_"..f, {
-               description = "Potted "..f:gsub("%f[%w]%l", string.upper):gsub("_", " "),
-               walkable = false,
-               groups = {snappy=3, flammable=3, plant=1, flower=1},
-               tiles = {"xdecor_"..f.."_pot.png"},
-               inventory_image = "xdecor_"..f.."_pot.png",
-               drawtype = "plantlike",
-               sounds = default.node_sound_leaves_defaults(),
-               selection_box = xdecor.nodebox.slab_y(0.3)
-       })
-
-       minetest.register_craft({
-               output = "xdecor:potted_"..f,
-               recipe = { {"default:clay_brick", "flowers:"..f, "default:clay_brick"},
-                          {"", "default:clay_brick", ""} }
-       })
-end
-
-local painting_box = {
-       type = "wallmounted",
-       wall_top = {-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125},
-       wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125},
-       wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375}
-}
-
-xdecor.register("painting_1", {
-       description = "Painting",
-       tiles = {"xdecor_painting_1.png"},
-       inventory_image = "xdecor_painting_empty.png",
-       wield_image = "xdecor_painting_empty.png",
-       paramtype2 = "wallmounted",
-       sunlight_propagates = true,
-       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2, attached_node=1},
-       sounds = default.node_sound_wood_defaults(),
-       node_box = painting_box,
-       node_placement_prediction = "",
-       on_place = function(itemstack, placer, pointed_thing)
-               local num = math.random(4)
-               local leftover = minetest.item_place_node(ItemStack("xdecor:painting_"..num), placer, pointed_thing)
-               if leftover:get_count() == 0 and not minetest.setting_getbool("creative_mode") then
-                       itemstack:take_item()
-               end
-               return itemstack
-       end
-})
-
-for i = 2, 4 do
-       xdecor.register("painting_"..i, {
-               tiles = {"xdecor_painting_"..i..".png"},
-               paramtype2 = "wallmounted",
-               drop = "xdecor:painting_1",
-               sunlight_propagates = true,
-               groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2, attached_node=1, not_in_creative_inventory=1},
-               sounds = default.node_sound_wood_defaults(),
-               node_box = painting_box
-       })
-end
-
-xdecor.register("stonepath", {
-       description = "Garden Stone Path",
-       tiles = {"default_stone.png"},
-       groups = {snappy=3},
-       on_rotate = screwdriver.rotate_simple,
-       sounds = default.node_sound_stone_defaults(),
-       sunlight_propagates = true,
-       node_box = xdecor.pixelbox(16, {
-               {8, 0,  8, 6, .5, 6}, {1,  0, 1, 6, .5, 6},
-               {1, 0, 10, 5, .5, 5}, {10, 0, 2, 4, .5, 4}
-       }),
-       selection_box = xdecor.nodebox.slab_y(0.05)
-})
-
-function xdecor.register_hard_node(name, desc, def)
-       xdecor.register(name, {
-               description = desc,
-               tiles = {"xdecor_"..name..".png"},
-               groups = def.groups or {cracky=1},
-               sounds = def.sounds or default.node_sound_stone_defaults()
-       })
-end
-
-xdecor.register_hard_node("cactusbrick", "Cactus Brick", {})
-xdecor.register_hard_node("coalstone_tile", "Coal Stone Tile", {})
-xdecor.register_hard_node("desertstone_tile", "Desert Stone Tile", {})
-xdecor.register_hard_node("hard_clay", "Hardened Clay", {})
-xdecor.register_hard_node("moonbrick", "Moon Brick", {})
-xdecor.register_hard_node("stone_tile", "Stone Tile", {})
-xdecor.register_hard_node("stone_rune", "Runestone", {})
-xdecor.register_hard_node("packed_ice", "Packed Ice", {
-       groups = {cracky=1, puts_out_fire=1},
-       sounds = default.node_sound_glass_defaults()
-})
-xdecor.register_hard_node("wood_tile", "Wooden Tile", {
-       groups = {choppy=1, wood=1, flammable=2},
-       sounds = default.node_sound_wood_defaults()
-})
-
-xdecor.register("table", {
-       description = "Table",
-       tiles = {"xdecor_wood.png"},
-       groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2},
-       sounds = default.node_sound_wood_defaults(),
-       node_box = xdecor.pixelbox(16, {
-               {0, 14, 0, 16, 2, 16}, {5.5, 0, 5.5, 5, 14, 6}
-       })
-})
-
-xdecor.register("tatami", {
-       description = "Tatami",
-       tiles = {"xdecor_tatami.png"},
-       wield_image = "xdecor_tatami.png",
-       groups = {snappy=3, flammable=3},
-       sunlight_propagates = true,
-       node_box = xdecor.nodebox.slab_y(0.0625)
-})
-
-xdecor.register("trampoline", {
-       description = "Trampoline",
-       tiles = {"xdecor_trampoline.png", "mailbox_blank16.png", "xdecor_trampoline_sides.png"},
-       groups = {cracky=3, oddly_breakable_by_hand=1, fall_damage_add_percent=-80, bouncy=90},
-       node_box = xdecor.nodebox.slab_y(0.5),
-       sounds = {footstep = {name="xdecor_bouncy", gain=0.8}}
-})
-
-xdecor.register("tv", {
-       description = "Television",
-       light_source = 11,
-       groups = {cracky=3, oddly_breakable_by_hand=2},
-       on_rotate = screwdriver.rotate_simple,
-       tiles = {"xdecor_television_left.png^[transformR270",
-                "xdecor_television_left.png^[transformR90",
-                "xdecor_television_left.png^[transformFX",
-                "xdecor_television_left.png", "xdecor_television_back.png",
-               {name="xdecor_television_front_animated.png",
-                animation = {type="vertical_frames", length=80.0}} }
-})
-
-xdecor.register("woodframed_glass", {
-       description = "Wood Framed Glass",
-       drawtype = "glasslike_framed",
-       sunlight_propagates = true,
-       tiles = {"xdecor_woodframed_glass.png", "xdecor_woodframed_glass_detail.png"},
-       groups = {cracky=2, oddly_breakable_by_hand=1},
-       sounds = default.node_sound_glass_defaults()
-})
-
diff --git a/recipes.lua b/recipes.lua
deleted file mode 100644 (file)
index 85af033..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-minetest.register_craft({
-       output = "xdecor:baricade",
-       recipe = {
-               {"group:stick", "", "group:stick"},
-               {"", "default:steel_ingot", ""},
-               {"group:stick", "", "group:stick"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:barrel",
-       recipe = {
-               {"group:wood", "group:wood", "group:wood"},
-               {"default:iron_lump", "", "default:iron_lump"},
-               {"group:wood", "group:wood", "group:wood"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:bowl 3",
-       recipe = {
-               {"group:wood", "", "group:wood"},
-               {"", "group:wood", ""}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:candle",
-       recipe = {
-               {"default:torch"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:cabinet",
-       recipe = {
-               {"group:wood", "group:wood", "group:wood"},
-               {"doors:trapdoor", "", "doors:trapdoor"},
-               {"group:wood", "group:wood", "group:wood"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:cabinet_half 2",
-       recipe = {
-               {"xdecor:cabinet"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:cactusbrick",
-       recipe = {
-               {"default:brick", "default:cactus"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:cauldron_empty",
-       recipe = {
-               {"default:iron_lump", "", "default:iron_lump"},
-               {"default:iron_lump", "", "default:iron_lump"},
-               {"default:iron_lump", "default:iron_lump", "default:iron_lump"}
-       }
-})
-
-minetest.register_craft({
-       output = "realchess:chessboard",
-       recipe = {
-               {"dye:black", "dye:white", "dye:black"},
-               {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:chair",
-       recipe = {
-               {"group:stick", "", ""},
-               {"group:stick", "group:stick", "group:stick"},
-               {"group:stick", "", "group:stick"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:coalstone_tile 4",
-       recipe = {
-               {"default:coalblock", "default:stone"},
-               {"default:stone", "default:coalblock"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:cobweb",
-       recipe = {
-               {"farming:cotton", "", "farming:cotton"},
-               {"", "farming:cotton", ""},
-               {"farming:cotton", "", "farming:cotton"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:crafting_guide",
-       type = "shapeless",
-       recipe = {"default:book"}
-})
-
-minetest.register_craft({
-       output = "xdecor:cushion 3",
-       recipe = {
-               {"wool:red", "wool:red", "wool:red"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:cushion_block",
-       recipe = {
-               {"xdecor:cushion"},
-               {"xdecor:cushion"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:desertstone_tile",
-       recipe = {
-               {"default:desert_cobble", "default:desert_cobble"},
-               {"default:desert_cobble", "default:desert_cobble"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:empty_shelf",
-       recipe = {
-               {"group:wood", "group:wood", "group:wood"},
-               {"", "", ""},
-               {"group:wood", "group:wood", "group:wood"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:enderchest",
-       recipe = {
-               {"", "default:obsidian", ""},
-               {"default:obsidian", "default:chest", "default:obsidian"},
-               {"", "default:obsidian", ""}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:enchantment_table",
-       recipe = {
-               {"", "default:book", ""},
-               {"default:diamond", "default:obsidian", "default:diamond"},
-               {"default:obsidian", "default:obsidian", "default:obsidian"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:itemframe",
-       recipe = {
-               {"group:stick", "group:stick", "group:stick"},
-               {"group:stick", "default:paper", "group:stick"},
-               {"group:stick", "group:stick", "group:stick"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:hammer",
-       recipe = {
-               {"default:steel_ingot", "group:stick", "default:steel_ingot"},
-               {"", "group:stick", ""}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:hard_clay",
-       recipe = {
-               {"default:clay", "default:clay"},
-               {"default:clay", "default:clay"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:hive",
-       recipe = {
-               {"group:stick", "group:stick", "group:stick"},
-               {"default:paper", "default:paper", "default:paper"},
-               {"group:stick", "group:stick", "group:stick"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:iron_lightbox",
-       recipe = {
-               {"xpanes:bar_flat", "default:torch", "xpanes:bar_flat"},
-               {"xpanes:bar_flat", "default:glass", "xpanes:bar_flat"},
-               {"xpanes:bar_flat", "default:torch", "xpanes:bar_flat"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:ivy 4",
-       recipe = {
-               {"group:leaves"},
-               {"group:leaves"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:lantern",
-       recipe = {
-               {"default:iron_lump"},
-               {"default:torch"},
-               {"default:iron_lump"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:lever_off",
-       recipe = {
-               {"group:stick"},
-               {"group:stone"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:mailbox",
-       recipe = {
-               {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
-               {"dye:red", "default:paper", "dye:red"},
-               {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:moonbrick",
-       recipe = {
-               {"default:brick", "default:stone"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:multishelf",
-       recipe = {
-               {"group:wood", "group:wood", "group:wood"},
-               {"group:vessel", "group:book", "group:vessel"},
-               {"group:wood", "group:wood", "group:wood"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:packed_ice",
-       recipe = {
-               {"default:ice", "default:ice"},
-               {"default:ice", "default:ice"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:painting_1",
-       recipe = {
-               {"default:sign_wall_wood", "dye:blue"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:pressure_stone_off",
-       type = "shapeless",
-       recipe = {"group:stone", "group:stone"}
-})
-
-minetest.register_craft({
-       output = "xdecor:pressure_wood_off",
-       type = "shapeless",
-       recipe = {"group:wood", "group:wood"}
-})
-
-minetest.register_craft({
-       output = "xdecor:rope",
-       recipe = {
-               {"farming:string"},
-               {"farming:string"},
-               {"farming:string"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:stone_tile 2",
-       recipe = {
-               {"default:cobble", "default:cobble"},
-               {"default:cobble", "default:cobble"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:stone_rune 4",
-       recipe = {
-               {"default:stone", "default:stone", "default:stone"},
-               {"default:stone", "", "default:stone"},
-               {"default:stone", "default:stone", "default:stone"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:stonepath 16",
-       recipe = {
-               {"stairs:slab_cobble", "", "stairs:slab_cobble"},
-               {"", "stairs:slab_cobble", ""},
-               {"stairs:slab_cobble", "", "stairs:slab_cobble"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:table",
-       recipe = {
-               {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"},
-               {"", "group:stick", ""},
-               {"", "group:stick", ""}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:tatami",
-       recipe = {
-               {"farming:wheat", "farming:wheat", "farming:wheat"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:trampoline",
-       recipe = {
-               {"farming:string", "farming:string", "farming:string"},
-               {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
-               {"default:steel_ingot", "", "default:steel_ingot"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:tv",
-       recipe = {
-               {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"},
-               {"default:steel_ingot", "default:glass", "default:steel_ingot"},
-               {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:workbench",
-       recipe = {
-               {"group:wood", "group:wood"},
-               {"group:wood", "group:wood"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:woodframed_glass",
-       recipe = {
-               {"group:stick", "group:stick", "group:stick"},
-               {"group:stick", "default:glass", "group:stick"},
-               {"group:stick", "group:stick", "group:stick"}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:wood_tile 2",
-       recipe = {
-               {"", "group:wood", ""},
-               {"group:wood", "", "group:wood"},
-               {"", "group:wood", ""}
-       }
-})
-
-minetest.register_craft({
-       output = "xdecor:wooden_lightbox",
-       recipe = {
-               {"group:stick", "default:torch", "group:stick"},
-               {"group:stick", "default:glass", "group:stick"},
-               {"group:stick", "default:torch", "group:stick"}
-       }
-})
-
diff --git a/rope.lua b/rope.lua
deleted file mode 100644 (file)
index 1627fd8..0000000
--- a/rope.lua
+++ /dev/null
@@ -1,57 +0,0 @@
-local rope = {}
-
--- Code by Mirko K. (modified by Temperest, Wulfsdad and kilbith) (License: GPL).
-function rope.place(itemstack, placer, pointed_thing)
-       if pointed_thing.type == "node" then
-               local pos = pointed_thing.above
-               local oldnode = minetest.get_node(pos)
-               local stackname = itemstack:get_name()
-               if minetest.is_protected(pos, placer:get_player_name()) then
-                       return itemstack
-               end
-
-               while oldnode.name == "air" and not itemstack:is_empty() do
-                       local newnode = {name = stackname, param1 = 0}
-                       minetest.set_node(pos, newnode)
-                       itemstack:take_item()
-                       pos.y = pos.y - 1
-                       oldnode = minetest.get_node(pos)
-               end
-       end
-       return itemstack
-end
-
-function rope.remove(pos, oldnode, digger, rope_name)
-       local num = 0
-       local below = {x=pos.x, y=pos.y, z=pos.z}
-       local digger_inv = digger:get_inventory()
-
-       while minetest.get_node(below).name == rope_name do
-               minetest.remove_node(below)
-               below.y = below.y - 1
-               num = num + 1
-       end
-       if num == 0 then return end
-       digger_inv:add_item("main", rope_name.." "..num)
-       return true
-end
-
-xdecor.register("rope", {
-       description = "Rope",
-       drawtype = "plantlike",
-       walkable = false,
-       climbable = true,
-       groups = {snappy=3, flammable=3},
-       tiles = {"xdecor_rope.png"},
-       inventory_image = "xdecor_rope_inv.png",
-       wield_image = "xdecor_rope_inv.png",
-       selection_box = xdecor.pixelbox(8, {{3, 0, 3, 2, 8, 2}}),
-       on_place = rope.place,
-       on_punch = function(pos, node, puncher, pointed_thing)
-               local player_name = puncher:get_player_name()
-               if not minetest.is_protected(pos, player_name) or
-                       minetest.get_player_privs(player_name).protection_bypass then
-                       rope.remove(pos, node, puncher, "xdecor:rope")
-               end
-       end
-})
diff --git a/src/chess.lua b/src/chess.lua
new file mode 100644 (file)
index 0000000..6de09cc
--- /dev/null
@@ -0,0 +1,628 @@
+local realchess = {}
+screwdriver = screwdriver or {}
+
+local function index_to_xy(idx)
+       idx = idx - 1
+       local x = idx % 8
+       local y = (idx - x) / 8
+       return x, y
+end
+
+local function xy_to_index(x, y)
+       return x + y * 8 + 1
+end
+
+function realchess.init(pos)
+       local meta = minetest.get_meta(pos)
+       local inv = meta:get_inventory()
+       
+       local formspec = [[ size[8,8.6;]
+                       bgcolor[#080808BB;true]
+                       background[0,0;8,8;chess_bg.png]
+                       button[3.1,7.8;2,2;new;New game]
+                       list[context;board;0,0;8,8;]
+                       listcolors[#00000000;#00000000;#00000000;#30434C;#FFF] ]]
+
+       meta:set_string("formspec", formspec)
+       meta:set_string("infotext", "Chess Board")
+       meta:set_string("playerBlack", "")
+       meta:set_string("playerWhite", "")
+       meta:set_string("lastMove", "")
+       meta:set_string("winner", "")
+
+       meta:set_int("lastMoveTime", 0)
+       meta:set_int("castlingBlackL", 1)
+       meta:set_int("castlingBlackR", 1)
+       meta:set_int("castlingWhiteL", 1)
+       meta:set_int("castlingWhiteR", 1)
+
+       inv:set_list("board", {
+               "realchess:rook_black_1",
+               "realchess:knight_black_1",
+               "realchess:bishop_black_1",
+               "realchess:queen_black",
+               "realchess:king_black",
+               "realchess:bishop_black_2",
+               "realchess:knight_black_2",
+               "realchess:rook_black_2",
+               "realchess:pawn_black_1",
+               "realchess:pawn_black_2",
+               "realchess:pawn_black_3",
+               "realchess:pawn_black_4",
+               "realchess:pawn_black_5",
+               "realchess:pawn_black_6",
+               "realchess:pawn_black_7",
+               "realchess:pawn_black_8",
+               '','','','','','','','','','','','','','','','',
+               '','','','','','','','','','','','','','','','',
+               "realchess:pawn_white_1",
+               "realchess:pawn_white_2",
+               "realchess:pawn_white_3",
+               "realchess:pawn_white_4",
+               "realchess:pawn_white_5",
+               "realchess:pawn_white_6",
+               "realchess:pawn_white_7",
+               "realchess:pawn_white_8",
+               "realchess:rook_white_1",
+               "realchess:knight_white_1",
+               "realchess:bishop_white_1",
+               "realchess:queen_white",
+               "realchess:king_white",
+               "realchess:bishop_white_2",
+               "realchess:knight_white_2",
+               "realchess:rook_white_2"
+       })
+
+       inv:set_size("board", 64)
+end
+
+function realchess.move(pos, from_list, from_index, to_list, to_index, _, player)
+       if from_list ~= "board" and to_list ~= "board" then
+               return 0
+       end
+
+       local playerName = player:get_player_name()
+       local meta = minetest.get_meta(pos)
+
+       if meta:get_string("winner") ~= "" then
+               minetest.chat_send_player(playerName, "This game is over.")
+               return 0
+       end
+
+       local inv = meta:get_inventory()
+       local pieceFrom = inv:get_stack(from_list, from_index):get_name()
+       local pieceTo = inv:get_stack(to_list, to_index):get_name()
+       local lastMove = meta:get_string("lastMove")
+       local thisMove -- will replace lastMove when move is legal
+       local playerWhite = meta:get_string("playerWhite")
+       local playerBlack = meta:get_string("playerBlack")
+
+       if pieceFrom:find("white") then
+               if playerWhite ~= "" and playerWhite ~= playerName then
+                       minetest.chat_send_player(playerName, "Someone else plays white pieces!")
+                       return 0
+               end             
+               if lastMove ~= "" and lastMove ~= "black" then
+                       minetest.chat_send_player(playerName, "It's not your turn, wait for your opponent to play.")
+                       return 0
+               end
+               if pieceTo:find("white") then
+                       -- Don't replace pieces of same color
+                       return 0
+               end
+               playerWhite = playerName
+               thisMove = "white"
+       elseif pieceFrom:find("black") then
+               if playerBlack ~= "" and playerBlack ~= playerName then
+                       minetest.chat_send_player(playerName, "Someone else plays black pieces!")
+                       return 0
+               end
+               if lastMove ~= "" and lastMove ~= "white" then
+                       minetest.chat_send_player(playerName, "It's not your turn, wait for your opponent to play.")
+                       return 0
+               end
+               if pieceTo:find("black") then
+                       -- Don't replace pieces of same color
+                       return 0
+               end
+               playerBlack = playerName
+               thisMove = "black"
+       end
+
+       -- DETERMINISTIC MOVING
+
+       local from_x, from_y = index_to_xy(from_index)
+       local to_x, to_y = index_to_xy(to_index)
+
+       if pieceFrom:sub(11,14) == "pawn" then
+               if thisMove == "white" then
+                       local pawnWhiteMove = inv:get_stack(from_list, xy_to_index(from_x, from_y - 1)):get_name()
+                       -- white pawns can go up only
+                       if from_y - 1 == to_y then
+                               if from_x == to_x then
+                                       if pieceTo ~= "" then
+                                               return 0
+                                       elseif to_index >= 1 and to_index <= 8 then
+                                               inv:set_stack(from_list, from_index, "realchess:queen_white")
+                                       end
+                               elseif from_x - 1 == to_x or from_x + 1 == to_x then
+                                       if not pieceTo:find("black") then
+                                               return 0
+                                       elseif to_index >= 1 and to_index <= 8 then
+                                               inv:set_stack(from_list, from_index, "realchess:queen_white")
+                                       end
+                               else
+                                       return 0
+                               end
+                       elseif from_y - 2 == to_y then
+                               if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then
+                                       return 0
+                               end
+                       else
+                               return 0
+                       end
+               elseif thisMove == "black" then
+                       local pawnBlackMove = inv:get_stack(from_list, xy_to_index(from_x, from_y + 1)):get_name()
+                       -- black pawns can go down only
+                       if from_y + 1 == to_y then
+                               if from_x == to_x then
+                                       if pieceTo ~= "" then
+                                               return 0
+                                       elseif to_index >= 57 and to_index <= 64 then
+                                               inv:set_stack(from_list, from_index, "realchess:queen_black")
+                                       end
+                               elseif from_x - 1 == to_x or from_x + 1 == to_x then
+                                       if not pieceTo:find("white") then
+                                               return 0
+                                       elseif to_index >= 57 and to_index <= 64 then
+                                               inv:set_stack(from_list, from_index, "realchess:queen_black")
+                                       end
+                               else
+                                       return 0
+                               end
+                       elseif from_y + 2 == to_y then
+                               if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then
+                                       return 0
+                               end
+                       else
+                               return 0
+                       end
+
+                       -- if x not changed,
+                       --   ensure that destination cell is empty
+                       -- elseif x changed one unit left or right
+                       --   ensure the pawn is killing opponent piece
+                       -- else
+                       --   move is not legal - abort
+
+                       if from_x == to_x then
+                               if pieceTo ~= "" then
+                                       return 0
+                               end
+                       elseif from_x - 1 == to_x or from_x + 1 == to_x then
+                               if not pieceTo:find("white") then
+                                       return 0
+                               end
+                       else
+                               return 0
+                       end
+               else
+                       return 0
+               end
+
+       elseif pieceFrom:sub(11,14) == "rook" then
+               if from_x == to_x then
+                       -- moving vertically
+                       if from_y < to_y then
+                               -- moving down
+                               -- ensure that no piece disturbs the way
+                               for i = from_y + 1, to_y - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- mocing up
+                               -- ensure that no piece disturbs the way
+                               for i = to_y + 1, from_y - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x, i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end
+               elseif from_y == to_y then
+                       -- mocing horizontally
+                       if from_x < to_x then
+                               -- mocing right
+                               -- ensure that no piece disturbs the way
+                               for i = from_x + 1, to_x - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- mocing left
+                               -- ensure that no piece disturbs the way
+                               for i = to_x + 1, from_x - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(i, from_y)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end
+               else
+                       -- attempt to move arbitrarily -> abort
+                       return 0
+               end
+
+               if thisMove == "white" or thisMove == "black" then
+                       if pieceFrom:sub(-1) == "1" then
+                               meta:set_int("castlingWhiteL", 0)
+                       elseif pieceFrom:sub(-1) == "2" then
+                               meta:set_int("castlingWhiteR", 0)
+                       end
+               end
+
+       elseif pieceFrom:sub(11,16) == "knight" then
+               -- get relative pos
+               local dx = from_x - to_x
+               local dy = from_y - to_y
+
+               -- get absolute values
+               if dx < 0 then dx = -dx end
+               if dy < 0 then dy = -dy end
+
+               -- sort x and y
+               if dx > dy then dx, dy = dy, dx end
+
+               -- ensure that dx == 1 and dy == 2
+               if dx ~= 1 or dy ~= 2 then
+                       return 0
+               end
+               -- just ensure that destination cell does not contain friend piece
+               -- ^ it was done already thus everything ok
+
+       elseif pieceFrom:sub(11,16) == "bishop" then
+               -- get relative pos
+               local dx = from_x - to_x
+               local dy = from_y - to_y
+
+               -- get absolute values
+               if dx < 0 then dx = -dx end
+               if dy < 0 then dy = -dy end
+
+               -- ensure dx and dy are equal
+               if dx ~= dy then return 0 end
+
+               if from_x < to_x then
+                       if from_y < to_y then
+                               -- moving right-down
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y + i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- moving right-up
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y - i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end
+               else
+                       if from_y < to_y then
+                               -- moving left-down
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y + i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- moving left-up
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y - i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end
+               end
+
+       elseif pieceFrom:sub(11,15) == "queen" then
+               local dx = from_x - to_x
+               local dy = from_y - to_y
+
+               -- get absolute values
+               if dx < 0 then dx = -dx end
+               if dy < 0 then dy = -dy end
+
+               -- ensure valid relative move
+               if dx ~= 0 and dy ~= 0 and dx ~= dy then
+                       return 0
+               end
+
+               if from_x == to_x then
+                       if from_y < to_y then
+                               -- goes down
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x, from_y + i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- goes up
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x, from_y - i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end             
+               elseif from_x < to_x then
+                       if from_y == to_y then
+                               -- goes right
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       elseif from_y < to_y then
+                               -- goes right-down
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y + i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- goes right-up
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x + i, from_y - i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end                             
+               else
+                       if from_y == to_y then
+                               -- goes left
+                               -- ensure that no piece disturbs the way and destination cell does
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       elseif from_y < to_y then
+                               -- goes left-down
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y + i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       else
+                               -- goes left-up
+                               -- ensure that no piece disturbs the way
+                               for i = 1, dx - 1 do
+                                       if inv:get_stack(from_list, xy_to_index(from_x - i, from_y - i)):get_name() ~= "" then
+                                               return 0
+                                       end
+                               end
+                       end             
+               end
+
+       elseif pieceFrom:sub(11,14) == "king" then
+               local dx = from_x - to_x
+               local dy = from_y - to_y
+               local check = true
+               
+               if thisMove == "white" then
+                       if from_y == 7 and to_y == 7 then
+                               if to_x == 1 then
+                                       local castlingWhiteL = meta:get_int("castlingWhiteL")
+                                       local idx57 = inv:get_stack(from_list, 57):get_name()
+
+                                       if castlingWhiteL == 1 and idx57 == "realchess:rook_white_1" then
+                                               for i = 58, from_index - 1 do
+                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
+                                                               return 0
+                                                       end
+                                               end
+                                               inv:set_stack(from_list, 57, "")
+                                               inv:set_stack(from_list, 59, "realchess:rook_white_1")
+                                               check = false
+                                       end
+                               elseif to_x == 6 then
+                                       local castlingWhiteR = meta:get_int("castlingWhiteR")
+                                       local idx64 = inv:get_stack(from_list, 64):get_name()
+
+                                       if castlingWhiteR == 1 and idx64 == "realchess:rook_white_2" then
+                                               for i = from_index + 1, 63 do
+                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
+                                                               return 0
+                                                       end
+                                               end
+                                               inv:set_stack(from_list, 62, "realchess:rook_white_2")
+                                               inv:set_stack(from_list, 64, "")
+                                               check = false
+                                       end
+                               end
+                       end
+               elseif thisMove == "black" then
+                       if from_y == 0 and to_y == 0 then
+                               if to_x == 1 then
+                                       local castlingBlackL = meta:get_int("castlingBlackL")
+                                       local idx1 = inv:get_stack(from_list, 1):get_name()
+
+                                       if castlingBlackL == 1 and idx1 == "realchess:rook_black_1" then
+                                               for i = 2, from_index - 1 do
+                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
+                                                               return 0
+                                                       end
+                                               end
+                                               inv:set_stack(from_list, 1, "")
+                                               inv:set_stack(from_list, 3, "realchess:rook_black_1")
+                                               check = false
+                                       end
+                               elseif to_x == 6 then
+                                       local castlingBlackR = meta:get_int("castlingBlackR")
+                                       local idx8 = inv:get_stack(from_list, 1):get_name()
+
+                                       if castlingBlackR == 1 and idx8 == "realchess:rook_black_2" then
+                                               for i = from_index + 1, 7 do
+                                                       if inv:get_stack(from_list, i):get_name() ~= "" then
+                                                               return 0
+                                                       end
+                                               end
+                                               inv:set_stack(from_list, 6, "realchess:rook_black_2")
+                                               inv:set_stack(from_list, 8, "")
+                                               check = false
+                                       end
+                               end
+                       end
+               end
+
+               if check then
+                       if dx < 0 then dx = -dx end
+                       if dy < 0 then dy = -dy end
+                       if dx > 1 or dy > 1 then return 0 end
+               end
+               
+               if thisMove == "white" then
+                       meta:set_int("castlingWhiteL", 0)
+                       meta:set_int("castlingWhiteR", 0)
+               elseif thisMove == "black" then
+                       meta:set_int("castlingBlackL", 0)               
+                       meta:set_int("castlingBlackR", 0)
+               end
+       end
+
+       meta:set_string("playerWhite", playerWhite)
+       meta:set_string("playerBlack", playerBlack)
+       lastMove = thisMove
+       meta:set_string("lastMove", lastMove)
+       meta:set_int("lastMoveTime", minetest.get_gametime())
+
+       if lastMove == "black" then
+               minetest.chat_send_player(playerWhite, "["..os.date("%H:%M:%S").."] "..
+                               playerName.." moved a "..pieceFrom:match(":(%a+)")..", it's now your turn.")
+       elseif lastMove == "white" then
+               minetest.chat_send_player(playerBlack, "["..os.date("%H:%M:%S").."] "..
+                               playerName.." moved a "..pieceFrom:match(":(%a+)")..", it's now your turn.")
+       end
+
+       if pieceTo:sub(11,14) == "king" then
+               minetest.chat_send_player(playerBlack, playerName.." won the game.")
+               minetest.chat_send_player(playerWhite, playerName.." won the game.")
+               meta:set_string("winner", thisMove)
+       end
+
+       return 1
+end
+
+local function timeout_format(timeout_limit)
+       local time_remaining = timeout_limit - minetest.get_gametime()
+       local minutes = math.floor(time_remaining / 60)
+       local seconds = time_remaining % 60
+
+       if minutes == 0 then return seconds.." sec." end
+       return minutes.." min. "..seconds.." sec."
+end
+
+function realchess.fields(pos, _, fields, sender)
+       local playerName = sender:get_player_name()
+       local meta = minetest.get_meta(pos)
+       local timeout_limit = meta:get_int("lastMoveTime") + 300
+       local playerWhite = meta:get_string("playerWhite")
+       local playerBlack = meta:get_string("playerBlack")
+       local lastMoveTime = meta:get_int("lastMoveTime")
+       if fields.quit then return end
+
+       -- timeout is 5 min. by default for resetting the game (non-players only)
+       if fields.new and (playerWhite == playerName or playerBlack == playerName) then
+               realchess.init(pos)
+       elseif fields.new and lastMoveTime ~= 0 and minetest.get_gametime() >= timeout_limit and
+                       (playerWhite ~= playerName or playerBlack ~= playerName) then
+               realchess.init(pos)
+       else
+               minetest.chat_send_player(playerName, "[!] You can't reset the chessboard, a game has been started.\n"..
+                               "If you are not a current player, try again in "..timeout_format(timeout_limit))
+       end
+end
+
+function realchess.dig(pos, player)
+       if not player then
+               return false
+       end
+       local meta = minetest.get_meta(pos)
+       local playerName = player:get_player_name()
+       local timeout_limit = meta:get_int("lastMoveTime") + 300
+       local lastMoveTime = meta:get_int("lastMoveTime")
+
+       -- timeout is 5 min. by default for digging the chessboard (non-players only)
+       return (lastMoveTime == 0 and minetest.get_gametime() > timeout_limit) or
+               minetest.chat_send_player(playerName, "[!] You can't dig the chessboard, a game has been started.\n"..
+                               "Reset it first if you're a current player, or dig again in "..timeout_format(timeout_limit))
+end
+
+function realchess.on_move(pos, from_list, from_index)
+       local inv = minetest.get_meta(pos):get_inventory()
+       inv:set_stack(from_list, from_index, '')
+       return false
+end
+
+minetest.register_node(":realchess:chessboard", {
+       description = "Chess Board",
+       drawtype = "nodebox",
+       paramtype = "light",
+       paramtype2 = "facedir",
+       inventory_image = "chessboard_top.png",
+       wield_image = "chessboard_top.png",
+       tiles = {"chessboard_top.png", "chessboard_top.png", "chessboard_sides.png"},
+       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
+       sounds = default.node_sound_wood_defaults(),
+       node_box = {type = "fixed", fixed = {-.375, -.5, -.375, .375, -.4375, .375}},
+       sunlight_propagates = true,
+       on_rotate = screwdriver.rotate_simple,
+       can_dig = realchess.dig,
+       on_construct = realchess.init,
+       on_receive_fields = realchess.fields,
+       allow_metadata_inventory_move = realchess.move,
+       on_metadata_inventory_move = realchess.on_move,
+       allow_metadata_inventory_take = function() return 0 end
+})
+
+local function register_piece(name, count)
+       for _, color in pairs({"black", "white"}) do
+       if not count then
+               minetest.register_craftitem(":realchess:"..name.."_"..color, {
+                       description = color:gsub("^%l", string.upper).." "..name:gsub("^%l", string.upper),
+                       inventory_image = name.."_"..color..".png",
+                       stack_max = 1,
+                       groups = {not_in_creative_inventory=1}
+               })
+       else
+               for i = 1, count do
+                       minetest.register_craftitem(":realchess:"..name.."_"..color.."_"..i, {
+                               description = color:gsub("^%l", string.upper).." "..name:gsub("^%l", string.upper),
+                               inventory_image = name.."_"..color..".png",
+                               stack_max = 1,
+                               groups = {not_in_creative_inventory=1}
+                       })
+               end
+       end
+       end
+end
+
+register_piece("pawn", 8)
+register_piece("rook", 2)
+register_piece("knight", 2)
+register_piece("bishop", 2)
+register_piece("queen")
+register_piece("king")
+
diff --git a/src/cooking.lua b/src/cooking.lua
new file mode 100644 (file)
index 0000000..46629ec
--- /dev/null
@@ -0,0 +1,200 @@
+local cauldron, sounds = {}, {}
+
+-- Add more ingredients here that make a soup.
+local ingredients_list = {
+       "apple", "mushroom", "honey", "pumpkin", "egg", "bread", "meat",
+       "chicken", "carrot", "potato", "melon", "rhubarb", "cucumber",
+       "corn", "beans", "berries", "grapes", "tomato", "wheat"
+}
+
+cauldron.cbox = {
+       {0,  0, 0,  16, 16, 0},
+       {0,  0, 16, 16, 16, 0},
+       {0,  0, 0,  0,  16, 16},
+       {16, 0, 0,  0,  16, 16},
+       {0,  0, 0,  16, 8,  16}
+}
+
+function cauldron.stop_sound(pos)
+       local spos = minetest.hash_node_position(pos)
+       if sounds[spos] then minetest.sound_stop(sounds[spos]) end
+end
+
+function cauldron.idle_construct(pos)
+       local timer = minetest.get_node_timer(pos)
+       timer:start(10.0)
+       cauldron.stop_sound(pos)
+end
+
+function cauldron.boiling_construct(pos)
+       local spos = minetest.hash_node_position(pos)
+       sounds[spos] = minetest.sound_play("xdecor_boiling_water", {
+               pos=pos, max_hear_distance=5, gain=0.8, loop=true
+       })
+
+       local meta = minetest.get_meta(pos)
+       meta:set_string("infotext", "Cauldron (active) - Drop some foods inside to make a soup")
+
+       local timer = minetest.get_node_timer(pos)
+       timer:start(5.0)
+end
+
+function cauldron.filling(pos, node, clicker, itemstack)
+       local inv = clicker:get_inventory()
+       local wield_item = clicker:get_wielded_item():get_name()
+
+       if wield_item:sub(1,7) == "bucket:" then
+               if wield_item:sub(-6) == "_empty" and not (node.name:sub(-6) == "_empty") then
+                       if itemstack:get_count() > 1 then
+                               if inv:room_for_item("main", "bucket:bucket_water 1") then
+                                       itemstack:take_item()
+                                       inv:add_item("main", "bucket:bucket_water 1")
+                               else
+                                       minetest.chat_send_player(clicker:get_player_name(),
+                                               "No room in your inventory to add a bucket of water.")
+                                       return itemstack
+                               end
+                       else
+                               itemstack:replace("bucket:bucket_water")
+                       end
+                       minetest.set_node(pos, {name="xdecor:cauldron_empty", param2=node.param2})
+               elseif wield_item:sub(-6) == "_water" and node.name:sub(-6) == "_empty" then
+                       minetest.set_node(pos, {name="xdecor:cauldron_idle", param2=node.param2})
+                       itemstack:replace("bucket:bucket_empty")
+               end
+               return itemstack
+       end
+end
+
+function cauldron.idle_timer(pos)
+       local below_node = {x=pos.x, y=pos.y-1, z=pos.z}
+       if not minetest.get_node(below_node).name:find("fire") then
+               return true
+       end
+
+       local node = minetest.get_node(pos)
+       minetest.set_node(pos, {name="xdecor:cauldron_boiling", param2=node.param2})
+       return true
+end
+
+-- Ugly hack to determine if an item has `minetest.item_eat` in its definition.
+local function eatable(itemstring)
+       local item = itemstring:match("[%w_:]+")
+       local on_use_def = minetest.registered_items[item].on_use
+       if not on_use_def then return end
+       return string.format("%q", string.dump(on_use_def)):find("item_eat")
+end
+
+function cauldron.boiling_timer(pos)
+       local node = minetest.get_node(pos)
+       local objs = minetest.get_objects_inside_radius(pos, 0.5)
+       if objs == {} then return true end
+
+       local ingredients = {}
+       for _, obj in pairs(objs) do
+               if obj and not obj:is_player() and obj:get_luaentity().itemstring then
+                       local itemstring = obj:get_luaentity().itemstring
+                       local food = itemstring:match(":([%w_]+)")
+
+                       for _, ingredient in pairs(ingredients_list) do
+                               if food and (eatable(itemstring) or food:find(ingredient)) then
+                                       ingredients[#ingredients+1] = food break
+                               end
+                       end
+               end
+       end
+
+       if #ingredients >= 2 then
+               for _, obj in pairs(objs) do obj:remove() end
+               minetest.set_node(pos, {name="xdecor:cauldron_soup", param2=node.param2})
+       end
+
+       local node_under = {x=pos.x, y=pos.y-1, z=pos.z}
+       if not minetest.get_node(node_under).name:find("fire") then
+               minetest.set_node(pos, {name="xdecor:cauldron_idle", param2=node.param2})
+       end
+       return true
+end
+
+function cauldron.take_soup(pos, node, clicker, itemstack)
+       local inv = clicker:get_inventory()
+       local wield_item = clicker:get_wielded_item()
+
+       if wield_item:get_name() == "xdecor:bowl" then
+               if wield_item:get_count() > 1 then
+                       if inv:room_for_item("main", "xdecor:bowl_soup 1") then
+                               itemstack:take_item()
+                               inv:add_item("main", "xdecor:bowl_soup 1")
+                       else
+                               minetest.chat_send_player(clicker:get_player_name(),
+                                       "No room in your inventory to add a bowl of soup.")
+                               return itemstack
+                       end
+               else
+                       itemstack:replace("xdecor:bowl_soup 1")
+               end
+
+               minetest.set_node(pos, {name="xdecor:cauldron_empty", param2=node.param2})
+       end
+       return itemstack
+end
+
+xdecor.register("cauldron_empty", {
+       description = "Cauldron",
+       groups = {cracky=2, oddly_breakable_by_hand=1},
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"xdecor_cauldron_top_empty.png", "xdecor_cauldron_sides.png"},
+       infotext = "Cauldron (empty)",
+       on_construct = function(pos)
+               cauldron.stop_sound(pos)
+       end,
+       on_rightclick = cauldron.filling,
+       collision_box = xdecor.pixelbox(16, cauldron.cbox)
+})
+
+xdecor.register("cauldron_idle", {
+       groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1},
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"xdecor_cauldron_top_idle.png", "xdecor_cauldron_sides.png"},
+       drop = "xdecor:cauldron_empty",
+       infotext = "Cauldron (idle)",
+       collision_box = xdecor.pixelbox(16, cauldron.cbox),
+       on_rightclick = cauldron.filling,
+       on_construct = cauldron.idle_construct,
+       on_timer = cauldron.idle_timer
+})
+
+xdecor.register("cauldron_boiling", {
+       groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1},
+       on_rotate = screwdriver.rotate_simple,
+       drop = "xdecor:cauldron_empty",
+       infotext = "Cauldron (active) - Drop foods inside to make a soup",
+       damage_per_second = 2,
+       tiles = {{name="xdecor_cauldron_top_anim_boiling_water.png",
+                       animation={type="vertical_frames", length=3.0}},
+               "xdecor_cauldron_sides.png"},
+       collision_box = xdecor.pixelbox(16, cauldron.cbox),
+       on_rightclick = cauldron.filling,
+       on_construct = cauldron.boiling_construct,
+       on_destruct = function(pos)
+               cauldron.stop_sound(pos)
+       end,
+       on_timer = cauldron.boiling_timer
+})
+
+xdecor.register("cauldron_soup", {
+       groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1},
+       on_rotate = screwdriver.rotate_simple,
+       drop = "xdecor:cauldron_empty",
+       infotext = "Cauldron (active) - Use a bowl to eat the soup",
+       damage_per_second = 2,
+       tiles = {{name="xdecor_cauldron_top_anim_soup.png",
+                       animation={type="vertical_frames", length=3.0}},
+               "xdecor_cauldron_sides.png"},
+       collision_box = xdecor.pixelbox(16, cauldron.cbox),
+       on_rightclick = cauldron.take_soup,
+       on_destruct = function(pos)
+               cauldron.stop_sound(pos)
+       end
+})
+
diff --git a/src/craftitems.lua b/src/craftitems.lua
new file mode 100644 (file)
index 0000000..a1eadb1
--- /dev/null
@@ -0,0 +1,38 @@
+minetest.register_craftitem("xdecor:bowl", {
+       description = "Bowl",
+       inventory_image = "xdecor_bowl.png",
+       wield_image = "xdecor_bowl.png"
+})
+
+minetest.register_craftitem("xdecor:bowl_soup", {
+       description = "Bowl of soup",
+       inventory_image = "xdecor_bowl_soup.png",
+       wield_image = "xdecor_bowl_soup.png",
+       groups = {not_in_creative_inventory=1},
+       stack_max = 1,
+       on_use = function(itemstack, user)
+               itemstack:replace("xdecor:bowl 1")
+               if rawget(_G, "hunger") then
+                       minetest.item_eat(20)
+               else
+                       user:set_hp(20)
+               end
+               return itemstack
+       end
+})
+
+minetest.register_tool("xdecor:hammer", {
+       description = "Hammer",
+       inventory_image = "xdecor_hammer.png",
+       wield_image = "xdecor_hammer.png",
+       on_use = function() do return end end
+})
+
+minetest.register_craftitem("xdecor:honey", {
+       description = "Honey",
+       inventory_image = "xdecor_honey.png",
+       wield_image = "xdecor_honey.png",
+       groups = {not_in_creative_inventory=1},
+       on_use = minetest.item_eat(2)
+})
+
diff --git a/src/enchanting.lua b/src/enchanting.lua
new file mode 100644 (file)
index 0000000..028a5b4
--- /dev/null
@@ -0,0 +1,287 @@
+local enchanting = {}
+screwdriver = screwdriver or {}
+
+-- Cost in Mese crystal(s) for enchanting.
+local mese_cost = 1
+
+-- Force of the enchantments.
+enchanting.uses     = 1.2  -- Durability
+enchanting.times    = 0.1  -- Efficiency
+enchanting.damages  = 1    -- Sharpness
+enchanting.strength = 1.2  -- Armor strength (3d_armor only)
+enchanting.speed    = 0.2  -- Player speed (3d_armor only)
+enchanting.jump     = 0.2  -- Player jumping (3d_armor only)
+
+function enchanting.formspec(pos, num)
+       local meta = minetest.get_meta(pos)
+       local formspec = [[ size[9,9;]
+                       bgcolor[#080808BB;true]
+                       background[0,0;9,9;ench_ui.png]
+                       list[context;tool;0.9,2.9;1,1;]
+                       list[context;mese;2,2.9;1,1;]
+                       list[current_player;main;0.5,4.5;8,4;]
+                       image[2,2.9;1,1;mese_layout.png]
+                       tooltip[sharp;Your weapon inflicts more damages]
+                       tooltip[durable;Your tool last longer]
+                       tooltip[fast;Your tool digs faster]
+                       tooltip[strong;Your armor is more resistant]
+                       tooltip[speed;Your speed is increased] ]]
+                       ..default.gui_slots..default.get_hotbar_bg(0.5,4.5)
+
+       local enchant_buttons = {
+               [[ image_button[3.9,0.85;4,0.92;bg_btn.png;fast;Efficiency]
+               image_button[3.9,1.77;4,1.12;bg_btn.png;durable;Durability] ]],
+               "image_button[3.9,0.85;4,0.92;bg_btn.png;strong;Strength]",
+               "image_button[3.9,2.9;4,0.92;bg_btn.png;sharp;Sharpness]",
+               [[ image_button[3.9,0.85;4,0.92;bg_btn.png;strong;Strength]
+               image_button[3.9,1.77;4,1.12;bg_btn.png;speed;Speed] ]]
+       }
+
+       formspec = formspec..(enchant_buttons[num] or "")
+       meta:set_string("formspec", formspec)
+end
+
+function enchanting.on_put(pos, listname, _, stack)
+       if listname == "tool" then
+               local stackname = stack:get_name()
+               local tool_groups = {
+                       "axe, pick, shovel",
+                       "chestplate, leggings, helmet",
+                       "sword", "boots"
+               }
+
+               for idx, tools in pairs(tool_groups) do
+                       if tools:find(stackname:match(":(%w+)")) then
+                               enchanting.formspec(pos, idx)
+                       end
+               end
+       end
+end
+
+function enchanting.fields(pos, _, fields, sender)
+       if not next(fields) or fields.quit then
+               return
+       end
+       local inv = minetest.get_meta(pos):get_inventory()
+       local tool = inv:get_stack("tool", 1)
+       local mese = inv:get_stack("mese", 1)
+       local orig_wear = tool:get_wear()
+       local mod, name = tool:get_name():match("(.*):(.*)")
+       local enchanted_tool = (mod or "")..":enchanted_"..(name or "").."_"..next(fields)
+
+       if mese:get_count() >= mese_cost and minetest.registered_tools[enchanted_tool] then
+               minetest.sound_play("xdecor_enchanting", {to_player=sender:get_player_name(), gain=0.8})
+               tool:replace(enchanted_tool)
+               tool:add_wear(orig_wear)
+               mese:take_item(mese_cost)
+               inv:set_stack("mese", 1, mese)
+               inv:set_stack("tool", 1, tool)
+       end
+end
+
+function enchanting.dig(pos)
+       local inv = minetest.get_meta(pos):get_inventory()
+       return inv:is_empty("tool") and inv:is_empty("mese")
+end
+
+local function allowed(tool)
+       if not tool then
+               return false
+       end
+       for item in pairs(minetest.registered_tools) do
+               if item:find("enchanted_"..tool) then return true end
+       end
+       return false
+end
+
+function enchanting.put(_, listname, _, stack)
+       local item = stack:get_name():match("[^:]+$")
+       if listname == "mese" and item == "mese_crystal" then
+               return stack:get_count()
+       elseif listname == "tool" and allowed(item) then
+               return 1 
+       end
+       return 0
+end
+
+function enchanting.on_take(pos, listname)
+       if listname == "tool" then enchanting.formspec(pos, nil) end
+end
+
+function enchanting.construct(pos)
+       local meta = minetest.get_meta(pos)
+       meta:set_string("infotext", "Enchantment Table")
+       enchanting.formspec(pos, nil)
+
+       local inv = meta:get_inventory()
+       inv:set_size("tool", 1)
+       inv:set_size("mese", 1)
+
+       minetest.add_entity({x=pos.x, y=pos.y+0.85, z=pos.z}, "xdecor:book_open")
+       local timer = minetest.get_node_timer(pos)
+       timer:start(5.0)
+end
+
+function enchanting.destruct(pos)
+       for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do
+               if obj and obj:get_luaentity() and
+                               obj:get_luaentity().name == "xdecor:book_open" then
+                       obj:remove() break
+               end
+       end
+end
+
+function enchanting.timer(pos)
+       local num = #minetest.get_objects_inside_radius(pos, 0.9)
+
+       if num == 0 then
+               minetest.add_entity({x=pos.x, y=pos.y+0.85, z=pos.z}, "xdecor:book_open")
+       end
+
+       local minp = {x=pos.x-2, y=pos.y, z=pos.z-2}
+       local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
+       local bookshelves = minetest.find_nodes_in_area(minp, maxp, "default:bookshelf")
+       if #bookshelves == 0 then return true end
+
+       local bookshelf_pos = bookshelves[math.random(1, #bookshelves)]
+       local x = pos.x - bookshelf_pos.x
+       local y = bookshelf_pos.y - pos.y
+       local z = pos.z - bookshelf_pos.z
+
+       if tostring(x..z):find(2) then
+               minetest.add_particle({
+                       pos = bookshelf_pos,
+                       velocity = {x=x, y=2-y, z=z},
+                       acceleration = {x=0, y=-2.2, z=0},
+                       expirationtime = 1,
+                       size = 2,
+                       texture = "xdecor_glyph"..math.random(1,18)..".png"
+               })
+       end
+       return true
+end
+
+xdecor.register("enchantment_table", {
+       description = "Enchantment Table",
+       tiles = {"xdecor_enchantment_top.png",  "xdecor_enchantment_bottom.png",
+                "xdecor_enchantment_side.png", "xdecor_enchantment_side.png",
+                "xdecor_enchantment_side.png", "xdecor_enchantment_side.png"},
+       groups = {cracky=1, level=1},
+       sounds = default.node_sound_stone_defaults(),
+       on_rotate = screwdriver.rotate_simple,
+       can_dig = enchanting.dig,
+       on_timer = enchanting.timer,
+       on_construct = enchanting.construct,
+       on_destruct = enchanting.destruct,
+       on_receive_fields = enchanting.fields,
+       on_metadata_inventory_put = enchanting.on_put,
+       on_metadata_inventory_take = enchanting.on_take,
+       allow_metadata_inventory_put = enchanting.put,
+       allow_metadata_inventory_move = function() return 0 end
+})
+
+minetest.register_entity("xdecor:book_open", {
+       visual = "sprite",
+       visual_size = {x=0.75, y=0.75},
+       collisionbox = {0},
+       physical = false,
+       textures = {"xdecor_book_open.png"},
+       on_activate = function(self)
+               local pos = self.object:getpos()
+               local pos_under = {x=pos.x, y=pos.y-1, z=pos.z}
+
+               if minetest.get_node(pos_under).name ~= "xdecor:enchantment_table" then
+                       self.object:remove()
+               end
+       end
+})
+
+local function cap(S) return S:gsub("^%l", string.upper) end
+
+function enchanting:register_tools(mod, def)
+       for tool in pairs(def.tools) do
+       for material in def.materials:gmatch("[%w_]+") do
+       for enchant in def.tools[tool].enchants:gmatch("[%w_]+") do
+               local original_tool = minetest.registered_tools[mod..":"..tool.."_"..material]
+               if not original_tool then break end
+
+               if original_tool.tool_capabilities then
+                       local original_damage_groups = original_tool.tool_capabilities.damage_groups
+                       local original_groupcaps = original_tool.tool_capabilities.groupcaps
+                       local groupcaps = table.copy(original_groupcaps)
+                       local fleshy = original_damage_groups.fleshy
+                       local full_punch_interval = original_tool.tool_capabilities.full_punch_interval
+                       local max_drop_level = original_tool.tool_capabilities.max_drop_level
+                       local group = next(original_groupcaps)
+
+                       if enchant == "durable" then
+                               groupcaps[group].uses = math.ceil(original_groupcaps[group].uses * enchanting.uses)
+                       elseif enchant == "fast" then
+                               for i, time in pairs(original_groupcaps[group].times) do
+                                       groupcaps[group].times[i] = time - enchanting.times
+                               end
+                       elseif enchant == "sharp" then
+                               fleshy = fleshy + enchanting.damages
+                       end
+
+                       minetest.register_tool(":"..mod..":enchanted_"..tool.."_"..material.."_"..enchant, {
+                               description = "Enchanted "..cap(material).." "..cap(tool).." ("..cap(enchant)..")",
+                               inventory_image = original_tool.inventory_image.."^[colorize:violet:50",
+                               wield_image = original_tool.wield_image,
+                               groups = {not_in_creative_inventory=1},
+                               tool_capabilities = {
+                                       groupcaps = groupcaps, damage_groups = {fleshy = fleshy},
+                                       full_punch_interval = full_punch_interval, max_drop_level = max_drop_level
+                               }
+                       })
+               end
+
+               if mod == "3d_armor" then
+                       local original_armor_groups = original_tool.groups
+                       local armorcaps = {}
+                       armorcaps.not_in_creative_inventory = 1
+
+                       for armor_group, value in pairs(original_armor_groups) do
+                               if enchant == "strong" then
+                                       armorcaps[armor_group] = math.ceil(value * enchanting.strength)
+                               elseif enchant == "speed" then
+                                       armorcaps[armor_group] = value
+                                       armorcaps.physics_speed = enchanting.speed
+                                       armorcaps.physics_jump = enchanting.jump
+                               end
+                       end
+
+                       minetest.register_tool(":"..mod..":enchanted_"..tool.."_"..material.."_"..enchant, {
+                               description = "Enchanted "..cap(material).." "..cap(tool).." ("..cap(enchant)..")",
+                               inventory_image = original_tool.inventory_image,
+                               texture = "3d_armor_"..tool.."_"..material,
+                               wield_image = original_tool.wield_image,
+                               groups = armorcaps,
+                               wear = 0
+                       })
+               end
+       end
+       end
+       end
+end
+
+enchanting:register_tools("default", {
+       materials = "steel, bronze, mese, diamond",
+       tools = {
+               axe    = {enchants = "durable, fast"},
+               pick   = {enchants = "durable, fast"}, 
+               shovel = {enchants = "durable, fast"},
+               sword  = {enchants = "sharp"}
+       }
+})
+
+enchanting:register_tools("3d_armor", {
+       materials = "steel, bronze, gold, diamond",
+       tools = {
+               boots      = {enchants = "strong, speed"},
+               chestplate = {enchants = "strong"},
+               helmet     = {enchants = "strong"},
+               leggings   = {enchants = "strong"}
+       }
+})
+
diff --git a/src/hive.lua b/src/hive.lua
new file mode 100644 (file)
index 0000000..6043135
--- /dev/null
@@ -0,0 +1,69 @@
+local hive = {}
+local honey_max = 16
+
+function hive.construct(pos)
+       local meta = minetest.get_meta(pos)
+       local inv = meta:get_inventory()
+
+       local formspec = [[ size[8,5;]
+                       label[0.5,0;Bees are busy making honey...]
+                       image[6,0;1,1;hive_bee.png]
+                       image[5,0;1,1;hive_layout.png]
+                       list[context;honey;5,0;1,1;]
+                       list[current_player;main;0,1.35;8,4;] ]]
+                       ..xbg..default.get_hotbar_bg(0,1.35)
+
+       meta:set_string("formspec", formspec)
+       meta:set_string("infotext", "Artificial Hive")
+       inv:set_size("honey", 1)
+
+       local timer = minetest.get_node_timer(pos)
+       timer:start(math.random(64, 128))
+end
+
+function hive.timer(pos)
+       local time = (minetest.get_timeofday() or 0) * 24000
+       if time < 5500 or time > 18500 then return true end
+
+       local inv = minetest.get_meta(pos):get_inventory()
+       local honeystack = inv:get_stack("honey", 1)
+       local honey = honeystack:get_count()
+
+       local radius = 4
+       local minp = vector.add(pos, -radius)
+       local maxp = vector.add(pos, radius)
+       local flowers = minetest.find_nodes_in_area_under_air(minp, maxp, "group:flower")
+
+       if #flowers > 2 and honey < honey_max then
+               inv:add_item("honey", "xdecor:honey")
+       elseif honey == honey_max then
+               local timer = minetest.get_node_timer(pos)
+               timer:stop() return true
+       end
+       return true
+end
+
+xdecor.register("hive", {
+       description = "Artificial Hive",
+       tiles = {"xdecor_hive_top.png", "xdecor_hive_top.png",
+                "xdecor_hive_side.png", "xdecor_hive_side.png",
+                "xdecor_hive_side.png", "xdecor_hive_front.png"},
+       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=1},
+       on_construct = hive.construct,
+       on_timer = hive.timer,
+       can_dig = function(pos)
+               local inv = minetest.get_meta(pos):get_inventory()
+               return inv:is_empty("honey")
+       end,
+       on_punch = function(_, _, puncher)
+               puncher:set_hp(puncher:get_hp() - 2)
+       end,
+       allow_metadata_inventory_put = function() return 0 end,
+       on_metadata_inventory_take = function(pos, _, _, stack)
+               if stack:get_count() == honey_max then
+                       local timer = minetest.get_node_timer(pos)
+                       timer:start(math.random(64, 128))
+               end
+       end
+})
+
diff --git a/src/itemframe.lua b/src/itemframe.lua
new file mode 100644 (file)
index 0000000..02d83d6
--- /dev/null
@@ -0,0 +1,156 @@
+local itemframe, tmp = {}, {}
+screwdriver = screwdriver or {}
+
+local function remove_item(pos, node)
+       local objs = minetest.get_objects_inside_radius(pos, 0.5)
+       if not objs then return end
+
+       for _, obj in pairs(objs) do
+               if obj and obj:get_luaentity() and
+                               obj:get_luaentity().name == "xdecor:f_item" then
+                       obj:remove() break
+               end
+       end
+end
+
+local facedir = {
+       [0] = {x=0, y=0, z=1}, {x=1, y=0, z=0}, {x=0, y=0, z=-1}, {x=-1, y=0, z=0}
+}
+
+local function update_item(pos, node)
+       remove_item(pos, node)
+       local meta = minetest.get_meta(pos)
+       local itemstring = meta:get_string("item")
+       local posad = facedir[node.param2]
+       if not posad or itemstring == "" then return end
+
+       pos = vector.add(pos, vector.multiply(posad, 6.5/16))
+       tmp.nodename = node.name
+       tmp.texture = ItemStack(itemstring):get_name()
+
+       local entity = minetest.add_entity(pos, "xdecor:f_item")
+       local yaw = math.pi*2 - node.param2 * math.pi/2
+       entity:setyaw(yaw)
+
+       local timer = minetest.get_node_timer(pos)
+       timer:start(15.0)
+end
+
+local function drop_item(pos, node)
+       local meta = minetest.get_meta(pos)
+       local item = meta:get_string("item")
+       if item == "" then return end
+
+       minetest.add_item(pos, item)
+       meta:set_string("item", "")
+       remove_item(pos, node)
+
+       local timer = minetest.get_node_timer(pos)
+       timer:stop()
+end
+
+function itemframe.after_place(pos, placer, itemstack)
+       local meta = minetest.get_meta(pos)
+       local name = placer:get_player_name()
+       meta:set_string("owner", name)
+       meta:set_string("infotext", "Item Frame (owned by "..name..")")
+end
+
+function itemframe.timer(pos)
+       local node = minetest.get_node(pos)
+       local meta = minetest.get_meta(pos)
+       local num = #minetest.get_objects_inside_radius(pos, 0.5)
+
+       if num == 0 and meta:get_string("item") ~= "" then
+               update_item(pos, node)
+       end
+       return true
+end
+
+function itemframe.rightclick(pos, node, clicker, itemstack)
+       local meta = minetest.get_meta(pos)
+       local player = clicker:get_player_name()
+       local owner = meta:get_string("owner")
+       if player ~= owner or not itemstack then
+               return itemstack
+       end
+
+       drop_item(pos, node)
+       local itemstring = itemstack:take_item():to_string()
+       meta:set_string("item", itemstring)
+       update_item(pos, node)
+
+       return itemstack
+end
+
+function itemframe.punch(pos, node, puncher)
+       local meta = minetest.get_meta(pos)
+       local player = puncher:get_player_name()
+       local owner = meta:get_string("owner")
+
+       if player ~= owner then return end
+       drop_item(pos, node)
+end
+
+function itemframe.dig(pos, player)
+       local meta = minetest.get_meta(pos)
+       local pname = player and player:get_player_name()
+       local owner = meta:get_string("owner")
+
+       return pname == owner
+end
+
+xdecor.register("itemframe", {
+       description = "Item Frame",
+       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
+       sounds = default.node_sound_wood_defaults(),
+       on_rotate = screwdriver.disallow,
+       sunlight_propagates = true,
+       inventory_image = "xdecor_itemframe.png",
+       node_box = xdecor.nodebox.slab_z(0.9375),
+       tiles = {"xdecor_wood.png", "xdecor_wood.png", "xdecor_wood.png",
+                "xdecor_wood.png", "xdecor_wood.png", "xdecor_itemframe.png"},
+       after_place_node = itemframe.after_place,
+       on_timer = itemframe.timer,
+       on_rightclick = itemframe.rightclick,
+       on_punch = itemframe.punch,
+       can_dig = itemframe.dig,
+       after_destruct = remove_item
+})
+
+minetest.register_entity("xdecor:f_item", {
+       visual = "wielditem",
+       visual_size = {x=0.33, y=0.33},
+       collisionbox = {0},
+       physical = false,
+       textures = {"air"},
+       on_activate = function(self, staticdata)
+               local pos = self.object:getpos()
+               if minetest.get_node(pos).name ~= "xdecor:itemframe" then
+                       self.object:remove()
+               end
+
+               if tmp.nodename and tmp.texture then
+                       self.nodename = tmp.nodename
+                       tmp.nodename = nil
+                       self.texture = tmp.texture
+                       tmp.texture = nil
+               elseif staticdata and staticdata ~= "" then
+                       local data = staticdata:split(";")
+                       if data and data[1] and data[2] then
+                               self.nodename = data[1]
+                               self.texture = data[2]
+                       end
+               end
+               if self.texture then
+                       self.object:set_properties({textures={self.texture}})
+               end
+       end,
+       get_staticdata = function(self)
+               if self.nodename and self.texture then
+                       return self.nodename..";"..self.texture
+               end
+               return ""
+       end
+})
+
diff --git a/src/mailbox.lua b/src/mailbox.lua
new file mode 100644 (file)
index 0000000..cd9a03c
--- /dev/null
@@ -0,0 +1,154 @@
+local mailbox = {}
+screwdriver = screwdriver or {}
+
+local function get_img(img)
+       local img_name = img:match("(.*)%.png")
+       if img_name then return img_name..".png" end
+end
+
+local function img_col(stack)
+       local def = minetest.registered_items[stack]
+       if not def then return "" end
+
+       if def.inventory_image ~= "" then
+               local img = get_img(def.inventory_image)
+               if img then return img end
+       end
+
+       if def.tiles then
+               local img
+               local tile = def.tiles[1]
+
+               if type(tile) == "table" then
+                       img = get_img(tile.name)
+               elseif type(tile) == "string" then
+                       img = get_img(tile)
+               end
+
+               if img then return img end
+       end
+
+       return ""
+end
+
+function mailbox:formspec(pos, owner, num)
+       local spos = pos.x..","..pos.y..","..pos.z
+       local meta = minetest.get_meta(pos)
+       local giver, img = "", ""
+
+       if num == 1 then
+               for i = 1, 7 do
+                       local giving = meta:get_string("giver"..i)
+                       if giving ~= "" then
+                               local stack = meta:get_string("stack"..i)
+                               local giver_name = giving:sub(1,12)
+                               local stack_name = stack:match("[%w_:]+")
+                               local stack_count = stack:match("%s(%d+)") or 1
+
+                               giver = giver.."#FFFF00,"..giver_name..","..i..",#FFFFFF,x "..stack_count..","
+                               -- Hack to force using a 16px resolution for images in formspec's tablecolumn.
+                               -- The engine doesn't scale them automatically yet.
+                               img = img..i.."="..img_col(stack_name).."^\\[resize:16x16,"
+                       end
+               end
+
+               return [[ size[9.5,9]
+                       label[0,0;Mailbox]
+                       label[6,0;Last donators]
+                       box[6,0.72;3.3,3.5;#555555]
+                       listring[current_player;main]
+                       list[current_player;main;0.75,5.25;8,4;]
+                       tableoptions[background=#00000000;highlight=#00000000;border=false] ]]
+                       .."tablecolumns[color;text;image,"..img.."0;color;text]"..
+                       "table[6,0.75;3.3,4;givers;"..giver.."]"..
+                       "list[nodemeta:"..spos..";mailbox;0,0.75;6,4;]"..
+                       "listring[nodemeta:"..spos..";mailbox]"..
+                       xbg..default.get_hotbar_bg(0.75,5.25)
+       else
+               return [[ size[8,5]
+                       list[current_player;main;0,1.25;8,4;]
+                       tablecolumns[color;text;color;text]
+                       tableoptions[background=#00000000;highlight=#00000000;border=false] ]]
+                       .."table[0,0;3,1;sendform;#FFFFFF,Send your goods to,,,#FFFF00,"..owner.."]"..
+                       "list[nodemeta:"..spos..";drop;3.5,0;1,1;]"..
+                       xbg..default.get_hotbar_bg(0,1.25)
+       end
+end
+
+function mailbox.dig(pos, player)
+       local meta = minetest.get_meta(pos)
+       local owner = meta:get_string("owner")
+       local player_name = player and player:get_player_name()
+       local inv = meta:get_inventory()
+
+       return inv:is_empty("mailbox") and player_name == owner
+end
+
+function mailbox.after_place_node(pos, placer)
+       local meta = minetest.get_meta(pos)
+       local player_name = placer:get_player_name()
+
+       meta:set_string("owner", player_name)
+       meta:set_string("infotext", player_name.."'s Mailbox")
+
+       local inv = meta:get_inventory()
+       inv:set_size("mailbox", 6*4)
+       inv:set_size("drop", 1)
+end
+
+function mailbox.rightclick(pos, node, clicker, itemstack, pointed_thing)
+       local meta = minetest.get_meta(pos)
+       local player = clicker:get_player_name()
+       local owner = meta:get_string("owner")
+
+       if player == owner then
+               minetest.show_formspec(player, "xdecor:mailbox", mailbox:formspec(pos, owner, 1))
+       else
+               minetest.show_formspec(player, "xdecor:mailbox", mailbox:formspec(pos, owner, 0))
+       end
+       return itemstack
+end
+
+function mailbox.put(pos, listname, _, stack, player)
+       if listname == "drop" then
+               local inv = minetest.get_meta(pos):get_inventory()
+               if inv:room_for_item("mailbox", stack) then
+                       return -1
+               else
+                       minetest.chat_send_player(player:get_player_name(), "The mailbox is full")
+               end
+       end
+       return 0
+end
+
+function mailbox.on_put(pos, listname, _, stack, player)
+       local meta = minetest.get_meta(pos)
+       local inv = meta:get_inventory()
+
+       if listname == "drop" and inv:room_for_item("mailbox", stack) then
+               inv:set_list("drop", {})
+               inv:add_item("mailbox", stack)
+
+               for i = 7, 2, -1 do
+                       meta:set_string("giver"..i, meta:get_string("giver"..(i-1)))
+                       meta:set_string("stack"..i, meta:get_string("stack"..(i-1)))
+               end
+
+               meta:set_string("giver1", player:get_player_name())
+               meta:set_string("stack1", stack:to_string())
+       end
+end
+
+xdecor.register("mailbox", {
+       description = "Mailbox",
+       tiles = {"xdecor_mailbox_top.png", "xdecor_mailbox_bottom.png",
+                "xdecor_mailbox_side.png", "xdecor_mailbox_side.png",
+                "xdecor_mailbox.png", "xdecor_mailbox.png"},
+       groups = {cracky=3, oddly_breakable_by_hand=1},
+       on_rotate = screwdriver.rotate_simple,
+       can_dig = mailbox.dig,
+       on_rightclick = mailbox.rightclick,
+       on_metadata_inventory_put = mailbox.on_put,
+       allow_metadata_inventory_put = mailbox.put,
+       after_place_node = mailbox.after_place_node
+})
diff --git a/src/mechanisms.lua b/src/mechanisms.lua
new file mode 100644 (file)
index 0000000..4686302
--- /dev/null
@@ -0,0 +1,120 @@
+--[[ Thanks to sofar for helping with that code.
+Recommended setting in minetest.conf (requires 0.4.14 or newer) :
+       nodetimer_interval = 0.1
+]]
+
+local plate = {}
+screwdriver = screwdriver or {}
+
+local function door_toggle(pos_actuator, pos_door, player)
+       local actuator = minetest.get_node(pos_actuator)
+       local door = doors.get(pos_door)
+
+       if actuator.name:sub(-4) == "_off" then
+               minetest.set_node(pos_actuator,
+                       {name=actuator.name:gsub("_off", "_on"), param2=actuator.param2})
+       end
+       door:open(player)
+
+       minetest.after(2, function()
+               if minetest.get_node(pos_actuator).name:sub(-3) == "_on" then
+                       minetest.set_node(pos_actuator,
+                               {name=actuator.name, param2=actuator.param2})
+               end
+               door:close(player)
+       end)
+end
+
+function plate.construct(pos)
+       local timer = minetest.get_node_timer(pos)
+       timer:start(0.1)
+end
+
+function plate.timer(pos)
+       local objs = minetest.get_objects_inside_radius(pos, 0.8)
+       if objs == {} or not doors.get then return true end
+       local minp = {x=pos.x-2, y=pos.y, z=pos.z-2}
+       local maxp = {x=pos.x+2, y=pos.y, z=pos.z+2}
+       local doors = minetest.find_nodes_in_area(minp, maxp, "group:door")
+
+       for _, player in pairs(objs) do
+               if player:is_player() then
+                       for i = 1, #doors do
+                               door_toggle(pos, doors[i], player)
+                       end
+                       break
+               end
+       end
+       return true
+end
+
+function plate.register(material, desc, def)
+       xdecor.register("pressure_"..material.."_off", {
+               description = desc.." Pressure Plate",
+               tiles = {"xdecor_pressure_"..material..".png"},
+               drawtype = "nodebox",
+               node_box = xdecor.pixelbox(16, {{1, 0, 1, 14, 1, 14}}),
+               groups = def.groups,
+               sounds = def.sounds,
+               sunlight_propagates = true,
+               on_rotate = screwdriver.rotate_simple,
+               on_construct = plate.construct,
+               on_timer = plate.timer
+       })
+       xdecor.register("pressure_"..material.."_on", {
+               tiles = {"xdecor_pressure_"..material..".png"},
+               drawtype = "nodebox",
+               node_box = xdecor.pixelbox(16, {{1, 0, 1, 14, 0.4, 14}}),
+               groups = def.groups,
+               sounds = def.sounds,
+               drop = "xdecor:pressure_"..material.."_off",
+               sunlight_propagates = true,
+               on_rotate = screwdriver.rotate_simple
+       })
+end
+
+plate.register("wood", "Wooden", {
+       sounds = default.node_sound_wood_defaults(),
+       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2}
+})
+
+plate.register("stone", "Stone", {
+       sounds = default.node_sound_stone_defaults(),
+       groups = {cracky=3, oddly_breakable_by_hand=2}
+})
+
+xdecor.register("lever_off", {
+       description = "Lever",
+       tiles = {"xdecor_lever_off.png"},
+       drawtype = "nodebox",
+       node_box = xdecor.pixelbox(16, {{2, 1, 15, 12, 14, 1}}),
+       groups = {cracky=3, oddly_breakable_by_hand=2},
+       sounds = default.node_sound_stone_defaults(),
+       sunlight_propagates = true,
+       on_rotate = screwdriver.rotate_simple,
+       on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+               if not doors.get then
+                       return itemstack
+               end
+               local minp = {x=pos.x-2, y=pos.y-1, z=pos.z-2}
+               local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2}
+               local doors = minetest.find_nodes_in_area(minp, maxp, "group:door")
+
+               for i = 1, #doors do
+                       door_toggle(pos, doors[i], clicker)
+               end
+               return itemstack
+       end
+})
+
+xdecor.register("lever_on", {
+       tiles = {"xdecor_lever_on.png"},
+       drawtype = "nodebox",
+       node_box = xdecor.pixelbox(16, {{2, 1, 15, 12, 14, 1}}),
+       groups = {cracky=3, oddly_breakable_by_hand=2, not_in_creative_inventory=1},
+       sounds = default.node_sound_stone_defaults(),
+       sunlight_propagates = true,
+       on_rotate = screwdriver.rotate_simple,
+       drop = "xdecor:lever_off"
+})
+
diff --git a/src/nodes.lua b/src/nodes.lua
new file mode 100644 (file)
index 0000000..ba1a6b4
--- /dev/null
@@ -0,0 +1,475 @@
+screwdriver = screwdriver or {}
+
+function xdecor.register_pane(name, desc, def)
+       xpanes.register_pane(name, {
+               description = desc,
+               tiles = {"xdecor_"..name..".png"},
+               drawtype = "airlike",
+               paramtype = "light",
+               textures = {"xdecor_"..name..".png", "xdecor_"..name..".png", "xpanes_space.png"},
+               inventory_image = "xdecor_"..name..".png",
+               wield_image = "xdecor_"..name..".png",
+               groups = def.groups,
+               sounds = def.sounds or default.node_sound_defaults(),
+               recipe = def.recipe
+       })
+end
+
+xdecor.register_pane("bamboo_frame", "Bamboo Frame", {
+       groups = {choppy=3, oddly_breakable_by_hand=2, pane=1, flammable=2},
+       recipe = {{"default:papyrus", "default:papyrus", "default:papyrus"},
+                 {"default:papyrus", "farming:cotton",  "default:papyrus"},
+                 {"default:papyrus", "default:papyrus", "default:papyrus"}}
+})
+
+xdecor.register_pane("chainlink", "Chainlink", {
+       groups = {cracky=3, oddly_breakable_by_hand=2, pane=1},
+       recipe = {{"default:steel_ingot", "", "default:steel_ingot"},
+                 {"", "default:steel_ingot", ""},
+                 {"default:steel_ingot", "", "default:steel_ingot"}}
+})
+
+xdecor.register_pane("rusty_bar", "Rusty Iron Bars", {
+       sounds = default.node_sound_stone_defaults(),
+       groups = {cracky=2, pane=1},
+       recipe = {{"", "default:dirt", ""},
+                 {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
+                 {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}}
+})
+
+xdecor.register_pane("wood_frame", "Wood Frame", {
+       sounds = default.node_sound_wood_defaults(),
+       groups = {choppy=2, pane=1, flammable=2},
+       recipe = {{"group:wood", "group:stick", "group:wood"},
+                 {"group:stick", "group:stick", "group:stick"},
+                 {"group:wood", "group:stick", "group:wood"}}
+})
+
+xdecor.register("baricade", {
+       description = "Baricade",
+       drawtype = "plantlike",
+       paramtype2 = "facedir",
+       inventory_image = "xdecor_baricade.png",
+       tiles = {"xdecor_baricade.png"},
+       groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2},
+       damage_per_second = 4,
+       selection_box = xdecor.nodebox.slab_y(0.3),
+       collision_box = xdecor.pixelbox(2, {{0, 0, 1, 2, 2, 0}})
+})
+
+xdecor.register("barrel", {
+       description = "Barrel",
+       tiles = {"xdecor_barrel_top.png", "xdecor_barrel_top.png", "xdecor_barrel_sides.png"},
+       on_place = minetest.rotate_node,
+       groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2},
+       sounds = default.node_sound_wood_defaults()
+})
+
+function xdecor.register_storage(name, desc, def)
+       xdecor.register(name, {
+               description = desc,
+               inventory = {size=def.inv_size or 24},
+               infotext = desc,
+               tiles = def.tiles,
+               node_box = def.node_box,
+               on_rotate = def.on_rotate,
+               on_place = def.on_place,
+               groups = def.groups or {choppy=2, oddly_breakable_by_hand=1, flammable=2},
+               sounds = default.node_sound_wood_defaults()
+       })
+end
+
+xdecor.register_storage("cabinet", "Wooden Cabinet", {
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png",
+                "xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png",
+                "xdecor_cabinet_sides.png", "xdecor_cabinet_front.png"}
+})
+
+xdecor.register_storage("cabinet_half", "Half Wooden Cabinet", {
+       inv_size = 8,
+       node_box = xdecor.nodebox.slab_y(0.5, 0.5),
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"xdecor_cabinet_sides.png", "xdecor_cabinet_sides.png",
+                "xdecor_half_cabinet_sides.png", "xdecor_half_cabinet_sides.png",
+                "xdecor_half_cabinet_sides.png", "xdecor_half_cabinet_front.png"}
+})
+
+xdecor.register_storage("empty_shelf", "Empty Shelf", {
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"default_wood.png", "default_wood.png^xdecor_empty_shelf.png"}
+})
+
+xdecor.register_storage("multishelf", "Multi Shelf", {
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"default_wood.png", "default_wood.png^xdecor_multishelf.png"},
+})
+
+xdecor.register("candle", {
+       description = "Candle",
+       light_source = 12,
+       drawtype = "torchlike",
+       inventory_image = "xdecor_candle_inv.png",
+       wield_image = "xdecor_candle_wield.png",
+       paramtype2 = "wallmounted",
+       walkable = false,
+       groups = {dig_immediate=3, attached_node=1},
+       tiles = {{name = "xdecor_candle_floor.png",
+                       animation = {type="vertical_frames", length=1.5}},
+               {name = "xdecor_candle_floor.png",
+                       animation = {type="vertical_frames", length=1.5}},
+               {name = "xdecor_candle_wall.png",
+                       animation = {type="vertical_frames", length=1.5}}
+       },
+       selection_box = {
+               type = "wallmounted",
+               wall_top = {-0.25, -0.5, -0.25, 0.25, 0.1, 0.25},
+               wall_bottom = {-0.25, -0.5, -0.25, 0.25, 0.1, 0.25},
+               wall_side = {-0.5, -0.35, -0.15, -0.15, 0.4, 0.15}
+       }
+})
+
+xdecor.register("chair", {
+       description = "Chair",
+       tiles = {"xdecor_wood.png"},
+       sounds = default.node_sound_wood_defaults(),
+       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2},
+       on_rotate = screwdriver.rotate_simple,
+       node_box = xdecor.pixelbox(16, {
+               {3,  0, 11,   2, 16, 2}, {11, 0, 11,  2, 16, 2},
+               {5,  9, 11.5, 6,  6, 1}, {3,  0,  3,  2,  6, 2},
+               {11, 0,  3,   2,  6, 2}, {3,  6,  3, 10, 2, 8}
+       }),
+       can_dig = xdecor.sit_dig,
+       on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+               pos.y = pos.y + 0  -- Sitting position.
+               xdecor.sit(pos, node, clicker, pointed_thing)
+               return itemstack
+       end
+})
+
+xdecor.register("cobweb", {
+       description = "Cobweb",
+       drawtype = "plantlike",
+       tiles = {"xdecor_cobweb.png"},
+       inventory_image = "xdecor_cobweb.png",
+       liquid_viscosity = 8,
+       liquidtype = "source",
+       liquid_alternative_flowing = "xdecor:cobweb",
+       liquid_alternative_source = "xdecor:cobweb",
+       liquid_renewable = false,
+       liquid_range = 0,
+       walkable = false,
+       selection_box = {type = "regular"},
+       groups = {snappy=3, liquid=3, flammable=3},
+       sounds = default.node_sound_leaves_defaults()
+})
+
+for _, c in pairs({"red"}) do  -- Add more curtains colors simply here.
+       xdecor.register("curtain_"..c, {
+               description = c:gsub("^%l", string.upper).." Curtain",
+               walkable = false,
+               tiles = {"wool_white.png^[colorize:"..c..":170"},
+               inventory_image = "wool_white.png^[colorize:"..c..":170^xdecor_curtain_open_overlay.png^[makealpha:255,126,126",
+               wield_image = "wool_white.png^[colorize:"..c..":170",
+               drawtype = "signlike",
+               paramtype2 = "wallmounted",
+               groups = {dig_immediate=3, flammable=3},
+               selection_box = {type="wallmounted"},
+               on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+                       minetest.set_node(pos, {name="xdecor:curtain_open_"..c, param2=node.param2})
+                       return itemstack
+               end
+       })
+
+       xdecor.register("curtain_open_"..c, {
+               tiles = {"wool_white.png^[colorize:"..c..":170^xdecor_curtain_open_overlay.png^[makealpha:255,126,126"},
+               drawtype = "signlike",
+               paramtype2 = "wallmounted",
+               walkable = false,
+               groups = {dig_immediate=3, flammable=3, not_in_creative_inventory=1},
+               selection_box = {type="wallmounted"},
+               drop = "xdecor:curtain_"..c,
+               on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+                       minetest.set_node(pos, {name="xdecor:curtain_"..c, param2=node.param2})
+                       return itemstack
+               end
+       })
+
+       minetest.register_craft({
+               output = "xdecor:curtain_"..c.." 4",
+               recipe = { {"", "wool:"..c, ""},
+                          {"", "wool:"..c, ""} }
+       })
+end
+
+xdecor.register("cushion", {
+       description = "Cushion",
+       tiles = {"xdecor_cushion.png"},
+       groups = {snappy=3, flammable=3, fall_damage_add_percent=-50},
+       on_place = minetest.rotate_node,
+       node_box = xdecor.nodebox.slab_y(0.5),
+       can_dig = xdecor.sit_dig,
+       on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
+               pos.y = pos.y + 0  -- Sitting position.
+               xdecor.sit(pos, node, clicker, pointed_thing)
+               return itemstack
+       end
+})
+
+xdecor.register("cushion_block", {
+       description = "Cushion Block",
+       tiles = {"xdecor_cushion.png"},
+       groups = {snappy=3, flammable=3, fall_damage_add_percent=-75, not_in_creative_inventory=1}
+})
+
+local function door_access(name) return name:find("prison") end
+local xdecor_doors = {
+       japanese = {
+               {"group:wood", "default:paper"},
+               {"default:paper", "group:wood"},
+               {"group:wood", "default:paper"} },
+       prison = {
+               {"xpanes:bar_flat", "xpanes:bar_flat",},
+               {"xpanes:bar_flat", "xpanes:bar_flat",},
+               {"xpanes:bar_flat", "xpanes:bar_flat"} },
+       rusty_prison = {
+               {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat",},
+               {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat",},
+               {"xpanes:rusty_bar_flat", "xpanes:rusty_bar_flat"} },
+       screen = {
+               {"group:wood", "group:wood"},
+               {"xpanes:chainlink_flat", "xpanes:chainlink_flat"},
+               {"group:wood", "group:wood"} },
+       slide = {
+               {"default:paper", "default:paper"},
+               {"default:paper", "default:paper"},
+               {"group:wood", "group:wood"} },
+       woodglass = {
+               {"default:glass", "default:glass"},
+               {"group:wood", "group:wood"},
+               {"group:wood", "group:wood"} }
+}
+
+for name, recipe in pairs(xdecor_doors) do
+       if not doors.register then break end
+       doors.register(name.."_door", {
+               tiles = {{name = "xdecor_"..name.."_door.png", backface_culling=true}},
+               description = name:gsub("%f[%w]%l", string.upper):gsub("_", " ").." Door",
+               inventory_image = "xdecor_"..name.."_door_inv.png",
+               protected = door_access(name),
+               groups = {choppy=2, cracky=2, oddly_breakable_by_hand=1, door=1},
+               recipe = recipe
+       })
+end
+
+xdecor.register("enderchest", {
+       description = "Ender Chest",
+       tiles = {"xdecor_enderchest_top.png", "xdecor_enderchest_top.png",
+                "xdecor_enderchest_side.png", "xdecor_enderchest_side.png",
+                "xdecor_enderchest_side.png", "xdecor_enderchest_front.png"},
+       groups = {cracky=1, choppy=1},
+       sounds = default.node_sound_stone_defaults(),
+       on_rotate = screwdriver.rotate_simple,
+       on_construct = function(pos)
+               local meta = minetest.get_meta(pos)
+               meta:set_string("formspec", [[ size[8,9]
+                               list[current_player;enderchest;0,0;8,4;]
+                               list[current_player;main;0,5;8,4;]
+                               listring[current_player;enderchest]
+                               listring[current_player;main] ]]
+                               ..xbg..default.get_hotbar_bg(0,5))
+               meta:set_string("infotext", "Ender Chest")
+       end
+})
+
+minetest.register_on_joinplayer(function(player)
+       local inv = player:get_inventory()
+       inv:set_size("enderchest", 8*4)
+end)
+
+xdecor.register("ivy", {
+       description = "Ivy",
+       drawtype = "signlike",
+       walkable = false,
+       climbable = true,
+       groups = {snappy=3, flora=1, attached_node=1, plant=1, flammable=3},
+       paramtype2 = "wallmounted",
+       selection_box = {type="wallmounted"},
+       tiles = {"xdecor_ivy.png"},
+       inventory_image = "xdecor_ivy.png",
+       wield_image = "xdecor_ivy.png",
+       sounds = default.node_sound_leaves_defaults()
+})
+
+xdecor.register("lantern", {
+       description = "Lantern",
+       light_source = 13,
+       drawtype = "plantlike",
+       inventory_image = "xdecor_lantern_inv.png",
+       wield_image = "xdecor_lantern_inv.png",
+       paramtype2 = "wallmounted",
+       walkable = false,
+       groups = {snappy=3, attached_node=1},
+       tiles = {{name = "xdecor_lantern.png", animation = {type="vertical_frames", length=1.5}}},
+       selection_box = xdecor.pixelbox(16, {{4, 0, 4, 8, 16, 8}})
+})
+
+for _, l in pairs({"iron", "wooden"}) do
+       xdecor.register(l.."_lightbox", {
+               description = l:gsub("^%l", string.upper).." Light Box",
+               tiles = {"xdecor_"..l.."_lightbox.png"},
+               groups = {cracky=3, choppy=3, oddly_breakable_by_hand=2},
+               light_source = 13,
+               sounds = default.node_sound_glass_defaults()
+       })
+end
+
+for _, f in pairs({"dandelion_white", "dandelion_yellow", "geranium",
+               "rose", "tulip", "viola"}) do
+       xdecor.register("potted_"..f, {
+               description = "Potted "..f:gsub("%f[%w]%l", string.upper):gsub("_", " "),
+               walkable = false,
+               groups = {snappy=3, flammable=3, plant=1, flower=1},
+               tiles = {"xdecor_"..f.."_pot.png"},
+               inventory_image = "xdecor_"..f.."_pot.png",
+               drawtype = "plantlike",
+               sounds = default.node_sound_leaves_defaults(),
+               selection_box = xdecor.nodebox.slab_y(0.3)
+       })
+
+       minetest.register_craft({
+               output = "xdecor:potted_"..f,
+               recipe = { {"default:clay_brick", "flowers:"..f, "default:clay_brick"},
+                          {"", "default:clay_brick", ""} }
+       })
+end
+
+local painting_box = {
+       type = "wallmounted",
+       wall_top = {-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125},
+       wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125},
+       wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375}
+}
+
+xdecor.register("painting_1", {
+       description = "Painting",
+       tiles = {"xdecor_painting_1.png"},
+       inventory_image = "xdecor_painting_empty.png",
+       wield_image = "xdecor_painting_empty.png",
+       paramtype2 = "wallmounted",
+       sunlight_propagates = true,
+       groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2, attached_node=1},
+       sounds = default.node_sound_wood_defaults(),
+       node_box = painting_box,
+       node_placement_prediction = "",
+       on_place = function(itemstack, placer, pointed_thing)
+               local num = math.random(4)
+               local leftover = minetest.item_place_node(ItemStack("xdecor:painting_"..num), placer, pointed_thing)
+               if leftover:get_count() == 0 and not minetest.setting_getbool("creative_mode") then
+                       itemstack:take_item()
+               end
+               return itemstack
+       end
+})
+
+for i = 2, 4 do
+       xdecor.register("painting_"..i, {
+               tiles = {"xdecor_painting_"..i..".png"},
+               paramtype2 = "wallmounted",
+               drop = "xdecor:painting_1",
+               sunlight_propagates = true,
+               groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2, attached_node=1, not_in_creative_inventory=1},
+               sounds = default.node_sound_wood_defaults(),
+               node_box = painting_box
+       })
+end
+
+xdecor.register("stonepath", {
+       description = "Garden Stone Path",
+       tiles = {"default_stone.png"},
+       groups = {snappy=3},
+       on_rotate = screwdriver.rotate_simple,
+       sounds = default.node_sound_stone_defaults(),
+       sunlight_propagates = true,
+       node_box = xdecor.pixelbox(16, {
+               {8, 0,  8, 6, .5, 6}, {1,  0, 1, 6, .5, 6},
+               {1, 0, 10, 5, .5, 5}, {10, 0, 2, 4, .5, 4}
+       }),
+       selection_box = xdecor.nodebox.slab_y(0.05)
+})
+
+function xdecor.register_hard_node(name, desc, def)
+       xdecor.register(name, {
+               description = desc,
+               tiles = {"xdecor_"..name..".png"},
+               groups = def.groups or {cracky=1},
+               sounds = def.sounds or default.node_sound_stone_defaults()
+       })
+end
+
+xdecor.register_hard_node("cactusbrick", "Cactus Brick", {})
+xdecor.register_hard_node("coalstone_tile", "Coal Stone Tile", {})
+xdecor.register_hard_node("desertstone_tile", "Desert Stone Tile", {})
+xdecor.register_hard_node("hard_clay", "Hardened Clay", {})
+xdecor.register_hard_node("moonbrick", "Moon Brick", {})
+xdecor.register_hard_node("stone_tile", "Stone Tile", {})
+xdecor.register_hard_node("stone_rune", "Runestone", {})
+xdecor.register_hard_node("packed_ice", "Packed Ice", {
+       groups = {cracky=1, puts_out_fire=1},
+       sounds = default.node_sound_glass_defaults()
+})
+xdecor.register_hard_node("wood_tile", "Wooden Tile", {
+       groups = {choppy=1, wood=1, flammable=2},
+       sounds = default.node_sound_wood_defaults()
+})
+
+xdecor.register("table", {
+       description = "Table",
+       tiles = {"xdecor_wood.png"},
+       groups = {choppy=2, oddly_breakable_by_hand=1, flammable=2},
+       sounds = default.node_sound_wood_defaults(),
+       node_box = xdecor.pixelbox(16, {
+               {0, 14, 0, 16, 2, 16}, {5.5, 0, 5.5, 5, 14, 6}
+       })
+})
+
+xdecor.register("tatami", {
+       description = "Tatami",
+       tiles = {"xdecor_tatami.png"},
+       wield_image = "xdecor_tatami.png",
+       groups = {snappy=3, flammable=3},
+       sunlight_propagates = true,
+       node_box = xdecor.nodebox.slab_y(0.0625)
+})
+
+xdecor.register("trampoline", {
+       description = "Trampoline",
+       tiles = {"xdecor_trampoline.png", "mailbox_blank16.png", "xdecor_trampoline_sides.png"},
+       groups = {cracky=3, oddly_breakable_by_hand=1, fall_damage_add_percent=-80, bouncy=90},
+       node_box = xdecor.nodebox.slab_y(0.5),
+       sounds = {footstep = {name="xdecor_bouncy", gain=0.8}}
+})
+
+xdecor.register("tv", {
+       description = "Television",
+       light_source = 11,
+       groups = {cracky=3, oddly_breakable_by_hand=2},
+       on_rotate = screwdriver.rotate_simple,
+       tiles = {"xdecor_television_left.png^[transformR270",
+                "xdecor_television_left.png^[transformR90",
+                "xdecor_television_left.png^[transformFX",
+                "xdecor_television_left.png", "xdecor_television_back.png",
+               {name="xdecor_television_front_animated.png",
+                animation = {type="vertical_frames", length=80.0}} }
+})
+
+xdecor.register("woodframed_glass", {
+       description = "Wood Framed Glass",
+       drawtype = "glasslike_framed",
+       sunlight_propagates = true,
+       tiles = {"xdecor_woodframed_glass.png", "xdecor_woodframed_glass_detail.png"},
+       groups = {cracky=2, oddly_breakable_by_hand=1},
+       sounds = default.node_sound_glass_defaults()
+})
+
diff --git a/src/recipes.lua b/src/recipes.lua
new file mode 100644 (file)
index 0000000..9e0b169
--- /dev/null
@@ -0,0 +1,373 @@
+minetest.register_craft({
+       output = "xdecor:baricade",
+       recipe = {
+               {"group:stick", "", "group:stick"},
+               {"", "default:steel_ingot", ""},
+               {"group:stick", "", "group:stick"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:barrel",
+       recipe = {
+               {"group:wood", "group:wood", "group:wood"},
+               {"default:iron_lump", "", "default:iron_lump"},
+               {"group:wood", "group:wood", "group:wood"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:bowl 3",
+       recipe = {
+               {"group:wood", "", "group:wood"},
+               {"", "group:wood", ""}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:candle",
+       recipe = {
+               {"default:torch"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cabinet",
+       recipe = {
+               {"group:wood", "group:wood", "group:wood"},
+               {"doors:trapdoor", "", "doors:trapdoor"},
+               {"group:wood", "group:wood", "group:wood"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cabinet_half 2",
+       recipe = {
+               {"xdecor:cabinet"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cactusbrick",
+       recipe = {
+               {"default:brick", "default:cactus"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cauldron_empty",
+       recipe = {
+               {"default:iron_lump", "", "default:iron_lump"},
+               {"default:iron_lump", "", "default:iron_lump"},
+               {"default:iron_lump", "default:iron_lump", "default:iron_lump"}
+       }
+})
+
+minetest.register_craft({
+       output = "realchess:chessboard",
+       recipe = {
+               {"dye:black", "dye:white", "dye:black"},
+               {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:chair",
+       recipe = {
+               {"group:stick", "", ""},
+               {"group:stick", "group:stick", "group:stick"},
+               {"group:stick", "", "group:stick"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:coalstone_tile 4",
+       recipe = {
+               {"default:coalblock", "default:stone"},
+               {"default:stone", "default:coalblock"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cobweb",
+       recipe = {
+               {"farming:cotton", "", "farming:cotton"},
+               {"", "farming:cotton", ""},
+               {"farming:cotton", "", "farming:cotton"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cushion 3",
+       recipe = {
+               {"wool:red", "wool:red", "wool:red"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:cushion_block",
+       recipe = {
+               {"xdecor:cushion"},
+               {"xdecor:cushion"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:desertstone_tile",
+       recipe = {
+               {"default:desert_cobble", "default:desert_cobble"},
+               {"default:desert_cobble", "default:desert_cobble"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:empty_shelf",
+       recipe = {
+               {"group:wood", "group:wood", "group:wood"},
+               {"", "", ""},
+               {"group:wood", "group:wood", "group:wood"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:enderchest",
+       recipe = {
+               {"", "default:obsidian", ""},
+               {"default:obsidian", "default:chest", "default:obsidian"},
+               {"", "default:obsidian", ""}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:enchantment_table",
+       recipe = {
+               {"", "default:book", ""},
+               {"default:diamond", "default:obsidian", "default:diamond"},
+               {"default:obsidian", "default:obsidian", "default:obsidian"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:itemframe",
+       recipe = {
+               {"group:stick", "group:stick", "group:stick"},
+               {"group:stick", "default:paper", "group:stick"},
+               {"group:stick", "group:stick", "group:stick"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:hammer",
+       recipe = {
+               {"default:steel_ingot", "group:stick", "default:steel_ingot"},
+               {"", "group:stick", ""}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:hard_clay",
+       recipe = {
+               {"default:clay", "default:clay"},
+               {"default:clay", "default:clay"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:hive",
+       recipe = {
+               {"group:stick", "group:stick", "group:stick"},
+               {"default:paper", "default:paper", "default:paper"},
+               {"group:stick", "group:stick", "group:stick"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:iron_lightbox",
+       recipe = {
+               {"xpanes:bar_flat", "default:torch", "xpanes:bar_flat"},
+               {"xpanes:bar_flat", "default:glass", "xpanes:bar_flat"},
+               {"xpanes:bar_flat", "default:torch", "xpanes:bar_flat"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:ivy 4",
+       recipe = {
+               {"group:leaves"},
+               {"group:leaves"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:lantern",
+       recipe = {
+               {"default:iron_lump"},
+               {"default:torch"},
+               {"default:iron_lump"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:lever_off",
+       recipe = {
+               {"group:stick"},
+               {"group:stone"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:mailbox",
+       recipe = {
+               {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
+               {"dye:red", "default:paper", "dye:red"},
+               {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:moonbrick",
+       recipe = {
+               {"default:brick", "default:stone"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:multishelf",
+       recipe = {
+               {"group:wood", "group:wood", "group:wood"},
+               {"group:vessel", "group:book", "group:vessel"},
+               {"group:wood", "group:wood", "group:wood"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:packed_ice",
+       recipe = {
+               {"default:ice", "default:ice"},
+               {"default:ice", "default:ice"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:painting_1",
+       recipe = {
+               {"default:sign_wall_wood", "dye:blue"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:pressure_stone_off",
+       type = "shapeless",
+       recipe = {"group:stone", "group:stone"}
+})
+
+minetest.register_craft({
+       output = "xdecor:pressure_wood_off",
+       type = "shapeless",
+       recipe = {"group:wood", "group:wood"}
+})
+
+minetest.register_craft({
+       output = "xdecor:rope",
+       recipe = {
+               {"farming:string"},
+               {"farming:string"},
+               {"farming:string"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:stone_tile 2",
+       recipe = {
+               {"default:cobble", "default:cobble"},
+               {"default:cobble", "default:cobble"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:stone_rune 4",
+       recipe = {
+               {"default:stone", "default:stone", "default:stone"},
+               {"default:stone", "", "default:stone"},
+               {"default:stone", "default:stone", "default:stone"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:stonepath 16",
+       recipe = {
+               {"stairs:slab_cobble", "", "stairs:slab_cobble"},
+               {"", "stairs:slab_cobble", ""},
+               {"stairs:slab_cobble", "", "stairs:slab_cobble"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:table",
+       recipe = {
+               {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"},
+               {"", "group:stick", ""},
+               {"", "group:stick", ""}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:tatami",
+       recipe = {
+               {"farming:wheat", "farming:wheat", "farming:wheat"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:trampoline",
+       recipe = {
+               {"farming:string", "farming:string", "farming:string"},
+               {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
+               {"default:steel_ingot", "", "default:steel_ingot"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:tv",
+       recipe = {
+               {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"},
+               {"default:steel_ingot", "default:glass", "default:steel_ingot"},
+               {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:workbench",
+       recipe = {
+               {"group:wood", "group:wood"},
+               {"group:wood", "group:wood"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:woodframed_glass",
+       recipe = {
+               {"group:stick", "group:stick", "group:stick"},
+               {"group:stick", "default:glass", "group:stick"},
+               {"group:stick", "group:stick", "group:stick"}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:wood_tile 2",
+       recipe = {
+               {"", "group:wood", ""},
+               {"group:wood", "", "group:wood"},
+               {"", "group:wood", ""}
+       }
+})
+
+minetest.register_craft({
+       output = "xdecor:wooden_lightbox",
+       recipe = {
+               {"group:stick", "default:torch", "group:stick"},
+               {"group:stick", "default:glass", "group:stick"},
+               {"group:stick", "default:torch", "group:stick"}
+       }
+})
+
diff --git a/src/rope.lua b/src/rope.lua
new file mode 100644 (file)
index 0000000..1627fd8
--- /dev/null
@@ -0,0 +1,57 @@
+local rope = {}
+
+-- Code by Mirko K. (modified by Temperest, Wulfsdad and kilbith) (License: GPL).
+function rope.place(itemstack, placer, pointed_thing)
+       if pointed_thing.type == "node" then
+               local pos = pointed_thing.above
+               local oldnode = minetest.get_node(pos)
+               local stackname = itemstack:get_name()
+               if minetest.is_protected(pos, placer:get_player_name()) then
+                       return itemstack
+               end
+
+               while oldnode.name == "air" and not itemstack:is_empty() do
+                       local newnode = {name = stackname, param1 = 0}
+                       minetest.set_node(pos, newnode)
+                       itemstack:take_item()
+                       pos.y = pos.y - 1
+                       oldnode = minetest.get_node(pos)
+               end
+       end
+       return itemstack
+end
+
+function rope.remove(pos, oldnode, digger, rope_name)
+       local num = 0
+       local below = {x=pos.x, y=pos.y, z=pos.z}
+       local digger_inv = digger:get_inventory()
+
+       while minetest.get_node(below).name == rope_name do
+               minetest.remove_node(below)
+               below.y = below.y - 1
+               num = num + 1
+       end
+       if num == 0 then return end
+       digger_inv:add_item("main", rope_name.." "..num)
+       return true
+end
+
+xdecor.register("rope", {
+       description = "Rope",
+       drawtype = "plantlike",
+       walkable = false,
+       climbable = true,
+       groups = {snappy=3, flammable=3},
+       tiles = {"xdecor_rope.png"},
+       inventory_image = "xdecor_rope_inv.png",
+       wield_image = "xdecor_rope_inv.png",
+       selection_box = xdecor.pixelbox(8, {{3, 0, 3, 2, 8, 2}}),
+       on_place = rope.place,
+       on_punch = function(pos, node, puncher, pointed_thing)
+               local player_name = puncher:get_player_name()
+               if not minetest.is_protected(pos, player_name) or
+                       minetest.get_player_privs(player_name).protection_bypass then
+                       rope.remove(pos, node, puncher, "xdecor:rope")
+               end
+       end
+})
diff --git a/src/workbench.lua b/src/workbench.lua
new file mode 100644 (file)
index 0000000..ccf1918
--- /dev/null
@@ -0,0 +1,273 @@
+local workbench = {}
+screwdriver = screwdriver or {}
+
+-- Nodes allowed to be cut.
+-- Only the regular, solid blocks without metas or explosivity can be cut.
+local nodes = {}
+for node, def in pairs(minetest.registered_nodes) do
+       if (def.drawtype == "normal" or def.drawtype:sub(1,5) == "glass") and
+          (def.groups.cracky or def.groups.choppy) and
+          not def.on_construct and
+          not def.after_place_node and
+          not def.on_rightclick and
+          not def.on_blast and
+          not def.allow_metadata_inventory_take and
+          not (def.groups.not_in_creative_inventory == 1) and
+          not def.groups.wool and
+          not def.description:find("Ore") and
+          def.description and
+          def.description ~= "" and
+          def.light_source == 0
+       then
+               nodes[#nodes+1] = node
+       end
+end
+
+-- Nodeboxes definitions.
+workbench.defs = {
+       -- Name       Yield   X  Y   Z  W   H  L
+       {"nanoslab",    16, { 0, 0,  0, 8,  1, 8  }},
+       {"micropanel",  16, { 0, 0,  0, 16, 1, 8  }},
+       {"microslab",   8,  { 0, 0,  0, 16, 1, 16 }},
+       {"thinstair",   8,  { 0, 7,  0, 16, 1, 8  },
+                           { 0, 15, 8, 16, 1, 8  }},
+       {"cube",        4,  { 0, 0,  0, 8,  8, 8  }},
+       {"panel",       4,  { 0, 0,  0, 16, 8, 8  }},
+       {"slab",        2,  nil                   },
+       {"doublepanel", 2,  { 0, 0,  0, 16, 8, 8  },
+                           { 0, 8,  8, 16, 8, 8  }},
+       {"halfstair",   2,  { 0, 0,  0, 8,  8, 16 },
+                           { 0, 8,  8, 8,  8, 8  }},
+       {"outerstair",  1,  { 0, 0,  0, 16, 8, 16 },
+                           { 0, 8,  8, 8,  8, 8  }},
+       {"stair",       1,  nil                   },
+       {"innerstair",  1,  { 0, 0,  0, 16, 8, 16 },
+                           { 0, 8,  8, 16, 8, 8  },
+                           { 0, 8,  0, 8,  8, 8  }}
+}
+
+-- Tools allowed to be repaired.
+function workbench:repairable(stack)
+       local tools = {"pick", "axe", "shovel", "sword", "hoe", "armor", "shield"}
+       for _, t in pairs(tools) do
+               if stack:find(t) then return true end
+       end
+       return false
+end
+
+function workbench:get_output(inv, input, name)
+       if inv:is_empty("input") then
+               inv:set_list("forms", {}) return
+       end
+
+       local output = {}
+       for _, n in pairs(self.defs) do
+               local count = math.min(n[2] * input:get_count(), input:get_stack_max())
+               local item = name.."_"..n[1]
+               if not n[3] then item = "stairs:"..n[1].."_"..name:match(":(.*)") end
+               output[#output+1] = item.." "..count
+       end
+       inv:set_list("forms", output)
+end
+
+local formspecs = {
+       -- Main formspec.
+       [[ label[0.9,1.23;Cut]
+          label[0.9,2.23;Repair]
+          box[-0.05,1;2.05,0.9;#555555]
+          box[-0.05,2;2.05,0.9;#555555]
+          button[0,0;2,1;craft;Crafting]
+          button[2,0;2,1;storage;Storage]
+          image[3,1;1,1;gui_furnace_arrow_bg.png^[transformR270]
+          image[0,1;1,1;worktable_saw.png]
+          image[0,2;1,1;worktable_anvil.png]
+          image[3,2;1,1;hammer_layout.png]
+          list[context;input;2,1;1,1;]
+          list[context;tool;2,2;1,1;]
+          list[context;hammer;3,2;1,1;]
+          list[context;forms;4,0;4,3;] ]],
+       -- Crafting formspec.
+       [[ image[5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]
+          button[0,0;1.5,1;back;< Back]
+          list[current_player;craft;2,0;3,3;]
+          list[current_player;craftpreview;6,1;1,1;]
+          listring[current_player;main]
+          listring[current_player;craft] ]],
+       -- Storage formspec.
+       [[ list[context;storage;0,1;8,2;]
+          button[0,0;1.5,1;back;< Back]
+          listring[context;storage]
+          listring[current_player;main] ]]
+}
+
+function workbench:set_formspec(meta, id)
+       meta:set_string("formspec", "size[8,7;]list[current_player;main;0,3.25;8,4;]"..
+                       formspecs[id]..xbg..default.get_hotbar_bg(0,3.25))
+end
+
+function workbench.construct(pos)
+       local meta = minetest.get_meta(pos)
+       local inv = meta:get_inventory()
+
+       inv:set_size("tool", 1)
+       inv:set_size("input", 1)
+       inv:set_size("hammer", 1)
+       inv:set_size("forms", 4*3)
+       inv:set_size("storage", 8*2)
+
+       meta:set_string("infotext", "Work Bench")
+       workbench:set_formspec(meta, 1)
+end
+
+function workbench.fields(pos, _, fields)
+       local meta = minetest.get_meta(pos)
+       if     fields.back    then workbench:set_formspec(meta, 1)
+       elseif fields.craft   then workbench:set_formspec(meta, 2)
+       elseif fields.storage then workbench:set_formspec(meta, 3) end
+end
+
+function workbench.dig(pos)
+       local inv = minetest.get_meta(pos):get_inventory()
+       return inv:is_empty("input") and inv:is_empty("hammer") and
+               inv:is_empty("tool") and inv:is_empty("storage")
+end
+
+function workbench.timer(pos)
+       local timer = minetest.get_node_timer(pos)
+       local inv = minetest.get_meta(pos):get_inventory()
+       local tool = inv:get_stack("tool", 1)
+       local hammer = inv:get_stack("hammer", 1)
+
+       if tool:is_empty() or hammer:is_empty() or tool:get_wear() == 0 then
+               timer:stop() return
+       end
+
+       -- Tool's wearing range: 0-65535 | 0 = new condition.
+       tool:add_wear(-500)
+       hammer:add_wear(700)
+
+       inv:set_stack("tool", 1, tool)
+       inv:set_stack("hammer", 1, hammer)
+       return true
+end
+
+function workbench.put(_, listname, _, stack)
+       local stackname = stack:get_name()
+       if (listname == "tool" and stack:get_wear() > 0 and workbench:repairable(stackname)) or
+          (listname == "input" and minetest.registered_nodes[stackname.."_cube"]) or
+          (listname == "hammer" and stackname == "xdecor:hammer") or
+           listname == "storage" then
+               return stack:get_count()
+       end
+       return 0
+end
+
+function workbench.take(_, listname, _, stack, player)
+       if listname == "forms" then
+               local inv = player:get_inventory()
+               if inv:room_for_item("main", stack:get_name()) then return -1 end
+               return 0
+       end
+       return stack:get_count()
+end
+
+function workbench.move(_, from_list, _, to_list, _, count)
+       if to_list == "storage" and from_list ~= "forms" then return count end
+       return 0
+end
+
+function workbench.on_put(pos, listname, _, stack)
+       local inv = minetest.get_meta(pos):get_inventory()
+       if listname == "input" then
+               local input = inv:get_stack("input", 1)
+               workbench:get_output(inv, input, stack:get_name())
+       elseif listname == "tool" or listname == "hammer" then
+               local timer = minetest.get_node_timer(pos)
+               timer:start(3.0)
+       end
+end
+
+function workbench.on_take(pos, listname, index, stack)
+       local inv = minetest.get_meta(pos):get_inventory()
+       local input = inv:get_stack("input", 1)
+
+       if listname == "input" then
+               if stack:get_name() == input:get_name() then
+                       workbench:get_output(inv, input, stack:get_name())
+               else
+                       inv:set_list("forms", {})
+               end
+       elseif listname == "forms" then
+               input:take_item(math.ceil(stack:get_count() / workbench.defs[index][2]))
+               inv:set_stack("input", 1, input)
+               workbench:get_output(inv, input, input:get_name())
+       end
+end
+
+xdecor.register("workbench", {
+       description = "Work Bench",
+       groups = {cracky=2, choppy=2, oddly_breakable_by_hand=1},
+       sounds = default.node_sound_wood_defaults(),
+       tiles = {"xdecor_workbench_top.png",   "xdecor_workbench_top.png",
+                "xdecor_workbench_sides.png", "xdecor_workbench_sides.png",
+                "xdecor_workbench_front.png", "xdecor_workbench_front.png"},
+       on_rotate = screwdriver.rotate_simple,
+       can_dig = workbench.dig,
+       on_timer = workbench.timer,
+       on_construct = workbench.construct,
+       on_receive_fields = workbench.fields,
+       on_metadata_inventory_put = workbench.on_put,
+       on_metadata_inventory_take = workbench.on_take,
+       allow_metadata_inventory_put = workbench.put,
+       allow_metadata_inventory_take = workbench.take,
+       allow_metadata_inventory_move = workbench.move
+})
+
+for _, d in pairs(workbench.defs) do
+for i = 1, #nodes do
+       local node = nodes[i]
+       local def = minetest.registered_nodes[node]
+
+       if d[3] then
+               local groups = {}
+               local tiles
+               groups.not_in_creative_inventory = 1
+
+               for k, v in pairs(def.groups) do
+                       if k ~= "wood" and k ~= "stone" and k ~= "level" then
+                               groups[k] = v
+                       end
+               end
+
+               if def.tiles then
+                       if #def.tiles > 1 and not (def.drawtype:sub(1,5) == "glass") then
+                               tiles = def.tiles
+                       else
+                               tiles = {def.tiles[1]}
+                       end
+               else
+                       tiles = {def.tile_images[1]}
+               end
+
+               if not minetest.registered_nodes["stairs:slab_"..node:match(":(.*)")] then
+                       stairs.register_stair_and_slab(node:match(":(.*)"), node, groups, tiles,
+                               def.description.." Stair", def.description.." Slab", def.sounds)
+               end
+
+               minetest.register_node(":"..node.."_"..d[1], {
+                       description = def.description.." "..d[1]:gsub("^%l", string.upper),
+                       paramtype = "light",
+                       paramtype2 = "facedir",
+                       drawtype = "nodebox",
+                       sounds = def.sounds,
+                       tiles = tiles,
+                       groups = groups,
+                       -- `unpack` has been changed to `table.unpack` in newest Lua versions.
+                       node_box = xdecor.pixelbox(16, {unpack(d, 3)}),
+                       sunlight_propagates = true,
+                       on_place = minetest.rotate_node
+               })
+       end
+end
+end
+
diff --git a/textures/xdecor_crafting_guide.png b/textures/xdecor_crafting_guide.png
deleted file mode 100644 (file)
index 4d08530..0000000
Binary files a/textures/xdecor_crafting_guide.png and /dev/null differ
diff --git a/workbench.lua b/workbench.lua
deleted file mode 100644 (file)
index ccf1918..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-local workbench = {}
-screwdriver = screwdriver or {}
-
--- Nodes allowed to be cut.
--- Only the regular, solid blocks without metas or explosivity can be cut.
-local nodes = {}
-for node, def in pairs(minetest.registered_nodes) do
-       if (def.drawtype == "normal" or def.drawtype:sub(1,5) == "glass") and
-          (def.groups.cracky or def.groups.choppy) and
-          not def.on_construct and
-          not def.after_place_node and
-          not def.on_rightclick and
-          not def.on_blast and
-          not def.allow_metadata_inventory_take and
-          not (def.groups.not_in_creative_inventory == 1) and
-          not def.groups.wool and
-          not def.description:find("Ore") and
-          def.description and
-          def.description ~= "" and
-          def.light_source == 0
-       then
-               nodes[#nodes+1] = node
-       end
-end
-
--- Nodeboxes definitions.
-workbench.defs = {
-       -- Name       Yield   X  Y   Z  W   H  L
-       {"nanoslab",    16, { 0, 0,  0, 8,  1, 8  }},
-       {"micropanel",  16, { 0, 0,  0, 16, 1, 8  }},
-       {"microslab",   8,  { 0, 0,  0, 16, 1, 16 }},
-       {"thinstair",   8,  { 0, 7,  0, 16, 1, 8  },
-                           { 0, 15, 8, 16, 1, 8  }},
-       {"cube",        4,  { 0, 0,  0, 8,  8, 8  }},
-       {"panel",       4,  { 0, 0,  0, 16, 8, 8  }},
-       {"slab",        2,  nil                   },
-       {"doublepanel", 2,  { 0, 0,  0, 16, 8, 8  },
-                           { 0, 8,  8, 16, 8, 8  }},
-       {"halfstair",   2,  { 0, 0,  0, 8,  8, 16 },
-                           { 0, 8,  8, 8,  8, 8  }},
-       {"outerstair",  1,  { 0, 0,  0, 16, 8, 16 },
-                           { 0, 8,  8, 8,  8, 8  }},
-       {"stair",       1,  nil                   },
-       {"innerstair",  1,  { 0, 0,  0, 16, 8, 16 },
-                           { 0, 8,  8, 16, 8, 8  },
-                           { 0, 8,  0, 8,  8, 8  }}
-}
-
--- Tools allowed to be repaired.
-function workbench:repairable(stack)
-       local tools = {"pick", "axe", "shovel", "sword", "hoe", "armor", "shield"}
-       for _, t in pairs(tools) do
-               if stack:find(t) then return true end
-       end
-       return false
-end
-
-function workbench:get_output(inv, input, name)
-       if inv:is_empty("input") then
-               inv:set_list("forms", {}) return
-       end
-
-       local output = {}
-       for _, n in pairs(self.defs) do
-               local count = math.min(n[2] * input:get_count(), input:get_stack_max())
-               local item = name.."_"..n[1]
-               if not n[3] then item = "stairs:"..n[1].."_"..name:match(":(.*)") end
-               output[#output+1] = item.." "..count
-       end
-       inv:set_list("forms", output)
-end
-
-local formspecs = {
-       -- Main formspec.
-       [[ label[0.9,1.23;Cut]
-          label[0.9,2.23;Repair]
-          box[-0.05,1;2.05,0.9;#555555]
-          box[-0.05,2;2.05,0.9;#555555]
-          button[0,0;2,1;craft;Crafting]
-          button[2,0;2,1;storage;Storage]
-          image[3,1;1,1;gui_furnace_arrow_bg.png^[transformR270]
-          image[0,1;1,1;worktable_saw.png]
-          image[0,2;1,1;worktable_anvil.png]
-          image[3,2;1,1;hammer_layout.png]
-          list[context;input;2,1;1,1;]
-          list[context;tool;2,2;1,1;]
-          list[context;hammer;3,2;1,1;]
-          list[context;forms;4,0;4,3;] ]],
-       -- Crafting formspec.
-       [[ image[5,1;1,1;gui_furnace_arrow_bg.png^[transformR270]
-          button[0,0;1.5,1;back;< Back]
-          list[current_player;craft;2,0;3,3;]
-          list[current_player;craftpreview;6,1;1,1;]
-          listring[current_player;main]
-          listring[current_player;craft] ]],
-       -- Storage formspec.
-       [[ list[context;storage;0,1;8,2;]
-          button[0,0;1.5,1;back;< Back]
-          listring[context;storage]
-          listring[current_player;main] ]]
-}
-
-function workbench:set_formspec(meta, id)
-       meta:set_string("formspec", "size[8,7;]list[current_player;main;0,3.25;8,4;]"..
-                       formspecs[id]..xbg..default.get_hotbar_bg(0,3.25))
-end
-
-function workbench.construct(pos)
-       local meta = minetest.get_meta(pos)
-       local inv = meta:get_inventory()
-
-       inv:set_size("tool", 1)
-       inv:set_size("input", 1)
-       inv:set_size("hammer", 1)
-       inv:set_size("forms", 4*3)
-       inv:set_size("storage", 8*2)
-
-       meta:set_string("infotext", "Work Bench")
-       workbench:set_formspec(meta, 1)
-end
-
-function workbench.fields(pos, _, fields)
-       local meta = minetest.get_meta(pos)
-       if     fields.back    then workbench:set_formspec(meta, 1)
-       elseif fields.craft   then workbench:set_formspec(meta, 2)
-       elseif fields.storage then workbench:set_formspec(meta, 3) end
-end
-
-function workbench.dig(pos)
-       local inv = minetest.get_meta(pos):get_inventory()
-       return inv:is_empty("input") and inv:is_empty("hammer") and
-               inv:is_empty("tool") and inv:is_empty("storage")
-end
-
-function workbench.timer(pos)
-       local timer = minetest.get_node_timer(pos)
-       local inv = minetest.get_meta(pos):get_inventory()
-       local tool = inv:get_stack("tool", 1)
-       local hammer = inv:get_stack("hammer", 1)
-
-       if tool:is_empty() or hammer:is_empty() or tool:get_wear() == 0 then
-               timer:stop() return
-       end
-
-       -- Tool's wearing range: 0-65535 | 0 = new condition.
-       tool:add_wear(-500)
-       hammer:add_wear(700)
-
-       inv:set_stack("tool", 1, tool)
-       inv:set_stack("hammer", 1, hammer)
-       return true
-end
-
-function workbench.put(_, listname, _, stack)
-       local stackname = stack:get_name()
-       if (listname == "tool" and stack:get_wear() > 0 and workbench:repairable(stackname)) or
-          (listname == "input" and minetest.registered_nodes[stackname.."_cube"]) or
-          (listname == "hammer" and stackname == "xdecor:hammer") or
-           listname == "storage" then
-               return stack:get_count()
-       end
-       return 0
-end
-
-function workbench.take(_, listname, _, stack, player)
-       if listname == "forms" then
-               local inv = player:get_inventory()
-               if inv:room_for_item("main", stack:get_name()) then return -1 end
-               return 0
-       end
-       return stack:get_count()
-end
-
-function workbench.move(_, from_list, _, to_list, _, count)
-       if to_list == "storage" and from_list ~= "forms" then return count end
-       return 0
-end
-
-function workbench.on_put(pos, listname, _, stack)
-       local inv = minetest.get_meta(pos):get_inventory()
-       if listname == "input" then
-               local input = inv:get_stack("input", 1)
-               workbench:get_output(inv, input, stack:get_name())
-       elseif listname == "tool" or listname == "hammer" then
-               local timer = minetest.get_node_timer(pos)
-               timer:start(3.0)
-       end
-end
-
-function workbench.on_take(pos, listname, index, stack)
-       local inv = minetest.get_meta(pos):get_inventory()
-       local input = inv:get_stack("input", 1)
-
-       if listname == "input" then
-               if stack:get_name() == input:get_name() then
-                       workbench:get_output(inv, input, stack:get_name())
-               else
-                       inv:set_list("forms", {})
-               end
-       elseif listname == "forms" then
-               input:take_item(math.ceil(stack:get_count() / workbench.defs[index][2]))
-               inv:set_stack("input", 1, input)
-               workbench:get_output(inv, input, input:get_name())
-       end
-end
-
-xdecor.register("workbench", {
-       description = "Work Bench",
-       groups = {cracky=2, choppy=2, oddly_breakable_by_hand=1},
-       sounds = default.node_sound_wood_defaults(),
-       tiles = {"xdecor_workbench_top.png",   "xdecor_workbench_top.png",
-                "xdecor_workbench_sides.png", "xdecor_workbench_sides.png",
-                "xdecor_workbench_front.png", "xdecor_workbench_front.png"},
-       on_rotate = screwdriver.rotate_simple,
-       can_dig = workbench.dig,
-       on_timer = workbench.timer,
-       on_construct = workbench.construct,
-       on_receive_fields = workbench.fields,
-       on_metadata_inventory_put = workbench.on_put,
-       on_metadata_inventory_take = workbench.on_take,
-       allow_metadata_inventory_put = workbench.put,
-       allow_metadata_inventory_take = workbench.take,
-       allow_metadata_inventory_move = workbench.move
-})
-
-for _, d in pairs(workbench.defs) do
-for i = 1, #nodes do
-       local node = nodes[i]
-       local def = minetest.registered_nodes[node]
-
-       if d[3] then
-               local groups = {}
-               local tiles
-               groups.not_in_creative_inventory = 1
-
-               for k, v in pairs(def.groups) do
-                       if k ~= "wood" and k ~= "stone" and k ~= "level" then
-                               groups[k] = v
-                       end
-               end
-
-               if def.tiles then
-                       if #def.tiles > 1 and not (def.drawtype:sub(1,5) == "glass") then
-                               tiles = def.tiles
-                       else
-                               tiles = {def.tiles[1]}
-                       end
-               else
-                       tiles = {def.tile_images[1]}
-               end
-
-               if not minetest.registered_nodes["stairs:slab_"..node:match(":(.*)")] then
-                       stairs.register_stair_and_slab(node:match(":(.*)"), node, groups, tiles,
-                               def.description.." Stair", def.description.." Slab", def.sounds)
-               end
-
-               minetest.register_node(":"..node.."_"..d[1], {
-                       description = def.description.." "..d[1]:gsub("^%l", string.upper),
-                       paramtype = "light",
-                       paramtype2 = "facedir",
-                       drawtype = "nodebox",
-                       sounds = def.sounds,
-                       tiles = tiles,
-                       groups = groups,
-                       -- `unpack` has been changed to `table.unpack` in newest Lua versions.
-                       node_box = xdecor.pixelbox(16, {unpack(d, 3)}),
-                       sunlight_propagates = true,
-                       on_place = minetest.rotate_node
-               })
-       end
-end
-end
-