diff --git a/mods/mail/LICENSE b/mods/mail/LICENSE new file mode 100644 index 00000000..745bdb19 --- /dev/null +++ b/mods/mail/LICENSE @@ -0,0 +1,12 @@ +The file textures/mail_button.png was created by bas080 and is licensed under the WTFPL. + +All other files: + +Copyright (c) 2016 Carter Kolwey ("Cheapie Systems") + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and/or any associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mods/mail/README b/mods/mail/README new file mode 100644 index 00000000..e9ed9e6e --- /dev/null +++ b/mods/mail/README @@ -0,0 +1,26 @@ +Mail mod for Minetest +===================== + +This mod adds a system to Minetest that allows players to send each other messages within the game. Unlike chat messages or /msgs, these can be sent to an offline player and will still be present the next time they join. + +License: See the "LICENSE" file + +Dependencies: None, but will integrate with unified_inventory if it is present. + +Crafting: N/A + +Instructions: + +The inbox can be accessed by using the /mail command or by pressing the "Mail" button in unified_inventory if that mod is installed. In that window, all messages that the player currently has have the sender and subject (truncated if necessary) shown in a list. Unread messages are shown in red, while read messages are shown in white. The "Mark Read" and "Mark Unread" buttons will change this status, as well as viewing the message. + +To view a message, either single-click on it and press "Read", or just double-click on it. A window will then open showing the sender, subject, and body of the message, with buttons to return to the inbox, reply to the message, forward it, or delete it. + +Single-clicking a message and pressing the "delete" button will remove the message from the inbox. + +The compose window can be opened by pressing the "New Message" button in the inbox. This opens a window where the recipient, subject, and body can be entered, along with buttons to cancel or send the message. Since messages can be sent to any name, including ones that have not yet joined the server for the first time, there is no validation to ensure that the recipient exists. + +If a message is sent to a player that is currently online, they will see a notification in the chat that a message has arrived, along with the sender and subject (truncated if necessary) of the message and a brief reminder that they can use the /mail command (or the mail button, if applicable) to view the message. + +If a player has unread messages in their inbox when they join, a notification will appear to notify them of this. It offers the option to either go to the inbox now, or not. If they choose not to, a reminder is shown in the chat to remind them that they can use the /mail command (or the mail button, if applicable) to view the message(s) later. + +All activity (sending messages, marking them as read/unread, deleting them, etc.) is immediately saved to a file called "mail.db" in the world directory. This file is then read at server startup. If an error occurs while saving this file, a message is printed in the server logs. diff --git a/mods/mail/depends.txt b/mods/mail/depends.txt new file mode 100644 index 00000000..20b7c424 --- /dev/null +++ b/mods/mail/depends.txt @@ -0,0 +1 @@ +unified_inventory? diff --git a/mods/mail/init.lua b/mods/mail/init.lua new file mode 100644 index 00000000..71895e33 --- /dev/null +++ b/mods/mail/init.lua @@ -0,0 +1,226 @@ +mail = {} + +mail.highlightedmessages = {} + +mail.messages = {} + +function mail.load() + local file = io.open(minetest.get_worldpath().."/mail.db","r") + if file then + local data = file:read("*a") + mail.messages = minetest.deserialize(data) + file:close() + end +end + +function mail.save() + local file = io.open(minetest.get_worldpath().."/mail.db","w") + if file and file:write(minetest.serialize(mail.messages)) and file:close() then + return true + else + minetest.log("error","[mail] Save failed - messages may be lost!") + return false + end +end + +mail.inboxformspec = "size[8,9;]".. + "button_exit[7.5,0;0.5,0.5;quit;X]".. + "button[6.25,1;1.5,0.5;new;New Message]".. + "button[6.25,2;1.5,0.5;read;Read]".. + "button[6.25,3;1.5,0.5;reply;Reply]".. + "button[6.25,4;1.5,0.5;forward;Forward]".. + "button[6.25,5;1.5,0.5;delete;Delete]".. + "button[6.25,6;1.5,0.5;markread;Mark Read]".. + "button[6.25,7;1.5,0.5;markunread;Mark Unread]".. + "button[6.25,8;1.5,0.5;about;About]".. + "textlist[0,0.5;6,8.5;message;" + +function mail.send(src,dst,subject,body) + if not mail.messages[dst] then mail.messages[dst] = {} end + table.insert(mail.messages[dst],1,{unread=true,sender=src,subject=subject,body=body}) + for _,player in ipairs(minetest.get_connected_players()) do + local name = player:get_player_name() + if name == dst then + if subject == "" then subject = "(No subject)" end + minetest.chat_send_player(dst,string.format("You have a new message from %s!. Use the /mail command" .. (minetest.get_modpath("unified_inventory") and " or the mail button in the inventory " or " ") .. "to view it. Subject: %s",src,(string.len(subject) > 30 and string.sub(subject,1,27) .. "..." or subject))) + end + end + mail.save() +end + +function mail.showabout(name) + local formspec = "size[4,5;]".. + "button[3.5,0;0.5,0.5;back;X]".. + "label[0,0;Mail]".. + "label[0,0.5;By cheapie]".. + "label[0,1;http://github.com/cheapie/mail]".. + "label[0,1.5;See LICENSE file for license information]".. + "label[0,2.5;NOTE: Communication using this system]".. + "label[0,3;is NOT guaranteed to be private!]".. + "label[0,3.5;Admins are able to view the messages]".. + "label[0,4;of any player.]" + minetest.show_formspec(name,"mail:about",formspec) +end + +function mail.showinbox(name) + local formspec = mail.inboxformspec + if not mail.messages[name] then mail.messages[name] = {} end + local idx, message + if mail.messages[name][1] then + for idx,message in ipairs(mail.messages[name]) do + if idx ~= 1 then formspec = formspec .. "," end + if message.unread then + formspec = formspec .. "#FF8888" + end + formspec = formspec .. "From: " .. minetest.formspec_escape(message.sender) .. " Subject: " + if message.subject ~= "" then + if string.len(message.subject) > 30 then + formspec = formspec .. minetest.formspec_escape(string.sub(message.subject,1,27)).. "..." + else + formspec = formspec .. minetest.formspec_escape(message.subject) + end + else + formspec = formspec .. "(No subject)" + end + end + formspec = formspec .. "]label[0,0;Welcome! You've got mail!]" + else + formspec = formspec .. "No mail :(]label[0,0;Welcome!]" + end + minetest.show_formspec(name,"mail:inbox",formspec) +end + +function mail.showmessage(name,msgnumber) + local message = mail.messages[name][msgnumber] + local formspec = "size[8,6]button[7.5,0;0.5,0.5;back;X]label[0,0;From: %s]label[0,0.5;Subject: %s]textarea[0.25,1;8,4;body;;%s]button[1,5;2,1;reply;Reply]button[3,5;2,1;forward;Forward]button[5,5;2,1;delete;Delete]" + local sender = minetest.formspec_escape(message.sender) + local subject = minetest.formspec_escape(message.subject) + local body = minetest.formspec_escape(message.body) + formspec = string.format(formspec,sender,subject,body) + minetest.show_formspec(name,"mail:message",formspec) +end + +function mail.showcompose(name,defaulttgt,defaultsubj,defaultbody) + local formspec = "size[8,8]field[0.25,0.5;4,1;to;To:;%s]field[0.25,1.5;4,1;subject;Subject:;%s]textarea[0.25,2.5;8,4;body;;%s]button[1,7;2,1;cancel;Cancel]button[7.5,0;0.5,0.5;cancel;X]button[5,7;2,1;send;Send]" + formspec = string.format(formspec,minetest.formspec_escape(defaulttgt),minetest.formspec_escape(defaultsubj),minetest.formspec_escape(defaultbody)) + minetest.show_formspec(name,"mail:compose",formspec) +end + +minetest.register_on_player_receive_fields(function(player,formname,fields) + if formname == "mail:about" then + mail.showinbox(player:get_player_name()) + elseif formname == "mail:inbox" then + local name = player:get_player_name() + if fields.message then + local event = minetest.explode_textlist_event(fields.message) + mail.highlightedmessages[name] = event.index + if event.type == "DCL" and mail.messages[name][mail.highlightedmessages[name]] then + mail.messages[name][mail.highlightedmessages[name]].unread = false + mail.showmessage(name,mail.highlightedmessages[name]) + end + end + if fields.read then + if mail.messages[name][mail.highlightedmessages[name]] then + mail.messages[name][mail.highlightedmessages[name]].unread = false + mail.showmessage(name,mail.highlightedmessages[name]) + end + elseif fields.delete then + if mail.messages[name][mail.highlightedmessages[name]] then table.remove(mail.messages[name],mail.highlightedmessages[name]) end + mail.showinbox(name) + mail.save() + elseif fields.reply and mail.messages[name][mail.highlightedmessages[name]] then + local message = mail.messages[name][mail.highlightedmessages[name]] + local replyfooter = "Type your reply here."..string.char(10)..string.char(10).."--Original message follows--"..string.char(10)..message.body + mail.showcompose(name,message.sender,"Re: "..message.subject,replyfooter) + elseif fields.forward and mail.messages[name][mail.highlightedmessages[name]] then + local message = mail.messages[name][mail.highlightedmessages[name]] + local fwfooter = "Type your message here."..string.char(10)..string.char(10).."--Original message follows--"..string.char(10)..message.body + mail.showcompose(name,"","Fw: "..message.subject,fwfooter) + elseif fields.markread then + if mail.messages[name][mail.highlightedmessages[name]] then mail.messages[name][mail.highlightedmessages[name]].unread = false end + mail.showinbox(name) + mail.save() + elseif fields.markunread then + if mail.messages[name][mail.highlightedmessages[name]] then mail.messages[name][mail.highlightedmessages[name]].unread = true end + mail.showinbox(name) + mail.save() + elseif fields.new then + mail.showcompose(name,"","","Type your message here.") + elseif fields.quit then + if minetest.get_modpath("unified_inventory") then + unified_inventory.set_inventory_formspec(player, "craft") + end + elseif fields.about then + mail.showabout(name) + end + return true + elseif formname == "mail:message" then + local name = player:get_player_name() + if fields.back then + mail.showinbox(name) + elseif fields.reply then + local message = mail.messages[name][mail.highlightedmessages[name]] + local replyfooter = "Type your reply here."..string.char(10)..string.char(10).."--Original message follows--"..string.char(10)..message.body + mail.showcompose(name,message.sender,"Re: "..message.subject,replyfooter) + elseif fields.forward then + local message = mail.messages[name][mail.highlightedmessages[name]] + local fwfooter = "Type your message here."..string.char(10)..string.char(10).."--Original message follows--"..string.char(10)..message.body + mail.showcompose(name,"","Fw: "..message.subject,fwfooter) + elseif fields.delete then + if mail.messages[name][mail.highlightedmessages[name]] then table.remove(mail.messages[name],mail.highlightedmessages[name]) end + mail.showinbox(name) + mail.save() + end + return true + elseif formname == "mail:compose" then + if fields.send then + mail.send(player:get_player_name(),fields.to,fields.subject,fields.body) + end + mail.showinbox(player:get_player_name()) + return true + elseif formname == "mail:unreadnag" then + if fields.yes then + mail.showinbox(player:get_player_name()) + else + minetest.chat_send_player(player:get_player_name(),"You can use the /mail command" .. (minetest.get_modpath("unified_inventory") and " or the mail button in the inventory " or " ") .. "to read your messages later.") + end + return true + elseif fields.mail then + mail.showinbox(player:get_player_name()) + else + return false + end +end) + +if minetest.get_modpath("unified_inventory") then + unified_inventory.register_button("mail", { + type = "image", + image = "mail_button.png", + tooltip = "Mail" + }) +end + +minetest.register_chatcommand("mail",{ + description = "Open the mail interface", + func = function(name) + mail.showinbox(name) + end + } +) + +minetest.register_on_joinplayer(function(player) + minetest.after(0,function(player) + local name = player:get_player_name() + local unreadflag = false + if mail.messages[name] then + for _,message in ipairs(mail.messages[name]) do + if message.unread then unreadflag = true end + end + end + if unreadflag then + minetest.show_formspec(name,"mail:unreadnag","size[3,2]label[0,0;You have unread messages in your inbox.]label[0,0.5;Go there now?]button[0.5,0.75;2,1;yes;Yes]button_exit[0.5,1.5;2,1;no;No]") + end + end,player) +end) + +mail.load() diff --git a/mods/mail/textures/mail_button.png b/mods/mail/textures/mail_button.png new file mode 100644 index 00000000..8adf3eaa Binary files /dev/null and b/mods/mail/textures/mail_button.png differ diff --git a/mods/prefab_redo/LICENSE b/mods/prefab_redo/LICENSE new file mode 100644 index 00000000..68a49daa --- /dev/null +++ b/mods/prefab_redo/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/mods/prefab_redo/README b/mods/prefab_redo/README new file mode 100644 index 00000000..18ea219c --- /dev/null +++ b/mods/prefab_redo/README @@ -0,0 +1,8 @@ +prefab_redo +=========== + +This is a rewrite of Dan Duncombe's prefab mod for Minetest. It includes many of the same nodes (and aliases for compatibility), but not the electric fence. All items have been retextured using technic concrete as a base. + +Dependencies: default, doors, concrete (from technic), moreblocks + +License: Unlicense, see LICENSE file for full text diff --git a/mods/prefab_redo/depends.txt b/mods/prefab_redo/depends.txt new file mode 100644 index 00000000..7af3d830 --- /dev/null +++ b/mods/prefab_redo/depends.txt @@ -0,0 +1,3 @@ +default +doors +basic_materials diff --git a/mods/prefab_redo/description.txt b/mods/prefab_redo/description.txt new file mode 100644 index 00000000..e0f913e5 --- /dev/null +++ b/mods/prefab_redo/description.txt @@ -0,0 +1 @@ +A rewrite of Dan Duncombe's prefab mod. diff --git a/mods/prefab_redo/init.lua b/mods/prefab_redo/init.lua new file mode 100644 index 00000000..7b28b844 --- /dev/null +++ b/mods/prefab_redo/init.lua @@ -0,0 +1,245 @@ +--Prefab Redo Mod +--Written by cheapie +--See LICENSE file for license information + +minetest.register_alias("prefab:concrete","technic:concrete") +minetest.register_alias("prefab:concrete_wall","prefab_redo:concrete_wall") +minetest.register_alias("prefab:concrete_with_grass","prefab_redo:concrete_with_grass") +minetest.register_alias("prefab:concrete_ladder","prefab_redo:concrete_ladder") +minetest.register_alias("prefab:concrete_door_a","doors:door_concrete_a") +minetest.register_alias("prefab:concrete_door_b","doors:door_concrete_b") +minetest.register_alias("prefab:concrete_fence","prefab_redo:concrete_wall") +minetest.register_alias("prefab:concrete_bollard","prefab_redo:concrete_wall") +minetest.register_alias("prefab:concrete_railing","prefab_redo:concrete_railing") +minetest.register_alias("prefab:concrete_railing_corner","prefab_redo:concrete_railing") +minetest.register_alias("prefab:concrete_catwalk","prefab_redo:concrete_catwalk") +minetest.register_alias("prefab:concrete_bench","prefab_redo:concrete_bench") + +minetest.register_node("prefab_redo:concrete_with_grass", { + description = "Concrete with Grass", + sounds = default.node_sound_glass_defaults(), + paramtype = "light", + tiles = { + "default_grass.png", + "basic_materials_concrete_block.png", + "basic_materials_concrete_block.png^default_grass_side.png" + }, + groups = {cracky = 1}, +}) + +minetest.register_node("prefab_redo:concrete_wall", { + description = "Concrete Wall", + sounds = default.node_sound_stone_defaults(), + paramtype = "light", + drawtype = "nodebox", + tiles = {"basic_materials_concrete_block.png"}, + sunlight_propagates = true, + groups = {cracky = 1}, + node_box = { + type = "connected", + fixed = {{-0.3, -0.5, -0.3, 0.3, -0.4, 0.3}, {-0.1, -0.5, -0.1, 0.1, 0.5, 0.1}}, + connect_front = {{-0.3, -0.5, -0.5, 0.3, -0.4, 0.3}, {-0.1, -0.5, -0.5, 0.1, 0.5, 0.1}}, + connect_back = {{-0.3, -0.5, -0.3, 0.3, -0.4, 0.5}, {-0.1, -0.5, -0.1, 0.1, 0.5, 0.5}}, + connect_left = {{-0.5, -0.5, -0.3, 0.3, -0.4, 0.3}, {-0.5, -0.5, -0.1, 0.1, 0.5, 0.1}}, + connect_right = {{-0.3, -0.5, -0.3, 0.5, -0.4, 0.3}, {-0.1, -0.5, -0.1, 0.5, 0.5, 0.1}}, + }, + connects_to = {"prefab_redo:concrete_wall","prefab_redo:concrete_wall_upper"}, + on_construct = function(pos) + local node = minetest.get_node(pos) + local pos_above = {x = pos.x,y = pos.y + 1,z = pos.z} + local node_above = minetest.get_node(pos_above) + local pos_below = {x = pos.x,y = pos.y - 1,z = pos.z} + local node_below = minetest.get_node(pos_below) + if node_above.name == "prefab_redo:concrete_wall" then + node_above.name = "prefab_redo:concrete_wall_upper" + minetest.swap_node(pos_above,node_above) + end + if node_below.name == "prefab_redo:concrete_wall" or node_below.name == "prefab_redo:concrete_wall_upper" then + node.name = "prefab_redo:concrete_wall_upper" + minetest.swap_node(pos,node) + end + end, + on_destruct = function(pos) + local node = minetest.get_node(pos) + local pos_above = {x = pos.x,y = pos.y + 1,z = pos.z} + local node_above = minetest.get_node(pos_above) + if node_above.name == "prefab_redo:concrete_wall_upper" then + node_above.name = "prefab_redo:concrete_wall" + minetest.swap_node(pos_above,node_above) + end + end, +}) + +minetest.register_node("prefab_redo:concrete_wall_upper", { + sounds = default.node_sound_stone_defaults(), + paramtype = "light", + drawtype = "nodebox", + tiles = {"basic_materials_concrete_block.png"}, + sunlight_propagates = true, + groups = {cracky = 1,not_in_creative_inventory = 1}, + drop = "prefab_redo:concrete_wall", + node_box = { + type = "connected", + fixed = {{-0.1, -0.5, -0.1, 0.1, 0.5, 0.1}}, + connect_front = {{-0.1, -0.5, -0.5, 0.1, 0.5, 0.1}}, + connect_back = {{-0.1, -0.5, -0.1, 0.1, 0.5, 0.5}}, + connect_left = {{-0.5, -0.5, -0.1, 0.1, 0.5, 0.1}}, + connect_right = {{-0.1, -0.5, -0.1, 0.5, 0.5, 0.1}}, + }, + connects_to = {"prefab_redo:concrete_wall","prefab_redo:concrete_wall_upper"}, + on_destruct = function(pos) + local node = minetest.get_node(pos) + local pos_above = {x = pos.x,y = pos.y + 1,z = pos.z} + local node_above = minetest.get_node(pos_above) + if node_above.name == "prefab_redo:concrete_wall_upper" then + node_above.name = "prefab_redo:concrete_wall" + minetest.swap_node(pos_above,node_above) + end + end, +}) + +minetest.register_node("prefab_redo:concrete_ladder", { + description = "Concrete Ladder", + drawtype = "signlike", + tiles = {"basic_materials_concrete_block.png^[mask:prefab_redo_ladder_mask.png^prefab_redo_ladder_overlay.png"}, + inventory_image = "basic_materials_concrete_block.png^[mask:prefab_redo_ladder_mask.png^prefab_redo_ladder_overlay.png", + wield_image = "basic_materials_concrete_block.png^[mask:prefab_redo_ladder_mask.png^prefab_redo_ladder_overlay.png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + walkable = false, + climbable = true, + selection_box = { + type = "wallmounted", + }, + groups = {cracky = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +doors.register("door_concrete", { + tiles = { "basic_materials_concrete_block.png^prefab_redo_door_resize.png^[mask:prefab_redo_door_mask.png^prefab_redo_door_overlay.png" }, + description = "Concrete Door", + inventory_image = "basic_materials_concrete_block.png^prefab_redo_door_overlay_half.png^[mask:prefab_redo_door_mask_half.png", + groups = { snappy=1, cracky=1, oddly_breakable_by_hand=3 }, + sounds = default.node_sound_stone_defaults(), + recipe = { + {"technic:concrete", "technic:concrete"}, + {"technic:concrete", "default:steel_ingot"}, + {"technic:concrete", "technic:concrete"}, + }, +}) + +minetest.register_node("prefab_redo:concrete_railing", { + description = "Concrete Railing", + sounds = default.node_sound_stone_defaults(), + paramtype = "light", + drawtype = "nodebox", + tiles = {"basic_materials_concrete_block.png"}, + sunlight_propagates = true, + groups = {cracky = 1}, + node_box = { + type = "connected", + fixed = {{0.0625,-0.5,0.0625,-0.0625,0.1875,-0.0625}}, + connect_front = {{-0.0625,0.1875,-0.5,0.0625,0.3125,0.0625}}, + connect_back = {{-0.0625,0.1875,-0.0625,0.0625,0.3125,0.5}}, + connect_left = {{-0.5,0.1875,-0.0625,0.0625,0.3125,0.0625}}, + connect_right = {{-0.0625,0.1875,-0.0625,0.5,0.3125,0.0625}} + }, + selection_box = { + type = "fixed", + fixed = {{-0.5,-0.5,-0.5,0.5,0.3125,0.5}} + }, + connects_to = {"prefab_redo:concrete_railing","prefab_redo:concrete_catwalk"} +}) + +minetest.register_node("prefab_redo:concrete_catwalk",{ + description= "Concrete Catwalk", + paramtype = "light", + paramtype2 = "facedir", + tiles = {"basic_materials_concrete_block.png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,0.5,-0.375,0.5}, + {-0.5,-0.5,-0.0625,-0.4375,0.5,0.0625}, + {0.4433,-0.5,-0.0625,0.5,0.5,0.0625}, + {0.4433,0.4485,-0.5,0.5,0.5,0.5}, + {-0.5,0.4485,-0.5,-0.4375,0.5,0.5}, + }, + }, + groups = {cracky = 2}, +}) + +minetest.register_node("prefab_redo:concrete_bench", { + description = "Concrete Bench", + tiles = {"basic_materials_concrete_block.png"}, + paramtype = "light", + paramtype2 = "facedir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.125,-0.5,-0.125,0.125,0.0625,0.125}, + {-0.5,0.0625,-0.3125,0.5,0.1875,0.3125}, + }, + }, + groups = {cracky = 2}, +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_railing 6", + recipe = { + {"","",""}, + {"technic:concrete","technic:concrete","technic:concrete"}, + {"","technic:concrete",""} + } +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_catwalk 3", + recipe = { + {"","",""}, + {"prefab_redo:concrete_railing","","prefab_redo:concrete_railing"}, + {"technic:concrete","technic:concrete","technic:concrete"} + } +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_bench 2", + recipe = { + {"","",""}, + {"","technic:concrete",""}, + {"","prefab_redo:concrete_railing",""} + } +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_with_grass", + type = "shapeless", + recipe = {"technic:concrete","default:junglegrass"} +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_with_grass", + type = "shapeless", + recipe = {"technic:concrete","default:grass_1"} +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_wall 3", + recipe = { + {"","technic:concrete",""}, + {"","technic:concrete",""}, + {"","technic:concrete",""} + } +}) + +minetest.register_craft({ + output = "prefab_redo:concrete_ladder 14", + recipe = { + {"technic:concrete","","technic:concrete"}, + {"technic:concrete","technic:concrete","technic:concrete"}, + {"technic:concrete","","technic:concrete"} + } +}) diff --git a/mods/prefab_redo/mod.conf b/mods/prefab_redo/mod.conf new file mode 100644 index 00000000..a489dd0d --- /dev/null +++ b/mods/prefab_redo/mod.conf @@ -0,0 +1 @@ +name = prefab_redo diff --git a/mods/prefab_redo/screenshot.png b/mods/prefab_redo/screenshot.png new file mode 100644 index 00000000..13f19458 Binary files /dev/null and b/mods/prefab_redo/screenshot.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_door_mask.png b/mods/prefab_redo/textures/prefab_redo_door_mask.png new file mode 100644 index 00000000..67419a57 Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_door_mask.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_door_mask_half.png b/mods/prefab_redo/textures/prefab_redo_door_mask_half.png new file mode 100644 index 00000000..fbb67b72 Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_door_mask_half.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_door_overlay.png b/mods/prefab_redo/textures/prefab_redo_door_overlay.png new file mode 100644 index 00000000..8df3dc95 Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_door_overlay.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_door_overlay_half.png b/mods/prefab_redo/textures/prefab_redo_door_overlay_half.png new file mode 100644 index 00000000..fa79a90b Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_door_overlay_half.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_door_resize.png b/mods/prefab_redo/textures/prefab_redo_door_resize.png new file mode 100644 index 00000000..7833da92 Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_door_resize.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_ladder_mask.png b/mods/prefab_redo/textures/prefab_redo_ladder_mask.png new file mode 100644 index 00000000..27486a30 Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_ladder_mask.png differ diff --git a/mods/prefab_redo/textures/prefab_redo_ladder_overlay.png b/mods/prefab_redo/textures/prefab_redo_ladder_overlay.png new file mode 100644 index 00000000..b0073086 Binary files /dev/null and b/mods/prefab_redo/textures/prefab_redo_ladder_overlay.png differ diff --git a/mods/techpack/tubelib_addons3/teleporter.lua b/mods/techpack/tubelib_addons3/teleporter.lua index b8d30722..c33e1e65 100644 --- a/mods/techpack/tubelib_addons3/teleporter.lua +++ b/mods/techpack/tubelib_addons3/teleporter.lua @@ -16,6 +16,7 @@ -- Load support for I18n local S = tubelib_addons3.S +local M = minetest.get_meta local Tube = tubelib.Tube @@ -41,6 +42,9 @@ minetest.register_node("tubelib_addons3:teleporter", { local tube_dir = ((minetest.dir_to_facedir(placer:get_look_dir()) + 1) % 4) + 1 Tube:prepare_pairing(pos, tube_dir, sFormspec) Tube:after_place_node(pos, {tube_dir}) + local meta = M(pos) + local valid_dirs = minetest.serialize({[tube_dir]=true}) + meta:set_string('valid_dirs', valid_dirs) end, on_receive_fields = function(pos, formname, fields, player) diff --git a/mods/tubelib2/README.md b/mods/tubelib2/README.md index 90bd7858..690e7c62 100644 --- a/mods/tubelib2/README.md +++ b/mods/tubelib2/README.md @@ -55,7 +55,7 @@ optional: intllib # License -Copyright (C) 2017-2020 Joachim Stolberg +Copyright (C) 2017-2021 Joachim Stolberg Code: Licensed under the GNU LGPL version 2.1 or later. See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt Textures: CC0 @@ -81,5 +81,6 @@ Textures: CC0 - 2020-01-03 v1.7 * max_tube_length bugfix - 2020-02-02 v1.8 * 'special nodes' as alternative to 'secondary nodes' introduced - 2020-05-31 v1.9 * Generator function 'get_tube_line' added, storage improvements +- 2021-01-17 v2.0 * Update cache on node removal (#7) and refuse to connect with faces of a node which are not marked valid (#3) diff --git a/mods/tubelib2/internal2.lua b/mods/tubelib2/internal2.lua index 20186d78..646dd628 100644 --- a/mods/tubelib2/internal2.lua +++ b/mods/tubelib2/internal2.lua @@ -121,7 +121,12 @@ function Tube:get_secondary_node(pos, dir) local npos = vector.add(pos, Dir6dToVector[dir or 0]) local node = self:get_node_lvm(npos) if self.secondary_node_names[node.name] then - return node, npos + local valid_dir_string = minetest.get_meta(npos):get_string('valid_dirs') + local valid_dirs = self.valid_dirs + if valid_dir_string and valid_dir_string ~= "" then + valid_dirs = minetest.deserialize(valid_dir_string) + end + return node, npos, valid_dirs[Turn180Deg[dir]] or false end end @@ -286,13 +291,17 @@ function Tube:determine_tube_dirs(pos, preferred_pos, fdir) -- Check for secondary nodes (chests and so on) for dir = 1,6 do if allowed[dir] then - local _,npos = self:get_secondary_node(pos, dir) - if npos then - if preferred_pos and vector.equals(npos, preferred_pos) then - preferred_pos = nil - table.insert(tbl, 2, dir) + local _,npos,allow = self:get_secondary_node(pos, dir) + if npos then + if not allow then + allowed[dir] = false else - table.insert(tbl, dir) + if preferred_pos and vector.equals(npos, preferred_pos) then + preferred_pos = nil + table.insert(tbl, 2, dir) + else + table.insert(tbl, dir) + end end end end diff --git a/mods/tubelib2/tube_api.lua b/mods/tubelib2/tube_api.lua index 97b8f657..9f1cfc48 100644 --- a/mods/tubelib2/tube_api.lua +++ b/mods/tubelib2/tube_api.lua @@ -13,7 +13,7 @@ ]]-- -- Version for compatibility checks, see readme.md/history -tubelib2.version = 1.9 +tubelib2.version = 2.0 -- for lazy programmers local S = function(pos) if pos then return minetest.pos_to_string(pos) end end @@ -161,6 +161,8 @@ local function update_secondary_nodes_after_node_dug(self, pos, dirs) tmp, npos = self:get_secondary_node(pos, dir) end if npos then + self:del_from_cache(npos, Turn180Deg[dir]) + self:del_from_cache(pos, dir) self:update_secondary_node(npos, Turn180Deg[dir]) self:update_secondary_node(pos, dir) end