This commit is contained in:
root 2021-01-17 18:42:05 +01:00
parent 826ecdeb5d
commit 767b91b9b8
23 changed files with 572 additions and 9 deletions

12
mods/mail/LICENSE Normal file
View file

@ -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.

26
mods/mail/README Normal file
View file

@ -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.

1
mods/mail/depends.txt Normal file
View file

@ -0,0 +1 @@
unified_inventory?

226
mods/mail/init.lua Normal file
View file

@ -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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

24
mods/prefab_redo/LICENSE Normal file
View file

@ -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 <http://unlicense.org/>

8
mods/prefab_redo/README Normal file
View file

@ -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

View file

@ -0,0 +1,3 @@
default
doors
basic_materials

View file

@ -0,0 +1 @@
A rewrite of Dan Duncombe's prefab mod.

245
mods/prefab_redo/init.lua Normal file
View file

@ -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"}
}
})

View file

@ -0,0 +1 @@
name = prefab_redo

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

View file

@ -16,6 +16,7 @@
-- Load support for I18n -- Load support for I18n
local S = tubelib_addons3.S local S = tubelib_addons3.S
local M = minetest.get_meta
local Tube = tubelib.Tube 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 local tube_dir = ((minetest.dir_to_facedir(placer:get_look_dir()) + 1) % 4) + 1
Tube:prepare_pairing(pos, tube_dir, sFormspec) Tube:prepare_pairing(pos, tube_dir, sFormspec)
Tube:after_place_node(pos, {tube_dir}) 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, end,
on_receive_fields = function(pos, formname, fields, player) on_receive_fields = function(pos, formname, fields, player)

View file

@ -55,7 +55,7 @@ optional: intllib
# License # License
Copyright (C) 2017-2020 Joachim Stolberg Copyright (C) 2017-2021 Joachim Stolberg
Code: Licensed under the GNU LGPL version 2.1 or later. Code: Licensed under the GNU LGPL version 2.1 or later.
See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt
Textures: CC0 Textures: CC0
@ -81,5 +81,6 @@ Textures: CC0
- 2020-01-03 v1.7 * max_tube_length bugfix - 2020-01-03 v1.7 * max_tube_length bugfix
- 2020-02-02 v1.8 * 'special nodes' as alternative to 'secondary nodes' introduced - 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 - 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)

View file

@ -121,7 +121,12 @@ function Tube:get_secondary_node(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0]) local npos = vector.add(pos, Dir6dToVector[dir or 0])
local node = self:get_node_lvm(npos) local node = self:get_node_lvm(npos)
if self.secondary_node_names[node.name] then 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
end end
@ -286,8 +291,11 @@ function Tube:determine_tube_dirs(pos, preferred_pos, fdir)
-- Check for secondary nodes (chests and so on) -- Check for secondary nodes (chests and so on)
for dir = 1,6 do for dir = 1,6 do
if allowed[dir] then if allowed[dir] then
local _,npos = self:get_secondary_node(pos, dir) local _,npos,allow = self:get_secondary_node(pos, dir)
if npos then if npos then
if not allow then
allowed[dir] = false
else
if preferred_pos and vector.equals(npos, preferred_pos) then if preferred_pos and vector.equals(npos, preferred_pos) then
preferred_pos = nil preferred_pos = nil
table.insert(tbl, 2, dir) table.insert(tbl, 2, dir)
@ -297,6 +305,7 @@ function Tube:determine_tube_dirs(pos, preferred_pos, fdir)
end end
end end
end end
end
-- player pointed to an unknown node to force the tube orientation? -- player pointed to an unknown node to force the tube orientation?
if preferred_pos and fdir then if preferred_pos and fdir then

View file

@ -13,7 +13,7 @@
]]-- ]]--
-- Version for compatibility checks, see readme.md/history -- Version for compatibility checks, see readme.md/history
tubelib2.version = 1.9 tubelib2.version = 2.0
-- for lazy programmers -- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end 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) tmp, npos = self:get_secondary_node(pos, dir)
end end
if npos then 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(npos, Turn180Deg[dir])
self:update_secondary_node(pos, dir) self:update_secondary_node(pos, dir)
end end