poikilos
6 years ago
committed by
Jacob Gustafson
18 changed files with 3322 additions and 0 deletions
@ -0,0 +1 @@ |
|||
See "oldcoder.txt". |
@ -0,0 +1,39 @@ |
|||
┌──────────────────────────────────────────────────────────────────────┐ |
|||
│ Copyright (c) 2015-2017 kilbith <jeanpatrick.guerrero@gmail.com> │ |
|||
│ │ |
|||
│ Code: BSD │ |
|||
│ Textures: WTFPL (credits: Gambit, kilbith, Cisoun) │ |
|||
│ Sounds: │ |
|||
│ - xdecor_boiling_water.ogg - by Audionautics - CC BY-SA │ |
|||
│ freesound.org/people/Audionautics/sounds/133901/ │ |
|||
│ - xdecor_enchanting.ogg - by Timbre - CC BY-SA-NC │ |
|||
│ freesound.org/people/Timbre/sounds/221683/ │ |
|||
│ - xdecor_bouncy.ogg - by Blender Foundation - CC BY 3.0 │ |
|||
│ opengameart.org/content/funny-comic-cartoon-bounce-sound │ |
|||
└──────────────────────────────────────────────────────────────────────┘ |
|||
|
|||
|
|||
Copyright (c) 1998, Regents of the University of California |
|||
All rights reserved. |
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are met: |
|||
|
|||
* Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright |
|||
notice, this list of conditions and the following disclaimer in the |
|||
documentation and/or other materials provided with the distribution. |
|||
* Neither the name of the University of California, Berkeley nor the |
|||
names of its contributors may be used to endorse or promote products |
|||
derived from this software without specific prior written permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY |
|||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY |
|||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,50 @@ |
|||
# Minetest Handpainted Texture Pack |
|||
|
|||
**!!! WORK IN PROGRESS !!!** |
|||
|
|||
This will be a high-res (128x128) texture pack for Minetest. Its license is CC0 1.0. |
|||
|
|||
The files in this repo are actually [webtoon](https://github.com/pithydon/webtoon) |
|||
CC0 texture pack, which I keep rewriting with the new textures. |
|||
|
|||
The textures are largely my own work, but a lot of them are taken out of other |
|||
CC0 works. |
|||
|
|||
I won't be commiting extremely often in order to not bloat the repo with binary file |
|||
changes. |
|||
|
|||
Most notable texture sources (feel free to send me more sources or your own contributions): |
|||
|
|||
- https://www.blendswap.com/blends/view/74021 |
|||
- https://opengameart.org/content/glitch-sprite-assets-huge-collection |
|||
- https://opengameart.org/content/glitch-alpine-landscape-svg |
|||
- https://opengameart.org/content/handpainted-tileable-textures-512%D1%85512 |
|||
- https://opengameart.org/content/handpainted-stone-wall-textures |
|||
- https://opengameart.org/content/4-hand-painted-ground-textures |
|||
- https://opengameart.org/content/rpg-item-collection-3 |
|||
- https://opengameart.org/content/rpg-item-collection-2 |
|||
- https://opengameart.org/content/rpg-item-collection-1 |
|||
- https://opengameart.org/content/crate-barrel-bundle |
|||
- https://opengameart.org/content/desert-rock |
|||
- https://opengameart.org/content/glitch-groddle-forestmeadow-terrain-svg |
|||
- https://opengameart.org/content/free-handpainted-plants-2 |
|||
- https://opengameart.org/content/free-handpainted-plants |
|||
- https://opengameart.org/content/chest-blizzard-style |
|||
- https://opengameart.org/content/free-lowpoly-golds |
|||
- https://opengameart.org/content/stone-coffin |
|||
- https://opengameart.org/content/free-textures-pack-59 |
|||
- https://www.blendswap.com/blends/view/46952 |
|||
- https://www.blendswap.com/blends/view/73730 |
|||
- https://opengameart.org/content/wyrmsun-cc0-over-900-items |
|||
- https://opengameart.org/content/40-procedural-textures |
|||
- https://opengameart.org/content/procedural-texture-pack?page=1 |
|||
- https://opengameart.org/content/cool-leaves-textures |
|||
- https://www.deviantart.com/yughues/art/Free-IDKWIAD-3-730335893 |
|||
- https://www.deviantart.com/yughues/art/Free-IDKWIAD-4-732217780 |
|||
- https://opengameart.org/content/freebies-mundo-commissions |
|||
- https://pixabay.com/en/floral-paisley-background-flower-1556345/ |
|||
- https://deepart.io |
|||
- https://opengameart.org/content/fantasy-crystal-set |
|||
- https://opengameart.org/content/cute-prop-models |
|||
- https://www.blendswap.com/blends/view/89476 |
|||
- https://pixabay.com/en/bread-food-bakery-foodstuff-baking-3365842/ |
@ -0,0 +1 @@ |
|||
minetest.register_alias("xdecor:crafting_guide", "craftguide:book") |
@ -0,0 +1,892 @@ |
|||
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 |
|||
|
|||
local function get_square(a, b) |
|||
return (a * 8) - (8 - b) |
|||
end |
|||
|
|||
local chat_prefix = minetest.colorize("#FFFF00", "[Chess] ") |
|||
local letters = {'A','B','C','D','E','F','G','H'} |
|||
|
|||
local rowDirs = {-1, -1, -1, 0, 0, 1, 1, 1} |
|||
local colDirs = {-1, 0, 1, -1, 1, -1, 0, 1} |
|||
|
|||
local bishopThreats = {true, false, true, false, false, true, false, true} |
|||
local rookThreats = {false, true, false, true, true, false, true, false} |
|||
local queenThreats = {true, true, true, true, true, true, true, true} |
|||
local kingThreats = {true, true, true, true, true, true, true, true} |
|||
|
|||
local function board_to_table(inv) |
|||
local t = {} |
|||
for i = 1, 64 do |
|||
t[#t + 1] = inv:get_stack("board", i):get_name() |
|||
end |
|||
|
|||
return t |
|||
end |
|||
|
|||
local function attacked(color, idx, board) |
|||
local threatDetected = false |
|||
local kill = color == "white" |
|||
local pawnThreats = {kill, false, kill, false, false, not kill, false, not kill} |
|||
|
|||
for dir = 1, 8 do |
|||
if not threatDetected then |
|||
local col, row = index_to_xy(idx) |
|||
col, row = col + 1, row + 1 |
|||
|
|||
for step = 1, 8 do |
|||
row = row + rowDirs[dir] |
|||
col = col + colDirs[dir] |
|||
|
|||
if row >= 1 and row <= 8 and col >= 1 and col <= 8 then |
|||
local square = get_square(row, col) |
|||
local square_name = board[square] |
|||
local piece, pieceColor = square_name:match(":(%w+)_(%w+)") |
|||
|
|||
if piece then |
|||
if pieceColor ~= color then |
|||
if piece == "bishop" and bishopThreats[dir] then |
|||
threatDetected = true |
|||
elseif piece == "rook" and rookThreats[dir] then |
|||
threatDetected = true |
|||
elseif piece == "queen" and queenThreats[dir] then |
|||
threatDetected = true |
|||
else |
|||
if step == 1 then |
|||
if piece == "pawn" and pawnThreats[dir] then |
|||
threatDetected = true |
|||
end |
|||
if piece == "king" and kingThreats[dir] then |
|||
threatDetected = true |
|||
end |
|||
end |
|||
end |
|||
end |
|||
break |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
|
|||
return threatDetected |
|||
end |
|||
|
|||
local function locate_kings(board) |
|||
local Bidx, Widx |
|||
for i = 1, 64 do |
|||
local piece, color = board[i]:match(":(%w+)_(%w+)") |
|||
if piece == "king" then |
|||
if color == "black" then |
|||
Bidx = i |
|||
else |
|||
Widx = i |
|||
end |
|||
end |
|||
end |
|||
|
|||
return Bidx, Widx |
|||
end |
|||
|
|||
local pieces = { |
|||
"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" |
|||
} |
|||
|
|||
local pieces_str, x = "", 0 |
|||
for i = 1, #pieces do |
|||
local p = pieces[i]:match(":(%w+_%w+)") |
|||
if pieces[i]:find(":(%w+)_(%w+)") and not pieces_str:find(p) then |
|||
pieces_str = pieces_str .. x .. "=" .. p .. ".png," |
|||
x = x + 1 |
|||
end |
|||
end |
|||
pieces_str = pieces_str .. "69=mailbox_blank16.png" |
|||
|
|||
local fs = [[ |
|||
size[14.7,10;] |
|||
no_prepend[] |
|||
bgcolor[#080808BB;true] |
|||
background[0,0;14.7,10;chess_bg.png] |
|||
list[context;board;0.3,1;8,8;] |
|||
listcolors[#00000000;#00000000;#00000000;#30434C;#FFF] |
|||
tableoptions[background=#00000000;highlight=#00000000;border=false] |
|||
button[10.5,8.5;2,2;new;New game] |
|||
]] .. "tablecolumns[image," .. pieces_str .. |
|||
";text;color;text;color;text;image," .. pieces_str .. "]" |
|||
|
|||
local function get_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, from_x, to_x, from_y, to_y) |
|||
local moves = meta:get_string("moves") |
|||
local pieceFrom_s = pieceFrom:match(":(%w+_%w+)") |
|||
local pieceFrom_si_id = pieces_str:match("(%d+)=" .. pieceFrom_s) |
|||
local pieceTo_si_id = pieceTo_s ~= "" and pieces_str:match("(%d+)=" .. pieceTo_s) or "" |
|||
|
|||
local coordFrom = letters[from_x + 1] .. math.abs(from_y - 8) |
|||
local coordTo = letters[to_x + 1] .. math.abs(to_y - 8) |
|||
|
|||
local new_moves = pieceFrom_si_id .. "," .. |
|||
coordFrom .. "," .. |
|||
(pieceTo ~= "" and "#33FF33" or "#FFFFFF") .. ", > ,#FFFFFF," .. |
|||
coordTo .. "," .. |
|||
(pieceTo ~= "" and pieceTo_si_id or "69") .. "," .. |
|||
moves |
|||
|
|||
meta:set_string("moves", new_moves) |
|||
end |
|||
|
|||
local function get_eaten_list(meta, pieceTo, pieceTo_s) |
|||
local eaten = meta:get_string("eaten") |
|||
if pieceTo ~= "" then |
|||
eaten = eaten .. pieceTo_s .. "," |
|||
end |
|||
|
|||
meta:set_string("eaten", eaten) |
|||
|
|||
local eaten_t = string.split(eaten, ",") |
|||
local eaten_img = "" |
|||
|
|||
local a, b = 0, 0 |
|||
for i = 1, #eaten_t do |
|||
local is_white = eaten_t[i]:sub(-5,-1) == "white" |
|||
local X = (is_white and a or b) % 4 |
|||
local Y = ((is_white and a or b) % 16 - X) / 4 |
|||
|
|||
if is_white then |
|||
a = a + 1 |
|||
else |
|||
b = b + 1 |
|||
end |
|||
|
|||
eaten_img = eaten_img .. |
|||
"image[" .. ((X + (is_white and 11.7 or 8.8)) - (X * 0.45)) .. "," .. |
|||
((Y + 5.56) - (Y * 0.2)) .. ";1,1;" .. eaten_t[i] .. ".png]" |
|||
end |
|||
|
|||
meta:set_string("eaten_img", eaten_img) |
|||
end |
|||
|
|||
function realchess.init(pos) |
|||
local meta = minetest.get_meta(pos) |
|||
local inv = meta:get_inventory() |
|||
|
|||
meta:set_string("formspec", fs) |
|||
meta:set_string("infotext", "Chess Board") |
|||
meta:set_string("playerBlack", "") |
|||
meta:set_string("playerWhite", "") |
|||
meta:set_string("lastMove", "") |
|||
meta:set_string("blackAttacked", "") |
|||
meta:set_string("whiteAttacked", "") |
|||
|
|||
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) |
|||
|
|||
meta:set_string("moves", "") |
|||
meta:set_string("eaten", "") |
|||
|
|||
inv:set_list("board", pieces) |
|||
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 meta = minetest.get_meta(pos) |
|||
local playerName = player:get_player_name() |
|||
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 playerWhite = meta:get_string("playerWhite") |
|||
local playerBlack = meta:get_string("playerBlack") |
|||
local thisMove -- Will replace lastMove when move is legal |
|||
|
|||
if pieceFrom:find("white") then |
|||
if playerWhite ~= "" and playerWhite ~= playerName then |
|||
minetest.chat_send_player(playerName, chat_prefix .. "Someone else plays white pieces!") |
|||
return 0 |
|||
end |
|||
|
|||
if lastMove ~= "" and lastMove ~= "black" then |
|||
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, chat_prefix .. "Someone else plays black pieces!") |
|||
return 0 |
|||
end |
|||
|
|||
if lastMove ~= "" and lastMove ~= "white" then |
|||
return 0 |
|||
end |
|||
|
|||
if pieceTo:find("black") then |
|||
-- Don't replace pieces of same color |
|||
return 0 |
|||
end |
|||
|
|||
playerBlack = playerName |
|||
thisMove = "black" |
|||
end |
|||
|
|||
-- MOVE LOGIC |
|||
|
|||
local from_x, from_y = index_to_xy(from_index) |
|||
local to_x, to_y = index_to_xy(to_index) |
|||
|
|||
-- PAWN |
|||
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 |
|||
|
|||
--[[ |
|||
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("black") 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 |
|||
|
|||
-- ROOK |
|||
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 |
|||
|
|||
-- KNIGHT |
|||
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 |
|||
|
|||
-- BISHOP |
|||
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 |
|||
|
|||
-- QUEEN |
|||
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 |
|||
|
|||
-- KING |
|||
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 |
|||
|
|||
local board = board_to_table(inv) |
|||
board[to_index] = board[from_index] |
|||
board[from_index] = "" |
|||
|
|||
local black_king_idx, white_king_idx = locate_kings(board) |
|||
local blackAttacked = attacked("black", black_king_idx, board) |
|||
local whiteAttacked = attacked("white", white_king_idx, board) |
|||
|
|||
if blackAttacked then |
|||
if thisMove == "black" and meta:get_string("blackAttacked") == "true" then |
|||
return 0 |
|||
else |
|||
meta:set_string("blackAttacked", "true") |
|||
end |
|||
else |
|||
meta:set_string("blackAttacked", "") |
|||
end |
|||
|
|||
if whiteAttacked then |
|||
if thisMove == "white" and meta:get_string("whiteAttacked") == "true" then |
|||
return 0 |
|||
else |
|||
meta:set_string("whiteAttacked", "true") |
|||
end |
|||
else |
|||
meta:set_string("whiteAttacked", "") |
|||
end |
|||
|
|||
lastMove = thisMove |
|||
|
|||
meta:set_string("lastMove", lastMove) |
|||
meta:set_int("lastMoveTime", minetest.get_gametime()) |
|||
meta:set_string("playerWhite", playerWhite) |
|||
meta:set_string("playerBlack", playerBlack) |
|||
|
|||
local pieceTo_s = pieceTo ~= "" and pieceTo:match(":(%w+_%w+)") or "" |
|||
get_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, from_x, to_x, from_y, to_y) |
|||
get_eaten_list(meta, pieceTo, pieceTo_s) |
|||
|
|||
return 1 |
|||
end |
|||
|
|||
function realchess.on_move(pos, from_list, from_index) |
|||
local meta = minetest.get_meta(pos) |
|||
local inv = meta:get_inventory() |
|||
inv:set_stack(from_list, from_index, '') |
|||
|
|||
local black_king_attacked = meta:get_string("blackAttacked") == "true" |
|||
local white_king_attacked = meta:get_string("whiteAttacked") == "true" |
|||
|
|||
local playerWhite = meta:get_string("playerWhite") |
|||
local playerBlack = meta:get_string("playerBlack") |
|||
|
|||
local moves = meta:get_string("moves") |
|||
local eaten_img = meta:get_string("eaten_img") |
|||
local lastMove = meta:get_string("lastMove") |
|||
local turnBlack = minetest.colorize("#000001", (lastMove == "white" and playerBlack ~= "") and |
|||
playerBlack .. "..." or playerBlack) |
|||
local turnWhite = minetest.colorize("#000001", (lastMove == "black" and playerWhite ~= "") and |
|||
playerWhite .. "..." or playerWhite) |
|||
local check_s = minetest.colorize("#FF0000", "\\[check\\]") |
|||
|
|||
local formspec = fs .. |
|||
"label[1.9,0.3;" .. turnBlack .. (black_king_attacked and " " .. check_s or "") .. "]" .. |
|||
"label[1.9,9.15;" .. turnWhite .. (white_king_attacked and " " .. check_s or "") .. "]" .. |
|||
"table[8.9,1.05;5.07,3.75;moves;" .. moves:sub(1,-2) .. ";1]" .. |
|||
eaten_img |
|||
|
|||
meta:set_string("formspec", formspec) |
|||
|
|||
return false |
|||
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 then |
|||
if (playerWhite == playerName or playerBlack == playerName) then |
|||
realchess.init(pos) |
|||
|
|||
elseif lastMoveTime ~= 0 then |
|||
if minetest.get_gametime() >= timeout_limit and |
|||
(playerWhite ~= playerName or playerBlack ~= playerName) then |
|||
realchess.init(pos) |
|||
else |
|||
minetest.chat_send_player(playerName, chat_prefix .. |
|||
"You can't reset the chessboard, a game has been started. " .. |
|||
"If you aren't a current player, try again in " .. |
|||
timeout_format(timeout_limit)) |
|||
end |
|||
end |
|||
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, chat_prefix .. |
|||
"You can't dig the chessboard, a game has been started. " .. |
|||
"Reset it first if you're a current player, or dig it again in " .. |
|||
timeout_format(timeout_limit)) |
|||
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") |
|||
|
|||
-- Recipes |
|||
|
|||
minetest.register_craft({ |
|||
output = "realchess:chessboard", |
|||
recipe = { |
|||
{"dye:black", "dye:white", "dye:black"}, |
|||
{"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"} |
|||
} |
|||
}) |
@ -0,0 +1,236 @@ |
|||
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 the function `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 not next(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 |
|||
}) |
|||
|
|||
-- Craft items |
|||
|
|||
minetest.register_craftitem("xdecor:bowl", { |
|||
description = "Bowl", |
|||
inventory_image = "xdecor_bowl.png", |
|||
wield_image = "xdecor_bowl.png", |
|||
groups = {food_bowl = 1, flammable = 2}, |
|||
}) |
|||
|
|||
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 = minetest.item_eat(30, "xdecor:bowl") |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
minetest.register_craft({ |
|||
output = "xdecor:bowl 3", |
|||
recipe = { |
|||
{"group:wood", "", "group:wood"}, |
|||
{"", "group:wood", ""} |
|||
} |
|||
}) |
|||
|
|||
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"} |
|||
} |
|||
}) |
@ -0,0 +1,291 @@ |
|||
screwdriver = screwdriver or {} |
|||
local ceil, abs, random = math.ceil, math.abs, math.random |
|||
|
|||
-- Cost in Mese crystal(s) for enchanting. |
|||
local mese_cost = 1 |
|||
|
|||
-- Force of the enchantments. |
|||
local enchanting = { |
|||
uses = 1.2, -- Durability |
|||
times = 0.1, -- Efficiency |
|||
damages = 1, -- Sharpness |
|||
} |
|||
|
|||
local function cap(S) return S:gsub("^%l", string.upper) end |
|||
local function to_percent(orig_value, final_value) |
|||
return abs(ceil(((final_value - orig_value) / orig_value) * 100)) |
|||
end |
|||
|
|||
function enchanting:get_tooltip(enchant, orig_caps, fleshy) |
|||
local bonus = {durable=0, efficiency=0, damages=0} |
|||
if orig_caps then |
|||
bonus.durable = to_percent(orig_caps.uses, orig_caps.uses * enchanting.uses) |
|||
local sum_caps_times = 0 |
|||
for i=1, #orig_caps.times do |
|||
sum_caps_times = sum_caps_times + orig_caps.times[i] |
|||
end |
|||
local average_caps_time = sum_caps_times / #orig_caps.times |
|||
bonus.efficiency = to_percent(average_caps_time, average_caps_time - |
|||
enchanting.times) |
|||
end |
|||
if fleshy then |
|||
bonus.damages = to_percent(fleshy, fleshy + enchanting.damages) |
|||
end |
|||
|
|||
local specs = { -- not finished, to complete |
|||
durable = {"#00baff", " (+"..bonus.durable.."%)"}, |
|||
fast = {"#74ff49", " (+"..bonus.efficiency.."%)"}, |
|||
sharp = {"#ffff00", " (+"..bonus.damages.."%)"}, |
|||
} |
|||
return minetest.colorize and minetest.colorize(specs[enchant][1], |
|||
"\n"..cap(enchant)..specs[enchant][2]) or |
|||
"\n"..cap(enchant)..specs[enchant][2] |
|||
end |
|||
|
|||
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,2.9;4,0.92;bg_btn.png;sharp;Sharpness]", |
|||
} |
|||
|
|||
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;] |
|||
listring[current_player;main] |
|||
listring[context;tool] |
|||
listring[current_player;main] |
|||
listring[context;mese] |
|||
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] ]] |
|||
..default.gui_slots..default.get_hotbar_bg(0.5,4.5) |
|||
|
|||
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", |
|||
"sword", |
|||
} |
|||
|
|||
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 stackname = stack:get_name() |
|||
if listname == "mese" and stackname == "default:mese_crystal" then |
|||
return stack:get_count() |
|||
elseif listname == "tool" and allowed(stackname:match("[^:]+$")) 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(0.5) |
|||
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[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 = 1.5, |
|||
glow = 5, |
|||
texture = "xdecor_glyph"..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}, |
|||
light_source = 6, |
|||
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 |
|||
}) |
|||
|
|||
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 |
|||
local original_toolcaps = original_tool.tool_capabilities |
|||
|
|||
if original_toolcaps then |
|||
local original_damage_groups = original_toolcaps.damage_groups |
|||
local original_groupcaps = original_toolcaps.groupcaps |
|||
local groupcaps = table.copy(original_groupcaps) |
|||
local fleshy = original_damage_groups.fleshy |
|||
local full_punch_interval = original_toolcaps.full_punch_interval |
|||
local max_drop_level = original_toolcaps.max_drop_level |
|||
local group = next(original_groupcaps) |
|||
|
|||
if enchant == "durable" then |
|||
groupcaps[group].uses = 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).. |
|||
self:get_tooltip(enchant, original_groupcaps[group], fleshy), |
|||
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 |
|||
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"} |
|||
} |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
minetest.register_craft({ |
|||
output = "xdecor:enchantment_table", |
|||
recipe = { |
|||
{"", "default:book", ""}, |
|||
{"default:diamond", "default:obsidian", "default:diamond"}, |
|||
{"default:obsidian", "default:obsidian", "default:obsidian"} |
|||
} |
|||
}) |
@ -0,0 +1,91 @@ |
|||
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;] |
|||
listring[current_player;main] |
|||
listring[context;honey] ]] |
|||
..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 |
|||
}) |
|||
|
|||
-- Craft items |
|||
|
|||
minetest.register_craftitem("xdecor:honey", { |
|||
description = "Honey", |
|||
inventory_image = "xdecor_honey.png", |
|||
wield_image = "xdecor_honey.png", |
|||
groups = {food_honey = 1, food_sugar = 1, flammable = 2, not_in_creative_inventory=1}, |
|||
on_use = minetest.item_eat(2) |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
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"} |
|||
} |
|||
}) |
@ -0,0 +1,47 @@ |
|||
--local t = os.clock() |
|||
|
|||
local mver_major, mver_minor, mver_patch = 0, 4, 16 -- Minetest 0.4.16 minimum. |
|||
|
|||
local client_version = minetest.get_version().string |
|||
local major, minor, patch = client_version:match("(%d+).(%d+).(%d+)") |
|||
|
|||
if (major and minor and patch) and |
|||
((tonumber(major) < mver_major) or |
|||
(mver_major == tonumber(major) and tonumber(minor) < mver_minor) or |
|||
(mver_minor == tonumber(minor) and tonumber(patch) < mver_patch)) then |
|||
minetest.log("error", "[xdecor] Your Minetest client is too old to run this mod. Disabling.") |
|||
return |
|||
end |
|||
|
|||
xdecor = {} |
|||
local modpath = minetest.get_modpath("xdecor") |
|||
|
|||
dofile(modpath.."/handlers/animations.lua") |
|||
dofile(modpath.."/handlers/helpers.lua") |
|||
dofile(modpath.."/handlers/nodeboxes.lua") |
|||
dofile(modpath.."/handlers/registration.lua") |
|||
|
|||
dofile(modpath.."/alias.lua") |
|||
dofile(modpath.."/nodes.lua") |
|||
dofile(modpath.."/recipes.lua") |
|||
|
|||
local subpart = { |
|||
"chess", |
|||
"cooking", |
|||
"enchanting", |
|||
"hive", |
|||
"itemframe", |
|||
"mailbox", |
|||
"mechanisms", |
|||
"rope", |
|||
"workbench" |
|||
} |
|||
|
|||
for _, name in pairs(subpart) do |
|||
local enable = minetest.settings:get_bool("enable_xdecor_"..name) |
|||
if enable or enable == nil then |
|||
dofile(modpath.."/"..name..".lua") |
|||
end |
|||
end |
|||
|
|||
--print(string.format("[xdecor] loaded in %.2f ms", (os.clock()-t)*1000)) |
@ -0,0 +1,171 @@ |
|||
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_name = clicker:get_player_name() |
|||
local owner = meta:get_string("owner") |
|||
local admin = minetest.check_player_privs(player_name, "protection_bypass") |
|||
|
|||
if not admin and (player_name ~= 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_name = puncher:get_player_name() |
|||
local owner = meta:get_string("owner") |
|||
local admin = minetest.check_player_privs(player_name, "protection_bypass") |
|||
|
|||
if not admin and player_name ~= owner then return end |
|||
drop_item(pos, node) |
|||
end |
|||
|
|||
function itemframe.dig(pos, player) |
|||
if not player then return end |
|||
local meta = minetest.get_meta(pos) |
|||
local player_name = player and player:get_player_name() |
|||
local owner = meta:get_string("owner") |
|||
local admin = minetest.check_player_privs(player_name, "protection_bypass") |
|||
|
|||
return admin or player_name == 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 |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
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"} |
|||
} |
|||
}) |
@ -0,0 +1,174 @@ |
|||
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 tile, img = 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, is_owner) |
|||
local spos = pos.x..","..pos.y..","..pos.z |
|||
local meta = minetest.get_meta(pos) |
|||
local giver, img = "", "" |
|||
|
|||
if is_owner 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.."," |
|||
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) |
|||
end |
|||
return [[ size[8,5] |
|||
list[current_player;main;0,1.25;8,4;] ]].. |
|||
"label[0,0;Send your goods to\n".. |
|||
(minetest.colorize and |
|||
minetest.colorize("#FFFF00", owner) or owner).."]".. |
|||
"list[nodemeta:"..spos..";drop;3.5,0;1,1;]".. |
|||
xbg..default.get_hotbar_bg(0,1.25) |
|||
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") |
|||
|
|||
minetest.show_formspec(player, "xdecor:mailbox", mailbox:formspec(pos, |
|||
owner, (player == owner))) |
|||
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 |
|||
|
|||
function mailbox.allow_take(pos, listname, index, stack, player) |
|||
local meta = minetest.get_meta(pos) |
|||
|
|||
if player:get_player_name() ~= meta:get_string("owner") then |
|||
return 0 |
|||
end |
|||
return stack:get_count() |
|||
end |
|||
|
|||
function mailbox.allow_move(pos) |
|||
return 0 |
|||
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, |
|||
allow_metadata_inventory_take = mailbox.allow_take, |
|||
allow_metadata_inventory_move = mailbox.allow_move, |
|||
on_metadata_inventory_put = mailbox.on_put, |
|||
allow_metadata_inventory_put = mailbox.put, |
|||
after_place_node = mailbox.after_place_node |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
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"} |
|||
} |
|||
}) |
@ -0,0 +1,141 @@ |
|||
-- Thanks to sofar for helping with that code. |
|||
|
|||
minetest.setting_set("nodetimer_interval", 0.1) |
|||
|
|||
local plate = {} |
|||
screwdriver = screwdriver or {} |
|||
|
|||
local function door_toggle(pos_actuator, pos_door, player) |
|||
local player_name = player:get_player_name() |
|||
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 |
|||
-- Re-get player object (or nil) because 'player' could |
|||
-- be an invalid object at this time (player left) |
|||
door:close(minetest.get_player_by_name(player_name)) |
|||
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 not next(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) |
|||
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" |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
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:lever_off", |
|||
recipe = { |
|||
{"group:stick"}, |
|||
{"group:stone"} |
|||
} |
|||
}) |
@ -0,0 +1,490 @@ |
|||
screwdriver = screwdriver or {} |
|||
|
|||
local function 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 |
|||
|
|||
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"}} |
|||
}) |
|||
|
|||
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"}} |
|||
}) |
|||
|
|||
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"}} |
|||
}) |
|||
|
|||
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() |
|||
}) |
|||
|
|||
local function 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 |
|||
|
|||
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"} |
|||
}) |
|||
|
|||
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"} |
|||
}) |
|||
|
|||
register_storage("empty_shelf", "Empty Shelf", { |
|||
on_rotate = screwdriver.rotate_simple, |
|||
tiles = {"default_wood.png", "default_wood.png", "default_wood.png", |
|||
"default_wood.png", "default_wood.png^xdecor_empty_shelf.png"} |
|||
}) |
|||
|
|||
register_storage("multishelf", "Multi Shelf", { |
|||
on_rotate = screwdriver.rotate_simple, |
|||
tiles = {"default_wood.png", "default_wood.png", "default_wood.png", |
|||
"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() |
|||
}) |
|||
|
|||
local curtain_colors = { |
|||
"red", |
|||
} |
|||
|
|||
for _, c in pairs(curtain_colors) do |
|||
xdecor.register("curtain_"..c, { |
|||
description = c:gsub("^%l", string.upper).." Curtain", |
|||
walkable = false, |
|||
tiles = {"wool_white.png"}, |
|||
color = c, |
|||
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 = "colorwallmounted", |
|||
groups = {dig_immediate=3, flammable=3}, |
|||
selection_box = {type="wallmounted"}, |
|||
on_rightclick = function(pos, node, _, itemstack) |
|||
minetest.set_node(pos, {name="xdecor:curtain_open_"..c, param2=node.param2}) |
|||
return itemstack |
|||
end |
|||
}) |
|||
|
|||
xdecor.register("curtain_open_"..c, { |
|||
tiles = {"wool_white.png^xdecor_curtain_open_overlay.png^[makealpha:255,126,126"}, |
|||
color = c, |
|||
drawtype = "signlike", |
|||
paramtype2 = "colorwallmounted", |
|||
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, _, itemstack) |
|||
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) |
|||
}) |
|||
|
|||
local function register_hard_node(name, desc, def) |
|||
def = def or {} |
|||
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 |
|||
|
|||
register_hard_node("cactusbrick", "Cactus Brick") |
|||
register_hard_node("coalstone_tile", "Coal Stone Tile") |
|||
register_hard_node("desertstone_tile", "Desert Stone Tile") |
|||
register_hard_node("hard_clay", "Hardened Clay") |
|||
register_hard_node("moonbrick", "Moon Brick") |
|||
register_hard_node("stone_tile", "Stone Tile") |
|||
register_hard_node("stone_rune", "Runestone") |
|||
register_hard_node("packed_ice", "Packed Ice", { |
|||
groups = {cracky=1, puts_out_fire=1, slippery=3}, |
|||
sounds = default.node_sound_glass_defaults() |
|||
}) |
|||
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() |
|||
}) |
@ -0,0 +1,35 @@ |
|||
Name: xdecor |
|||
Source: Modified version of upstream mod - Do not replace |
|||
License: See "LICENSE" |
|||
|
|||
---------------------------------------------------------------------- |
|||
|
|||
1. This is a modified version of an upstream mod. The starting point |
|||
was obtained initially as follows: |
|||
|
|||
rm -fr xdecor |
|||
git clone https://github.com/minetest-mods/xdecor.git |
|||
|
|||
---------------------------------------------------------------------- |
|||
|
|||
2. Changes include: |
|||
|
|||
2a. Replaced the contents of "depends.txt" with: |
|||
|
|||
bucket |
|||
default |
|||
doors |
|||
fire? |
|||
moreblocks? |
|||
oresplus? |
|||
stairs |
|||
xpanes |
|||
|
|||
2b. Removed screenshot file(s). |
|||
|
|||
2c. Added the files "00README" and "oldcoder.txt" (this file). |
|||
|
|||
---------------------------------------------------------------------- |
|||
|
|||
3. This mod shouldn't be replaced with an upstream version unless cha- |
|||
nge (2a) is duplicated in the new copy. |
@ -0,0 +1,267 @@ |
|||
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: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: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:hard_clay", |
|||
recipe = { |
|||
{"default:clay", "default:clay"}, |
|||
{"default:clay", "default:clay"} |
|||
} |
|||
}) |
|||
|
|||
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: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: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: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"} |
|||
} |
|||
}) |
|||
|
@ -0,0 +1,68 @@ |
|||
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 |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
minetest.register_craft({ |
|||
output = "xdecor:rope", |
|||
recipe = { |
|||
{"farming:string"}, |
|||
{"farming:string"}, |
|||
{"farming:string"} |
|||
} |
|||
}) |
@ -0,0 +1,11 @@ |
|||
#For enabling a subpart of X-Decor. |
|||
|
|||
enable_xdecor_chess (Enable Chess) bool true |
|||
enable_xdecor_cooking (Enable Cooking) bool true |
|||
enable_xdecor_enchanting (Enable Enchanting) bool true |
|||
enable_xdecor_hive (Enable Hive) bool true |
|||
enable_xdecor_itemframe (Enable Itemframe) bool true |
|||
enable_xdecor_mailbox (Enable Mailbox) bool true |
|||
enable_xdecor_mechanisms (Enable Mechanisms) bool true |
|||
enable_xdecor_rope (Enable Rope) bool true |
|||
enable_xdecor_workbench (Enable Workbench) bool true |
@ -0,0 +1,317 @@ |
|||
local workbench = {} |
|||
WB = {} |
|||
screwdriver = screwdriver or {} |
|||
local min, ceil = math.min, math.ceil |
|||
local registered_nodes = minetest.registered_nodes |
|||
|
|||
-- Nodes allowed to be cut |
|||
-- Only the regular, solid blocks without metas or explosivity can be cut |
|||
local nodes = {} |
|||
for node, def in pairs(registered_nodes) do |
|||
if xdecor.stairs_valid_def(def) then |
|||
nodes[#nodes+1] = node |
|||
end |
|||
end |
|||
|
|||
-- Optionally, you can register custom cuttable nodes in the workbench |
|||
WB.custom_nodes_register = { |
|||
-- "default:leaves", |
|||
} |
|||
|
|||
setmetatable(nodes, { |
|||
__concat = function(t1, t2) |
|||
for i=1, #t2 do |
|||
t1[#t1+1] = t2[i] |
|||
end |
|||
return t1 |
|||
end |
|||
}) |
|||
|
|||
nodes = nodes..WB.custom_nodes_register |
|||
|
|||
-- 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) |
|||
local output = {} |
|||
for i=1, #self.defs do |
|||
local nbox = self.defs[i] |
|||
local count = min(nbox[2] * input:get_count(), input:get_stack_max()) |
|||
local item = name.."_"..nbox[1] |
|||
item = nbox[3] and item or "stairs:"..nbox[1].."_"..name:match(":(.*)") |
|||
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;] |
|||
listring[current_player;main] |
|||
listring[context;tool] |
|||
listring[current_player;main] |
|||
listring[context;hammer] |
|||
listring[current_player;main] |
|||
listring[context;forms] |
|||
listring[current_player;main] |
|||
listring[context;input] ]], |
|||
-- 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) |
|||
if fields.quit then return end |
|||
local meta = minetest.get_meta(pos) |
|||
local id = fields.back and 1 or |
|||
fields.craft and 2 or |
|||
fields.storage and 3 |
|||
if not id then return end |
|||
workbench:set_formspec(meta, id) |
|||
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 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.move(_, from_list, _, to_list, _, count) |
|||
return (to_list == "storage" and from_list ~= "forms") and count or 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, player) |
|||
local inv = minetest.get_meta(pos):get_inventory() |
|||
local input = inv:get_stack("input", 1) |
|||
local inputname = input:get_name() |
|||
local stackname = stack:get_name() |
|||
|
|||
if listname == "input" then |
|||
if stackname == inputname and registered_nodes[inputname.."_cube"] then |
|||
workbench:get_output(inv, input, stackname) |
|||
else |
|||
inv:set_list("forms", {}) |
|||
end |
|||
elseif listname == "forms" then |
|||
local fromstack = inv:get_stack(listname, index) |
|||
if not fromstack:is_empty() and fromstack:get_name() ~= stackname then |
|||
local player_inv = player:get_inventory() |
|||
if player_inv:room_for_item("main", fromstack) then |
|||
player_inv:add_item("main", fromstack) |
|||
end |
|||
end |
|||
|
|||
input:take_item(ceil(stack:get_count() / workbench.defs[index][2])) |
|||
inv:set_stack("input", 1, input) |
|||
workbench:get_output(inv, input, inputname) |
|||
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_move = workbench.move |
|||
}) |
|||
|
|||
for _, d in pairs(workbench.defs) do |
|||
for i=1, #nodes do |
|||
local node = nodes[i] |
|||
local def = 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 (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 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 |
|||
|
|||
-- Craft items |
|||
|
|||
minetest.register_tool("xdecor:hammer", { |
|||
description = "Hammer", |
|||
inventory_image = "xdecor_hammer.png", |
|||
wield_image = "xdecor_hammer.png", |
|||
on_use = function() do return end end |
|||
}) |
|||
|
|||
-- Recipes |
|||
|
|||
minetest.register_craft({ |
|||
output = "xdecor:hammer", |
|||
recipe = { |
|||
{"default:steel_ingot", "group:stick", "default:steel_ingot"}, |
|||
{"", "group:stick", ""} |
|||
} |
|||
}) |
|||
|
|||
minetest.register_craft({ |
|||
output = "xdecor:workbench", |
|||
recipe = { |
|||
{"group:wood", "group:wood"}, |
|||
{"group:wood", "group:wood"} |
|||
} |
|||
}) |
Loading…
Reference in new issue