+++ /dev/null
-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")
-
+++ /dev/null
-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
-})
-
+++ /dev/null
-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
-})
-
+++ /dev/null
-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)
-})
-
+++ /dev/null
-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"}
- }
-})
-
+++ /dev/null
-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
-})
-
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))
-
+++ /dev/null
-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
-})
-
+++ /dev/null
-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
-})
+++ /dev/null
---[[ 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"
-})
-
+++ /dev/null
-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()
-})
-
+++ /dev/null
-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"}
- }
-})
-
+++ /dev/null
-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
-})
--- /dev/null
+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")
+
--- /dev/null
+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
+})
+
--- /dev/null
+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)
+})
+
--- /dev/null
+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"}
+ }
+})
+
--- /dev/null
+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
+})
+
--- /dev/null
+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
+})
+
--- /dev/null
+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
+})
--- /dev/null
+--[[ 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"
+})
+
--- /dev/null
+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()
+})
+
--- /dev/null
+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"}
+ }
+})
+
--- /dev/null
+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
+})
--- /dev/null
+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
+
+++ /dev/null
-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
-