summaryrefslogtreecommitdiff
path: root/locks
diff options
context:
space:
mode:
authorVanessa Ezekowitz <vanessaezekowitz@gmail.com>2016-04-01 20:02:19 -0400
committerVanessa Ezekowitz <vanessaezekowitz@gmail.com>2016-04-01 21:09:33 -0400
commitda66780a569712c23ae4f2996cfb4608a9f9d69d (patch)
tree217556029a78bc23ad4564720afc86de97228a04 /locks
parent615b22df4d423aded3613db7716943a2f389b047 (diff)
downloaddreambuilder_modpack-da66780a569712c23ae4f2996cfb4608a9f9d69d.tar
dreambuilder_modpack-da66780a569712c23ae4f2996cfb4608a9f9d69d.tar.gz
dreambuilder_modpack-da66780a569712c23ae4f2996cfb4608a9f9d69d.tar.bz2
dreambuilder_modpack-da66780a569712c23ae4f2996cfb4608a9f9d69d.tar.xz
dreambuilder_modpack-da66780a569712c23ae4f2996cfb4608a9f9d69d.zip
copy all standard Dreambuilder mods in from the old subgame
(exactly as last supplied there, updates to these mods will follow later)
Diffstat (limited to 'locks')
-rw-r--r--locks/README.md36
-rw-r--r--locks/depends.txt2
-rw-r--r--locks/init.lua611
-rw-r--r--locks/liscence.txt19
-rw-r--r--locks/shared_locked_chest.lua137
-rw-r--r--locks/shared_locked_furnace.lua436
-rw-r--r--locks/shared_locked_sign_wall.lua77
-rw-r--r--locks/shared_locked_xdoors2.lua212
-rw-r--r--locks/textures/bg_shared_locked_chest.jpgbin0 -> 37350 bytes
-rw-r--r--locks/textures/bg_shared_locked_furnace.jpgbin0 -> 85516 bytes
-rw-r--r--locks/textures/bg_shared_locked_sign.jpgbin0 -> 71297 bytes
-rw-r--r--locks/textures/licence.txt88
-rw-r--r--locks/textures/locks_key16.pngbin0 -> 390 bytes
-rw-r--r--locks/textures/locks_key32.pngbin0 -> 726 bytes
-rw-r--r--locks/textures/locks_keychain16.pngbin0 -> 756 bytes
-rw-r--r--locks/textures/locks_keychain32.pngbin0 -> 1843 bytes
-rw-r--r--locks/textures/locks_lock16.pngbin0 -> 727 bytes
-rw-r--r--locks/textures/locks_lock32.pngbin0 -> 1906 bytes
-rw-r--r--locks/textures/locks_xdoors2_bottom_1.pngbin0 -> 227 bytes
-rw-r--r--locks/textures/locks_xdoors2_bottom_2.pngbin0 -> 230 bytes
-rw-r--r--locks/textures/locks_xdoors2_door.pngbin0 -> 266 bytes
-rw-r--r--locks/textures/xdoors2_bottom.pngbin0 -> 109 bytes
-rw-r--r--locks/textures/xdoors2_side.pngbin0 -> 109 bytes
-rw-r--r--locks/textures/xdoors2_top.pngbin0 -> 109 bytes
-rw-r--r--locks/textures/xdoors2_top_1.pngbin0 -> 144 bytes
-rw-r--r--locks/textures/xdoors2_top_2.pngbin0 -> 144 bytes
-rw-r--r--locks/textures/xdoors2locked_bottom_1.pngbin0 -> 227 bytes
-rw-r--r--locks/textures/xdoors2locked_bottom_2.pngbin0 -> 230 bytes
-rw-r--r--locks/textures/xdoors2locked_door.pngbin0 -> 266 bytes
29 files changed, 1618 insertions, 0 deletions
diff --git a/locks/README.md b/locks/README.md
new file mode 100644
index 0000000..03f6534
--- /dev/null
+++ b/locks/README.md
@@ -0,0 +1,36 @@
+This Mod for Minetest adds objects that can be locked and shared.
+
+It is written so that other objects/mods can easily use the functions provided here.
+
+Comes with modified chest, sign and xyz' xdoor2 as sample objects.
+New: Furnaces added.
+For the (unmodified) xdoors2, see http://minetest.net/forum/viewtopic.php?id=2757. Chest and sign take their textures out of default.
+The textures (lock, key and keychain) have been provided by Addi. Please consult textures/licence.txt.
+The code of the lock mod has been written by Sokomine.
+
+A player may open/use a shared locked object if he/she is/has...
+- the owner
+- diglocks priv (may dig up shared locked objects)
+- openlocks priv (object may only be used - i.e. take something out of a chest, open a door - not digged up!)
+- has been added by the owner with the /add playername command
+- member of a playergroup that has been added with /add :playergroupname command (provided the playergroups mod is installed)
+- typed in the correct password that the owner did set with /set thisisthepassword
+
+Adds lock, key and keychain.
+- lock: craftitem to create shared locked objects (chests, signs, doors)
+- key: needed to open your own shared locked objects (a keychain is ok as well)
+- keychain: needed to open the shared locked objects of other players
+The tools do not have to be wielded. They just have to be in the players' inventory.
+Keys and keychains are not specific to a selected lock. They fit all locks - provided the player may open/use the object.
+Thus it is sufficient to carry around only one keychain to open all shared locked objects the player has access to.
+
+If you do not want any of the objects chest, sign and/or door, just remove the corresponding lines from the init.lua:
+dofile(minetest.get_modpath("locks").."/shared_locked_chest.lua");
+dofile(minetest.get_modpath("locks").."/shared_locked_sign_wall.lua");
+dofile(minetest.get_modpath("locks").."/shared_locked_xdoors2.lua");
+dofile(minetest.get_modpath("locks").."/shared_locked_furnace.lua");
+
+I hope this mod will be helpful.
+
+Sokomine
+
diff --git a/locks/depends.txt b/locks/depends.txt
new file mode 100644
index 0000000..7f4b9d7
--- /dev/null
+++ b/locks/depends.txt
@@ -0,0 +1,2 @@
+default
+pipeworks?
diff --git a/locks/init.lua b/locks/init.lua
new file mode 100644
index 0000000..2a35b02
--- /dev/null
+++ b/locks/init.lua
@@ -0,0 +1,611 @@
+
+
+
+--[[
+ Shared locked objects (Mod for MineTest)
+ Allows to restrict usage of blocks to a certain player or a group of
+ players.
+ Copyright (C) 2013 Sokomine
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+--]]
+
+-- Version 1.20
+
+-- Changelog:
+-- 08.05.2014 * Changed animation of shared locked furnace (removed pipeworks overlay on front, changed to new animation type)
+-- 10.01.2013 * Added command to toggle for pipeworks output
+-- * Added pipeworks support for chests and furnace.
+-- 17.12.2013 * aborting input with ESC is possible again
+-- 01.09.2013 * fixed bug in input sanitization
+-- 31.08.2013 * changed receipe for key to avoid crafting conflickt with screwdriver
+-- 10.07.2013 * removed a potential bug (now uses string:gmatch)
+-- * added shared locked furnaces
+
+
+
+locks = {};
+
+minetest.register_privilege("openlocks", { description = "allows to open/use all locked objects", give_to_singleplayer = false});
+minetest.register_privilege("diglocks", { description = "allows to open/use and dig up all locked objects", give_to_singleplayer = false});
+
+
+locks.pipeworks_enabled = false;
+
+if( minetest.get_modpath("pipeworks") ~= nil ) then
+ locks.pipeworks_enabled = true;
+end
+
+-- initializes a lock (that is: prepare the metadata so that it can store data)
+-- default_formspec is the formspec that will be used on right click; the input field for the commands has to exist
+-- Call this in on_construct in register_node. Excample:
+-- on_construct = function(pos)
+-- locks:lock_init( pos, "" );
+-- end;
+
+function locks:lock_init( pos, default_formspec )
+
+ if( pos == nil ) then
+ print( "Error: [locks] lock_init: pos is nil");
+ return;
+ end
+
+ local meta = minetest.env:get_meta(pos);
+ if( meta == nil ) then
+ print( "Error: [locks] lock_init: unable to get meta data");
+ return;
+ end
+
+ -- this will be changed after the node is placed
+ meta:set_string("infotext", "Locked object");
+ -- prepare the field for the owner
+ meta:set_string("owner", "");
+ -- this is the list of players/groups that may unlock the lock even if they are not the owner
+ meta:set_string("allowed_users","");
+ -- objects can be unlocked by passwords as well (if it is set)
+ meta:set_string("password","");
+ -- the last player who entered the right password (to save space this is not a list)
+ meta:set_string("pw_user","");
+ -- this formspec is presented on right-click for every user
+ meta:set_string("formspec", default_formspec);
+ -- by default, do not send output to pipework tubes
+ meta:set_int( "allow_pipeworks", 0 );
+end
+
+
+-- returns the information stored in the metadata strings (like owner etc.)
+function locks:get_lockdata( pos )
+ if( pos == nil ) then
+ return;
+ end
+
+ local meta = minetest.env:get_meta(pos);
+ if( meta == nil) then
+ return;
+ end
+
+ return{ infotext = (meta:get_string( "infotext" ) or ""),
+ owner = (meta:get_string( "owner" ) or ""),
+ allowed_users = (meta:get_string( "allowed_users" ) or ""),
+ password = (meta:get_string( "password" ) or ""),
+ pw_user = (meta:get_string( "w_user" ) or ""),
+ formspec = (meta:get_string( "formspec" ) or "")
+ };
+end
+
+
+-- sets all the metadata the look needs (used e.g. in doors)
+function locks:set_lockdata( pos, data )
+ if( pos == nil ) then
+ return;
+ end
+
+ local meta = minetest.env:get_meta(pos);
+ if( meta == nil) then
+ return;
+ end
+
+ meta:set_string("infotext", (data.infotext or ""));
+ meta:set_string("owner", (data.owner or ""));
+ meta:set_string("allowed_users",(data.allowed_users or ""));
+ meta:set_string("password", (data.password or ""));
+ meta:set_string("pw_user", (data.pw_user or ""));
+ meta:set_string("formspec", (data.formspec or ""));
+end
+
+
+
+
+-- Set the owner of the locked object.
+-- Call this in after_place_node in register_node. Example:
+-- after_place_node = function(pos, placer)
+-- locks:lock_set_owner( pos, placer, "Shared locked object" );
+-- end,
+function locks:lock_set_owner( pos, player_or_name, description )
+
+ if( pos == nil or player_or_name == nil ) then
+ print( "Error: [locks] Missing/wrong parameters to lock_set_owner");
+ return false;
+ end
+
+ local meta = minetest.env:get_meta(pos);
+ if( meta == nil ) then
+ print( "Error: [locks] lock_set_owner: unable to get meta data");
+ return;
+ end
+
+ -- accepts a name or a player object
+ if( type( player_or_name )~="string") then
+ player_or_name = player_or_name:get_player_name();
+ end
+
+ meta:set_string("owner", player_or_name or "");
+ -- add the name of the owner to the description
+ meta:set_string("infotext", ( description or "Shared lockecd object" ).." (owned by "..meta:get_string("owner")..")");
+end
+
+
+
+-- The locked object can only be digged by the owner OR by people with the diglocks priv
+-- Call this in can_dig in register_node. Example:
+-- can_dig = function(pos,player)
+-- return locks:lock_allow_dig( pos, player );
+-- end
+function locks:lock_allow_dig( pos, player )
+
+ if( pos == nil or player == nil ) then
+ print( "Error: [locks] Missing/wrong parameters to lock_allow_dig");
+ return false;
+ end
+
+ local meta = minetest.env:get_meta(pos);
+ local lock_owner = meta:get_string("owner");
+
+ -- locks who lost their owner can be opened/digged by anyone
+ if( meta == nil or lock_owner == nil or lock_owner == "") then
+ return true;
+ end
+
+ -- the owner can dig up his own locked objects
+ if( player:get_player_name() == meta:get_string("owner")) then
+ return true;
+ end
+
+ -- players with diglocks priv can dig up locked objects as well
+ if( minetest.check_player_privs(player:get_player_name(), {diglocks=true})) then
+ return true;
+ end
+
+ return false; -- fallback
+end
+
+
+-- The locked object can only be used (i.e. opened, stuff taken out, changed, ... - depends on object) if this
+-- function returns true. Call it wherever appropriate (usually in on_punch in register_node). Example:
+-- on_punch = function(pos,player)
+-- if( !locks:lock_allow_use( pos, player ) then
+-- print( "Sorry, you have no access here.");
+-- else
+-- do_what_this_object_is_good_for( pos, puncher );
+-- end
+-- end
+
+function locks:lock_allow_use( pos, player )
+
+ if( pos == nil or player == nil ) then
+ print( "Error: [locks] Missing/wrong parameters to lock_allow_use");
+ return false;
+ end
+
+ local name = player:get_player_name();
+ local meta = minetest.env:get_meta(pos);
+
+ -- pipeworks sends a special username
+ if( name == ':pipeworks' or (player.is_fake_player and player.is_fake_player==":pipeworks")) then
+ if( meta:get_int( 'allow_pipeworks' ) == 1 ) then
+ return true;
+ else
+ return false;
+ end
+ end
+
+ -- the player has to have a key or a keychain to open his own shared locked objects
+ if( name == meta:get_string("owner")) then
+
+ if( not( player:get_inventory():contains_item("main","locks:keychain 1"))
+ and not( player:get_inventory():contains_item("main","locks:key 1"))) then
+ minetest.chat_send_player( name, "You do not have a key or a keychain. Without that you can't use your shared locked objects!");
+ return false;
+ end
+
+ -- the player has to have a keychain to open shared locked objects of other players
+ else
+
+ if( not( player:get_inventory():contains_item("main","locks:keychain 1"))) then
+ minetest.chat_send_player(name, "You do not have a keychain. Without that you can't open shared locked objects of other players!");
+ return false;
+ end
+ end
+
+ -- if the user would even be allowed to dig this node up, using the node is allowed as well
+ if( locks:lock_allow_dig( pos, player )) then
+ return true;
+ end
+
+
+ if( meta == nil ) then
+ minetest.chat_send_player( name, "Error: Could not access metadata of this shared locked object.");
+ return false;
+ end
+
+ -- players with openlocks priv can open locked objects
+ if( minetest.check_player_privs(name, {openlocks=true})) then
+ return true;
+ end
+
+ -- the player might be specificly allowed to use this object through allowed_users
+ local liste = meta:get_string("allowed_users"):split( "," );
+ for i in ipairs( liste ) do
+
+ if( liste[i] == name ) then
+ return true;
+ end
+
+ -- the player might member of a playergroup that is allowed to use this object
+ if( liste[i]:sub(1,1) == ":"
+ and playergroups ~= nil
+ and playergroups:is_group_member( meta:get_string("owner"), liste[i]:sub(2), name )) then
+ return true;
+ end
+
+ end
+
+
+ -- the player may have entered the right password
+ if( name == meta:get_string("pw_user")) then
+ return true;
+ end
+
+ -- the lock may have a password set. If this is the case then ask the user for it
+ if( meta:get_string( "password" ) and meta:get_string( "password" ) ~= "" ) then
+ minetest.chat_send_player(name, "Access denied. Right-click and enter password first!");
+ return false;
+ end
+
+ return false; -- fallback
+
+end
+
+
+
+-- Method for the lock to get password and configuration data
+-- Call in on_receive_fields in register_node. Example:
+-- on_receive_fields = function(pos, formname, fields, sender)
+-- locks:lock_handle_input( pos, formname, fields, sender );
+-- end,
+function locks:lock_handle_input( pos, formname, fields, player )
+
+ if( pos == nil or player == nil ) then
+ print( "Error: [locks] Missing/wrong parameters to lock_handle_input");
+ return false;
+ end
+
+ local meta = minetest.env:get_meta(pos);
+ if( meta == nil ) then
+ print( "Error: [locks] lock_handle_input: unable to get meta data");
+ return;
+ end
+
+ -- is this input the lock is supposed to handle?
+ if( ( not( fields.locks_sent_lock_command )
+ or fields.locks_sent_lock_command == "" )
+ and (fields.quit and (fields.quit==true or fields.quit=='true'))) then
+-- or not( fields.locks_sent_input )
+ return;
+ end
+
+ name = player:get_player_name();
+
+ if( fields.locks_sent_lock_command == "/help" ) then
+
+ if( name == meta:get_string( "owner" )) then
+ minetest.chat_send_player(name, "The following commands are available to you, the owner of this object, only:\n"..
+ " /help Shows this help text.\n"..
+ " /add <name> Player <name> can now unlock this object with any key.\n"..
+ " /del <name> Player <name> can no longer use this object.\n"..
+ " /list Shows a list of players who can use this object.\n"..
+ " /set <password> Sets a password. Everyone who types that in can use the object.\n"..
+ " /pipeworks Toggles permission for pipeworks to take inventory out of the shared locked object.\n");
+
+ else if( locks:lock_allow_use( pos, player )) then
+ minetest.chat_send_player(name, "This locked object is owned by "..tostring( meta:get_string( "owner" ))..".\n"..
+ "You do have access to it.\n");
+
+ else if( meta:get_string( "password" ) ~= "" ) then
+ minetest.chat_send_player(name, "This locked object is owned by "..tostring( meta:get_string( "owner" ))..".\n"..
+ "Enter the correct password to gain access.\n");
+
+ else
+ minetest.chat_send_player(name, "This locked object is owned by "..tostring( meta:get_string( "owner" ))..".\n"..
+ "There is no password set. You can only gain access if the owner grants it to you.");
+
+ end end end -- lua is not the most intuitive language here....
+ return;
+ end -- of /help
+
+ -- sanitize player input
+ if( fields.locks_sent_lock_command:match("[^%a%d%s_%- /%:]")) then
+ minetest.chat_send_player(name, "Input contains unsupported characters. Allowed: a-z, A-Z, 0-9, _, -, :.");
+ return;
+ end
+
+ if( #fields.locks_sent_lock_command > 60) then
+ minetest.chat_send_player(name, "Input too long. Only up to 80 characters supported.");
+ return;
+ end
+
+
+ -- other players can only try to input the correct password
+ if( name ~= meta:get_string( "owner" )) then
+
+ -- no need to bother with trying other PWs if none is set...
+ if( meta:get_string("password")=="" ) then
+ minetest.chat_send_player(name, "There is no password set. Access denied.");
+ return;
+ end
+
+ -- the player may have entered the right password already
+ if( name == meta:get_string("pw_user")) then
+ -- nothing to do - the player entered the right pw alredy
+ minetest.chat_send_player(name, "You have entered the right password already. Access granted.");
+ return;
+ end
+
+ if( fields.locks_sent_lock_command ~= meta:get_string("password")) then
+ minetest.chat_send_player(name, "Wrong password. Access denied.");
+ return;
+ end
+
+ -- store the last user (this one) who entered the right pw
+ meta:set_string( "pw_user", name );
+
+ minetest.chat_send_player(name, "Password confirmed. Access granted.");
+ return;
+ end
+
+ local txt = "";
+
+
+ if( fields.locks_sent_lock_command == "/list" ) then
+
+ if( meta:get_string("allowed_users")=="" ) then
+ txt = "No other users are allowed to use this object (except those with global privs like moderators/admins).";
+ else
+ txt = "You granted the following users/groups of users access to this object:\n";
+ local liste = meta:get_string("allowed_users"):split( "," );
+ for i in ipairs( liste ) do
+ txt = txt.." "..tostring(liste[i]);
+ end
+ end
+
+ if( meta:get_string( "password" ) == "" ) then
+ txt = txt.."\nThere is no password set. That means no one can get access through a password.";
+ else
+ txt = txt.."\nThe password for this lock is: \""..tostring( meta:get_string( "password" ).."\"");
+ end
+
+ if( not( minetest.get_modpath("pipeworks") )) then
+ txt = txt.."\nThe pipeworks mod is not installed. Install it if you wish support for tubes.";
+ elseif( meta:get_int( "allow_pipeworks" ) == 1 ) then
+ txt = txt.."\nTubes from pipeworks may be used to extract items out of/add items to this shared locked object.";
+ else
+ txt = txt.."\nInput from tubes is accepted, but output to them is denied (default).";
+ end
+
+ minetest.chat_send_player(name, txt );
+ return;
+ end -- of /list
+
+
+ -- toggle tube output on/off
+ if( fields.locks_sent_lock_command == "/pipeworks" ) then
+
+ if( meta:get_int('allow_pipeworks') == 1 ) then
+ meta:set_int('allow_pipeworks', 0 );
+ minetest.chat_send_player( name, 'Output to pipework tubes is now DISABLED (input is still acceped).');
+ return;
+ else
+ meta:set_int('allow_pipeworks', 1 );
+ minetest.chat_send_player( name, 'Output to pipework tubes is now ENABLED. Connected tubes may insert and remove items.');
+ return;
+ end
+ end
+
+-- -- all other commands take exactly one parameter
+ local help = fields.locks_sent_lock_command:split( " " );
+
+ print( tostring( help[1] ));
+ print( tostring( help[2] ));
+
+
+ -- set/change a password
+ if( help[1]=="/set" ) then
+
+ -- if empty password then delete it
+ if( help[2]==nil ) then
+ help[2] = "";
+ end
+
+ minetest.chat_send_player(name, "Old password: \""..tostring( meta:get_string( "password" ))..
+ "\"\n Changed to new password: \""..tostring( help[2]).."\".");
+
+
+ meta:set_string( "password", help[2]);
+ -- reset the list of users who typed the right password
+ meta:set_string("pw_users","");
+
+ if( help[2]=="") then
+ minetest.chat_send_player(name, "The password is empty and thus will be disabled.");
+ end
+ return;
+ end
+
+ if( help[2]==nil or help[2]=="") then
+ minetest.chat_send_player(name, "Error: Missing parameter (player name) for command \""..tostring( help[1] ).."\"." );
+ return;
+ end
+
+ -- for add and del: check if the player is already in the list
+
+ local found = false;
+ local anz = 0;
+ local liste = meta:get_string("allowed_users"):split( "," );
+ for i in ipairs( liste ) do
+
+ anz = anz + 1; -- count players
+ if( tostring( liste[i] ) == help[2] ) then
+ found = true;
+ end
+
+ end
+
+ if( help[1]=="/add" and found==true ) then
+ minetest.chat_send_player(name, "Player \""..tostring( help[2] ).."\" is already allowed to use this locked object. Nothing to do.");
+ return;
+ end
+
+ if( help[1]=="/del" and found==false) then
+ minetest.chat_send_player(name, "Player \""..tostring( help[2] ).."\" is not amongst the players allowed to use this locked object. Nothing to do.");
+ return;
+ end
+
+
+ if( help[1]=="/add" ) then
+
+ if( anz >= 6 ) then
+ minetest.chat_send_player(name, "Sorry, no more players can be added. To save space, only up to 6 players can be added. For more players please use groups!");
+ return;
+ end
+
+ if( name == help[2] ) then
+ minetest.chat_send_player(name, "You are already owner of this object.");
+ return;
+ end
+
+ -- the player might try to add a playergroup
+ if( help[2]:sub(1,1) == ":" ) then
+
+ if( not( playergroups )) then
+ minetest.chat_send_player(name, "Sorry, this server does not support playergroups.");
+ return;
+ end
+
+ if( #help[2]<2 ) then
+ minetest.chat_send_player(name, "Please specify the name of the playergroup you want to add!");
+ return;
+ end
+
+ if( not( playergroups:is_playergroup(meta:get_string("owner"), help[2]:sub(2) ))) then
+ minetest.chat_send_player(name, "You do not have a playergroup named \""..tostring( help[2]:sub(2)).."\".");
+ return;
+ end
+
+ else
+
+ -- check if the player exists
+ local privs = minetest.get_player_privs( help[2] );
+ if( not( privs ) or not( privs.interact )) then
+ minetest.chat_send_player(name, "Player \""..help[2].."\" not found or has no interact privs.");
+ return;
+ end
+ end
+
+ meta:set_string( "allowed_users", meta:get_string("allowed_users")..","..help[2] );
+
+ if( help[2]:sub(1,1) == ":" ) then
+ minetest.chat_send_player(name, "All members of your playergroup "..tostring(help[2]:sub(2)).." may now use/access this locked object.");
+ else
+ minetest.chat_send_player(name, help[2].." may now use/access this locked object.");
+ end
+ return;
+ end
+
+
+ if( help[1]=="/del" ) then
+
+ userlist = meta:get_string("allowed_users"):split( ","..help[2] );
+ meta:set_string( "allowed_users", ( userlist[1] or "" )..(userlist[2] or "" ));
+
+ minetest.chat_send_player(name, "Access for player \""..tostring(help[2]).."\" has been revoked.");
+ return;
+ end
+
+ minetest.chat_send_player(name, "Error: Command \""..tostring(help[1]).."\" not understood.");
+end
+
+
+
+-- craftitem; that can be used to craft shared locked objects
+minetest.register_craftitem("locks:lock", {
+ description = "Lock to lock and share objects",
+ image = "locks_lock16.png",
+});
+
+
+minetest.register_craft({
+ output = "locks:lock 2",
+ recipe = {
+ {'default:steel_ingot', 'default:steel_ingot','default:steel_ingot'},
+ {'default:steel_ingot', '', 'default:steel_ingot'},
+ {'', 'default:steel_ingot',''},
+ }
+ });
+
+
+-- a key allowes to open your own shared locked objects
+minetest.register_craftitem("locks:key", {
+ description = "Key to open your own shared locked objects",
+ image = "locks_key32.png",
+});
+
+minetest.register_craft({
+ output = "locks:key",
+ recipe = {
+ {'', 'default:stick', ''},
+ {'', 'default:steel_ingot',''},
+ }
+ });
+
+
+
+-- in order to open shared locked objects of other players, a keychain is needed (plus the owner has to admit it via /add playername or through /set password)
+minetest.register_craftitem("locks:keychain", {
+ description = "Keychain to open shared locked objects of others",
+ image = "locks_keychain32.png",
+});
+
+minetest.register_craft({
+ output = "locks:keychain",
+ recipe = {
+ {'', 'default:steel_ingot', '' },
+ {'locks:key', 'locks:key', 'locks:key'},
+ }
+ });
+
+dofile(minetest.get_modpath("locks").."/shared_locked_chest.lua");
+dofile(minetest.get_modpath("locks").."/shared_locked_sign_wall.lua");
+dofile(minetest.get_modpath("locks").."/shared_locked_xdoors2.lua");
+dofile(minetest.get_modpath("locks").."/shared_locked_furnace.lua");
+
+
diff --git a/locks/liscence.txt b/locks/liscence.txt
new file mode 100644
index 0000000..7dd6dff
--- /dev/null
+++ b/locks/liscence.txt
@@ -0,0 +1,19 @@
+License of locks mod for Minetest-c55
+-------------------------------------
+
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
diff --git a/locks/shared_locked_chest.lua b/locks/shared_locked_chest.lua
new file mode 100644
index 0000000..66496b1
--- /dev/null
+++ b/locks/shared_locked_chest.lua
@@ -0,0 +1,137 @@
+-- 09.01.13 Added support for pipeworks.
+
+
+locks.chest_add = {};
+locks.chest_add.tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png",
+ "default_chest_side.png", "default_chest_side.png", "default_chest_front.png"};
+locks.chest_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2};
+locks.chest_add.tube = {};
+
+-- additional/changed definitions for pipeworks;
+-- taken from pipeworks/compat.lua
+if( locks.pipeworks_enabled ) then
+ locks.chest_add.tiles = {
+ "default_chest_top.png^pipeworks_tube_connection_wooden.png",
+ "default_chest_top.png^pipeworks_tube_connection_wooden.png",
+ "default_chest_side.png^pipeworks_tube_connection_wooden.png",
+ "default_chest_side.png^pipeworks_tube_connection_wooden.png",
+ "default_chest_side.png^pipeworks_tube_connection_wooden.png"};
+ locks.chest_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,
+ tubedevice = 1, tubedevice_receiver = 1 };
+ locks.chest_add.tube = {
+ insert_object = function(pos, node, stack, direction)
+ local meta = minetest.env:get_meta(pos)
+ local inv = meta:get_inventory()
+ return inv:add_item("main", stack)
+ end,
+ can_insert = function(pos, node, stack, direction)
+ local meta = minetest.env:get_meta(pos)
+ local inv = meta:get_inventory()
+ return inv:room_for_item("main", stack)
+ end,
+ input_inventory = "main",
+ connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1}
+ };
+end
+
+
+minetest.register_node("locks:shared_locked_chest", {
+ description = "Shared locked chest",
+ tiles = locks.chest_add.tiles,
+ paramtype2 = "facedir",
+ groups = locks.chest_add.groups,
+ tube = locks.chest_add.tube,
+ legacy_facedir_simple = true,
+
+ on_construct = function(pos)
+ local meta = minetest.env:get_meta(pos)
+ -- prepare the lock of the chest
+ locks:lock_init( pos,
+ "size[8,10]"..
+-- "field[0.5,0.2;8,1.0;locks_sent_lock_command;Locked chest. Type password, command or /help for help:;]"..
+-- "button_exit[3,0.8;2,1.0;locks_sent_input;Proceed]"..
+ "list[current_name;main;0,0;8,4;]"..
+ "list[current_player;main;0,5;8,4;]"..
+ "field[0.3,9.6;6,0.7;locks_sent_lock_command;Locked chest. Type /help for help:;]"..
+ "background[-0.5,-0.65;9,11.2;bg_shared_locked_chest.jpg]"..
+ "button_exit[6.3,9.2;1.7,0.7;locks_sent_input;Proceed]" );
+-- "size[8,9]"..
+-- "list[current_name;main;0,0;8,4;]"..
+-- "list[current_player;main;0,5;8,4;]");
+ local inv = meta:get_inventory()
+ inv:set_size("main", 8*4)
+ end,
+
+ after_place_node = function(pos, placer)
+
+ if( locks.pipeworks_enabled ) then
+ pipeworks.scan_for_tube_objects( pos );
+ end
+
+ locks:lock_set_owner( pos, placer, "Shared locked chest" );
+ end,
+
+
+ can_dig = function(pos,player)
+
+ if( not(locks:lock_allow_dig( pos, player ))) then
+ return false;
+ end
+ local meta = minetest.env:get_meta(pos);
+ local inv = meta:get_inventory()
+ return inv:is_empty("main")
+ end,
+
+ on_receive_fields = function(pos, formname, fields, sender)
+ locks:lock_handle_input( pos, formname, fields, sender );
+ end,
+
+
+
+ allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ return count;
+ end,
+ allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ return stack:get_count()
+ end,
+ allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ return stack:get_count()
+ end,
+ on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+ minetest.log("action", player:get_player_name()..
+ " moves stuff in locked shared chest at "..minetest.pos_to_string(pos))
+ end,
+ on_metadata_inventory_put = function(pos, listname, index, stack, player)
+ minetest.log("action", player:get_player_name()..
+ " moves stuff to locked shared chest at "..minetest.pos_to_string(pos))
+ end,
+ on_metadata_inventory_take = function(pos, listname, index, stack, player)
+ minetest.log("action", player:get_player_name()..
+ " takes stuff from locked shared chest at "..minetest.pos_to_string(pos))
+ end,
+
+
+ after_dig_node = function( pos )
+ if( locks.pipeworks_enabled ) then
+ pipeworks.scan_for_tube_objects(pos)
+ end
+ end
+})
+
+minetest.register_craft({
+ output = 'locks:shared_locked_chest',
+ recipe = {
+ { 'default:chest', 'locks:lock', '' },
+ },
+})
+
+print( "[Mod] locks: loading locks:shared_locked_chest");
diff --git a/locks/shared_locked_furnace.lua b/locks/shared_locked_furnace.lua
new file mode 100644
index 0000000..1543c7b
--- /dev/null
+++ b/locks/shared_locked_furnace.lua
@@ -0,0 +1,436 @@
+
+-- this is a (slightly!) modified copy of minetest_game/mods/default/nodes.lua,
+-- containing only the furnace and adopted slightly for my locks mod
+
+
+-- 09.01.13 Added support for pipeworks.
+
+
+locks.furnace_add = {};
+locks.furnace_add.tiles_normal = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
+ "default_furnace_side.png", "default_furnace_side.png", "default_furnace_front.png"};
+locks.furnace_add.tiles_active = {"default_furnace_top.png", "default_furnace_bottom.png", "default_furnace_side.png",
+ "default_furnace_side.png", "default_furnace_side.png", --"default_furnace_front_active.png"};
+ {
+ image = "default_furnace_front_active.png",
+ backface_culling = false,
+ animation = {
+ type = "vertical_frames",
+ aspect_w = 16,
+ aspect_h = 16,
+ length = 1.5
+ },
+ }};
+locks.furnace_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2};
+locks.furnace_add.tube = {};
+
+-- additional/changed definitions for pipeworks;
+-- taken from pipeworks/compat.lua
+if( locks.pipeworks_enabled ) then
+
+ locks.furnace_add.tiles_normal = {
+ "default_furnace_top.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_bottom.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_side.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_side.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_side.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_front.png" };
+
+
+ locks.furnace_add.tiles_active = {
+ "default_furnace_top.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_bottom.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_side.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_side.png^pipeworks_tube_connection_stony.png",
+ "default_furnace_side.png^pipeworks_tube_connection_stony.png",
+ {
+ image = "default_furnace_front_active.png",
+ backface_culling = false,
+ animation = {
+ type = "vertical_frames",
+ aspect_w = 16,
+ aspect_h = 16,
+ length = 1.5
+ },
+ }};
+-- "default_furnace_front_active.png" };
+
+
+ locks.furnace_add.groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,
+ tubedevice = 1, tubedevice_receiver = 1 };
+ locks.furnace_add.tube = {
+ insert_object = function(pos, node, stack, direction)
+ local meta = minetest.env:get_meta(pos)
+ local inv = meta:get_inventory()
+ if direction.y == 1 then
+ return inv:add_item("fuel",stack)
+ else
+ return inv:add_item("src",stack)
+ end
+ end,
+ can_insert = function(pos, node, stack, direction)
+ local meta = minetest.env:get_meta(pos)
+ local inv = meta:get_inventory()
+ if direction.y == 1 then
+ return inv:room_for_item("fuel", stack)
+ else
+ return inv:room_for_item("src", stack)
+ end
+ end,
+ input_inventory = "dst",
+ connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1}
+ };
+end
+
+
+function locks.get_furnace_active_formspec(pos, percent)
+ local formspec =
+ "size[8,9]"..
+ "image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
+ (100-percent)..":default_furnace_fire_fg.png]"..
+ "list[current_name;fuel;2,3;1,1;]"..
+ "list[current_name;src;2,1;1,1;]"..
+ "list[current_name;dst;5,1;2,2;]"..
+ "list[current_player;main;0,5;8,4;]"..
+ "background[-0.5,-0.65;9,10.35;bg_shared_locked_furnace.jpg]"..
+
+ "field[0.3,4.5;6,0.7;locks_sent_lock_command;Locked furnace. Type /help for help:;]"..
+ "button_exit[6.3,4;1.7,0.7;locks_sent_input;Proceed]" ;
+ return formspec
+end
+
+locks.furnace_inactive_formspec =
+ "size[8,9]"..
+ "image[2,2;1,1;default_furnace_fire_bg.png]"..
+ "list[current_name;fuel;2,3;1,1;]"..
+ "list[current_name;src;2,1;1,1;]"..
+ "list[current_name;dst;5,1;2,2;]"..
+ "list[current_player;main;0,5;8,4;]"..
+ "background[-0.5,-0.65;9,10.35;bg_shared_locked_furnace.jpg]"..
+ "field[0.3,4.5;6,0.7;locks_sent_lock_command;Locked furnace. Type /help for help:;]"..
+ "button_exit[6.3,4;1.7,0.7;locks_sent_input;Proceed]" ;
+
+minetest.register_node("locks:shared_locked_furnace", {
+ description = "Shared locked furnace",
+ paramtype2 = "facedir",
+ groups = {cracky=2},
+ legacy_facedir_simple = true,
+
+ tiles = locks.furnace_add.tiles_normal,
+ groups = locks.furnace_add.groups,
+ tube = locks.furnace_add.tube,
+
+-- sounds = default.node_sound_stone_defaults(),
+ on_construct = function(pos)
+ local meta = minetest.get_meta(pos)
+ locks:lock_init( pos, locks.furnace_inactive_formspec)
+ meta:set_string("infotext", "Shared locked furnace")
+ local inv = meta:get_inventory()
+ inv:set_size("fuel", 1)
+ inv:set_size("src", 1)
+ inv:set_size("dst", 4)
+ end,
+
+ after_place_node = function(pos, placer)
+ if( locks.pipeworks_enabled ) then
+ pipeworks.scan_for_tube_objects(pos)
+ end
+ locks:lock_set_owner( pos, placer, "Shared locked furnace" );
+ end,
+ after_dig_node = function(pos)
+ if( locks.pipeworks_enabled ) then
+ pipeworks.scan_for_tube_objects(pos)
+ end
+ end,
+
+ can_dig = function(pos,player)
+ if( not(locks:lock_allow_dig( pos, player ))) then
+ return false;
+ end
+ local meta = minetest.get_meta(pos);
+ local inv = meta:get_inventory()
+ if not inv:is_empty("fuel") then
+ return false
+ elseif not inv:is_empty("dst") then
+ return false
+ elseif not inv:is_empty("src") then
+ return false
+ end
+ return true
+ end,
+ on_receive_fields = function(pos, formname, fields, sender)
+ locks:lock_handle_input( pos, formname, fields, sender );
+ end,
+ allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ if listname == "fuel" then
+ if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
+ if inv:is_empty("src") then
+ meta:set_string("infotext","Furnace is empty")
+ end
+ return stack:get_count()
+ else
+ return 0
+ end
+ elseif listname == "src" then
+ return stack:get_count()
+ elseif listname == "dst" then
+ return 0
+ end
+ end,
+ allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ local stack = inv:get_stack(from_list, from_index)
+ if to_list == "fuel" then
+ if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
+ if inv:is_empty("src") then
+ meta:set_string("infotext","Furnace is empty")
+ end
+ return count
+ else
+ return 0
+ end
+ elseif to_list == "src" then
+ return count
+ elseif to_list == "dst" then
+ return 0
+ end
+ end,
+ allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ return stack:get_count()
+ end,
+})
+
+minetest.register_node("locks:shared_locked_furnace_active", {
+ description = "Furnace",
+ paramtype2 = "facedir",
+ light_source = 8,
+ drop = "locks:shared_locked_furnace",
+ groups = {cracky=2, not_in_creative_inventory=1},
+ legacy_facedir_simple = true,
+
+ tiles = locks.furnace_add.tiles_active,
+ groups = locks.furnace_add.groups,
+ tube = locks.furnace_add.tube,
+
+-- sounds = default.node_sound_stone_defaults(),
+ on_construct = function(pos)
+ local meta = minetest.get_meta(pos)
+ locks:lock_init( pos, locks.furnace_inactive_formspec)
+ meta:set_string("infotext", "Shared locked furnace");
+ local inv = meta:get_inventory()
+ inv:set_size("fuel", 1)
+ inv:set_size("src", 1)
+ inv:set_size("dst", 4)
+ end,
+ can_dig = function(pos,player)
+ if( not(locks:lock_allow_dig( pos, player ))) then
+ return false;
+ end
+ local meta = minetest.get_meta(pos);
+ local inv = meta:get_inventory()
+ if not inv:is_empty("fuel") then
+ return false
+ elseif not inv:is_empty("dst") then
+ return false
+ elseif not inv:is_empty("src") then
+ return false
+ end
+ return true
+ end,
+
+ after_place_node = function(pos, placer)
+ if( locks.pipeworks_enabled ) then
+ pipeworks.scan_for_tube_objects(pos)
+ end
+ locks:lock_set_owner( pos, placer, "Shared locked furnace (active)" );
+ end,
+ after_dig_node = function(pos)
+ if( locks.pipeworks_enabled ) then
+ pipeworks.scan_for_tube_objects(pos)
+ end
+ end,
+
+ on_receive_fields = function(pos, formname, fields, sender)
+ locks:lock_handle_input( pos, formname, fields, sender );
+ end,
+ allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ if listname == "fuel" then
+ if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
+ if inv:is_empty("src") then
+ meta:set_string("infotext","Shared locked furnace (empty)")
+ end
+ return stack:get_count()
+ else
+ return 0
+ end
+ elseif listname == "src" then
+ return stack:get_count()
+ elseif listname == "dst" then
+ return 0
+ end
+ end,
+ allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ local meta = minetest.get_meta(pos)
+ local inv = meta:get_inventory()
+ local stack = inv:get_stack(from_list, from_index)
+ if to_list == "fuel" then
+ if minetest.get_craft_result({method="fuel",width=1,items={stack}}).time ~= 0 then
+ if inv:is_empty("src") then
+ meta:set_string("infotext","Shared locked furnace (empty)")
+ end
+ return count
+ else
+ return 0
+ end
+ elseif to_list == "src" then
+ return count
+ elseif to_list == "dst" then
+ return 0
+ end
+ end,
+ allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+ if( not( locks:lock_allow_use( pos, player ))) then
+ return 0;
+ end
+ return stack:get_count()
+ end,
+})
+
+-- better make this a function specific to this mod to avoid trouble with the same function in default
+locks.hacky_swap_node = function(pos,name)
+ local node = minetest.get_node(pos)
+ local meta = minetest.get_meta(pos)
+ local meta0 = meta:to_table()
+ if node.name == name then
+ return
+ end
+ node.name = name
+ local meta0 = meta:to_table()
+ minetest.set_node(pos,node)
+ meta = minetest.get_meta(pos)
+ meta:from_table(meta0)
+end
+
+minetest.register_abm({
+ nodenames = {"locks:shared_locked_furnace","locks:shared_locked_furnace_active"},
+ interval = 1.0,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local meta = minetest.get_meta(pos)
+ for i, name in ipairs({
+ "fuel_totaltime",
+ "fuel_time",
+ "src_totaltime",
+ "src_time"
+ }) do
+ if meta:get_string(name) == "" then
+ meta:set_float(name, 0.0)
+ end
+ end
+
+ local inv = meta:get_inventory()
+
+ local srclist = inv:get_list("src")
+ local cooked = nil
+ local aftercooked
+
+ if srclist then
+ cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
+ end
+
+ local was_active = false
+
+ if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
+ was_active = true
+ meta:set_float("fuel_time", meta:get_float("fuel_time") + 1)
+ meta:set_float("src_time", meta:get_float("src_time") + 1)
+ if cooked and cooked.item and meta:get_float("src_time") >= cooked.time then
+ -- check if there's room for output in "dst" list
+ if inv:room_for_item("dst",cooked.item) then
+ -- Put result in "dst" list
+ inv:add_item("dst", cooked.item)
+ -- take stuff from "src" list
+ inv:set_stack("src", 1, aftercooked.items[1])
+ else
+ print("Could not insert '"..cooked.item:to_string().."'")
+ end
+ meta:set_string("src_time", 0)
+ end
+ end
+
+ if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
+ local percent = math.floor(meta:get_float("fuel_time") /
+ meta:get_float("fuel_totaltime") * 100)
+ meta:set_string("infotext","Shared locked furnace active: "..percent.."%")
+ locks.hacky_swap_node(pos,"locks:shared_locked_furnace_active")
+ meta:set_string("formspec",locks.get_furnace_active_formspec(pos, percent))
+ return
+ end
+
+ local fuel = nil
+ local afterfuel
+ local cooked = nil
+ local fuellist = inv:get_list("fuel")
+ local srclist = inv:get_list("src")
+
+ if srclist then
+ cooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
+ end
+ if fuellist then
+ fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
+ end
+
+ if not( fuel) or fuel.time <= 0 then
+ meta:set_string("infotext","Shared locked furnace out of fuel")
+ locks.hacky_swap_node(pos,"locks:shared_locked_furnace")
+ meta:set_string("formspec", locks.furnace_inactive_formspec)
+ return
+ end
+
+ if cooked.item:is_empty() then
+ if was_active then
+ meta:set_string("infotext","Shared locked furnace is empty")
+ locks.hacky_swap_node(pos,"locks:shared_locked_furnace")
+ meta:set_string("formspec", locks.furnace_inactive_formspec)
+ end
+ return
+ end
+
+ meta:set_string("fuel_totaltime", fuel.time)
+ meta:set_string("fuel_time", 0)
+
+ inv:set_stack("fuel", 1, afterfuel.items[1])
+ end,
+})
+
+
+minetest.register_craft({
+ output = 'locks:shared_locked_furnace',
+ recipe = {
+ { 'default:furnace', 'locks:lock', '' },
+ },
+})
+
+print( "[Mod] locks: loading locks:shared_locked_furnace");
+
+
diff --git a/locks/shared_locked_sign_wall.lua b/locks/shared_locked_sign_wall.lua
new file mode 100644
index 0000000..2dcf19e
--- /dev/null
+++ b/locks/shared_locked_sign_wall.lua
@@ -0,0 +1,77 @@
+
+-- allow aborting with ESC in newer Versions of MT again
+
+-- a sign
+minetest.register_node("locks:shared_locked_sign_wall", {
+ description = "Shared locked sign",
+ drawtype = "signlike",
+ tiles = {"default_sign_wall.png"},
+ inventory_image = "default_sign_wall.png",
+ wield_image = "default_sign_wall.png",
+ paramtype = "light",
+ paramtype2 = "wallmounted",
+ sunlight_propagates = true,
+ walkable = false,
+ selection_box = {
+ type = "wallmounted",
+ --wall_top = <default>
+ --wall_bottom = <default>
+ --wall_side = <default>
+ },
+ groups = {choppy=2,dig_immediate=2},
+ legacy_wallmounted = true,
+
+
+ on_construct = function(pos)
+ local meta = minetest.env:get_meta(pos)
+ -- prepare the lock of the sign
+ locks:lock_init( pos,
+ "size[8,4]"..
+ "field[0.3,0.6;6,0.7;text;Text:;${text}]"..
+ "field[0.3,3.6;6,0.7;locks_sent_lock_command;Locked sign. Type /help for help:;]"..
+ "button_exit[6.3,3.2;1.7,0.7;locks_sent_input;Proceed]"..
+ "background[-0.5,-0.5;9,5;bg_shared_locked_sign.jpg]" );
+ end,
+
+ after_place_node = function(pos, placer)
+ locks:lock_set_owner( pos, placer, "Shared locked sign" );
+ end,
+
+
+ can_dig = function(pos,player)
+ return locks:lock_allow_dig( pos, player );
+ end,
+
+ on_receive_fields = function(pos, formname, fields, sender)
+
+ -- if the user already has the right to use this and did input text
+ if( fields.text
+ and ( not(fields.locks_sent_lock_command)
+ or fields.locks_sent_lock_command=="")
+ and locks:lock_allow_use( pos, sender )) then
+
+ --print("Sign at "..minetest.pos_to_string(pos).." got "..dump(fields))
+ local meta = minetest.env:get_meta(pos)
+ fields.text = fields.text or "";
+ print((sender:get_player_name() or "").." wrote \""..fields.text..
+ "\" to sign at "..minetest.pos_to_string(pos));
+ meta:set_string("text", fields.text);
+ meta:set_string("infotext", '"'..fields.text..'"'.." ["..sender:get_player_name().."]");
+
+ -- a command for the lock?
+ else
+ locks:lock_handle_input( pos, formname, fields, sender );
+ end
+
+ end,
+ });
+
+
+minetest.register_craft({
+ output = 'locks:shared_locked_sign_wall',
+ recipe = {
+ { 'default:sign_wall', 'locks:lock', '' },
+ },
+})
+
+print( "[Mod] locks: loading locks:shared_locked_sign_wall");
diff --git a/locks/shared_locked_xdoors2.lua b/locks/shared_locked_xdoors2.lua
new file mode 100644
index 0000000..1af36fc
--- /dev/null
+++ b/locks/shared_locked_xdoors2.lua
@@ -0,0 +1,212 @@
+-- xDoors² mod by xyz
+-- modified by Sokomine to allow locked doors that can only be opened/closed/dig up by the player who placed them
+-- a little bit modified by addi to allow someone with the priv "opendoors" to open/close/dig all locked doors.
+-- Sokomine: modified again so that it uses the new locks-mod
+
+local door_bottom = {-0.5, -0.5, -0.5, 0.5, 0.5, -0.4}
+local door_top = {
+ {-0.5, -0.5, -0.5, -0.3, 0.5, -0.4},
+ {0.3, -0.5, -0.5, 0.5, 0.5, -0.4},
+ {-0.3, 0.3, -0.5, 0.3, 0.5, -0.4},
+ {-0.3, -0.5, -0.5, 0.3, -0.4, -0.4},
+ {-0.05, -0.4, -0.5, 0.05, 0.3, -0.4},
+ {-0.3, -0.1, -0.5, -0.05, 0, -0.4},
+ {0.05, -0.1, -0.5, 0.3, 0, -0.4}
+}
+
+local is_top = function(name)
+ return name:sub(12, 12) == "t"
+end
+
+
+local xdoors2_transform = function(pos, node, puncher)
+
+ if( not( locks:lock_allow_use( pos, puncher ))) then
+ minetest.chat_send_player( puncher:get_player_name(), "This door is locked. It can only be opened by its owner or people with a key that fits.");
+ return;
+ end
+
+ if is_top(node.name) then
+ pos = {x = pos.x, y = pos.y - 1, z = pos.z}
+ end
+ local t = 3 - node.name:sub(-1)
+ local p2 = 0
+ if t == 2 then
+ p2 = (node.param2 + 1) % 4
+ else
+ p2 = (node.param2 + 3) % 4
+ end
+
+ local olddata = locks:get_lockdata( pos );
+ minetest.env:add_node(pos, {name = "locks:door_bottom_"..t, param2 = p2})
+ minetest.env:add_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "locks:door_top_"..t, param2 = p2})
+
+ -- remember who owns the door, what passwords are set etc.
+ locks:set_lockdata( pos, olddata );
+ locks:set_lockdata( {x = pos.x, y = pos.y + 1, z = pos.z}, olddata );
+end
+
+
+local xdoors2_destruct = function(pos, oldnode)
+ if is_top(oldnode.name) then
+ pos = {x = pos.x, y = pos.y - 1, z = pos.z}
+ end
+ minetest.env:remove_node(pos)
+ minetest.env:remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
+end
+
+for i = 1, 2 do
+ minetest.register_node("locks:door_top_"..i, {
+ tiles = {"xdoors2_side.png", "xdoors2_side.png", "xdoors2_top.png", "xdoors2_bottom.png", "xdoors2_top_"..(3 - i)..".png", "xdoors2_top_"..i..".png"},
+ paramtype = "light",
+ paramtype2 = "facedir",
+ drawtype = "nodebox",
+ drop = "locks:door",
+ groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+ node_box = {
+ type = "fixed",
+ fixed = door_top
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = door_bottom
+ },
+ on_punch = xdoors2_transform,
+ after_dig_node = xdoors2_destruct,
+
+ on_construct = function(pos)
+ locks:lock_init( pos,
+ "size[8,2]"..
+ "field[0.3,0.6;6,0.7;locks_sent_lock_command;Locked door. Type /help for help:;]"..
+ "button_exit[6.3,1.2;1.7,0.7;locks_sent_input;Proceed]" );
+ end,
+
+ on_receive_fields = function(pos, formname, fields, sender)
+ locks:lock_handle_input( pos, formname, fields, sender );
+ end,
+
+ can_dig = function(pos,player)
+ return locks:lock_allow_dig( pos, player );
+ end
+ })
+ minetest.register_node("locks:door_bottom_"..i, {
+ tiles = {"xdoors2_side.png", "xdoors2_side.png", "xdoors2_top.png", "xdoors2_bottom.png", "locks_xdoors2_bottom_"..(3 - i)..".png", "locks_xdoors2_bottom_"..i..".png"},
+ paramtype = "light",
+ paramtype2 = "facedir",
+ drawtype = "nodebox",
+ drop = "locks:door",
+ groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
+ node_box = {
+ type = "fixed",
+ fixed = door_bottom
+ },
+ selection_box = {
+ type = "fixed",
+ fixed = door_bottom
+ },
+ on_punch = xdoors2_transform,
+ after_dig_node = xdoors2_destruct,
+
+ on_construct = function(pos)
+ locks:lock_init( pos,
+ "size[8,2]"..
+ "field[0.3,0.6;6,0.7;locks_sent_lock_command;Locked door. Type /help for help:;]"..
+ "button_exit[6.3,0.2;1.7,0.7;locks_sent_input;Proceed]" );
+ end,
+
+ on_receive_fields = function(pos, formname, fields, sender)
+ locks:lock_handle_input( pos, formname, fields, sender );
+ end,
+
+ can_dig = function(pos,player)
+ return locks:lock_allow_dig( pos, player );
+ end
+ })
+end
+
+local delta = {
+ {x = -1, z = 0},
+ {x = 0, z = 1},
+ {x = 1, z = 0},
+ {x = 0, z = -1}
+}
+
+minetest.register_node("locks:door", {
+ description = "Shared locked Wooden Door",
+ node_placement_prediction = "",
+ inventory_image = 'locks_xdoors2_door.png',
+ wield_image = 'xdoors2_door.png',
+ stack_max = 1,
+ on_place = function(itemstack, placer, pointed_thing)
+ local above = pointed_thing.above
+
+ -- there should be 2 empty nodes
+ if minetest.env:get_node({x = above.x, y = above.y + 1, z = above.z}).name ~= "air" then
+ return itemstack
+ end
+
+ local fdir = 0
+ local placer_pos = placer:getpos()
+ if placer_pos then
+ dir = {
+ x = above.x - placer_pos.x,
+ y = above.y - placer_pos.y,
+ z = above.z - placer_pos.z
+ }
+ fdir = minetest.dir_to_facedir(dir)
+ end
+
+ local t = 1
+ local another_door = minetest.env:get_node({x = above.x + delta[fdir + 1].x, y = above.y, z = above.z + delta[fdir + 1].z})
+ if (another_door.name:sub(-1) == "1" and another_door.param2 == fdir)
+ or (another_door.name:sub(-1) == "2" and another_door.param2 == (fdir + 1) % 4) then
+ t = 2
+ end
+
+ minetest.env:add_node(above, {name = "locks:door_bottom_"..t, param2 = fdir})
+ minetest.env:add_node({x = above.x, y = above.y + 1, z = above.z}, {name = "locks:door_top_"..t, param2 = fdir})
+
+ -- store who owns the door; the other data can be default for now
+ locks:lock_set_owner( above, placer:get_player_name() or "", "Shared locked door");
+ locks:lock_set_owner( {x = above.x, y = above.y + 1, z = above.z}, placer:get_player_name() or "", "Shared locked door");
+
+ return ItemStack("")
+ end
+})
+
+
+-- if xdoors2 is installed
+if( minetest.get_modpath("xdoors2") ~= nil ) then
+ minetest.register_craft({
+ output = 'locks:door',
+ recipe = {
+ { 'xdoors2:door', 'locks:lock', '' },
+ },
+ });
+
+-- if the normal doors are installed
+else if( minetest.get_modpath("doors") ~= nil ) then
+
+ minetest.register_craft({
+ output = 'locks:door',
+ recipe = {
+ { 'doors:door_wood', 'locks:lock', '' },
+ },
+ })
+
+-- fallback if no doors can be found
+else
+ minetest.register_craft({
+ output = 'locks:door',
+ recipe = {
+ { 'default:wood', 'default:wood', '' },
+ { 'default:wood', 'default:wood', 'locks:lock' },
+ { 'default:wood', 'default:wood', '' },
+ },
+ });
+end
+end -- of previous else
+
+
+
+print( "[Mod] locks: loading locks:door");
diff --git a/locks/textures/bg_shared_locked_chest.jpg b/locks/textures/bg_shared_locked_chest.jpg
new file mode 100644
index 0000000..531b004
--- /dev/null
+++ b/locks/textures/bg_shared_locked_chest.jpg
Binary files differ
diff --git a/locks/textures/bg_shared_locked_furnace.jpg b/locks/textures/bg_shared_locked_furnace.jpg
new file mode 100644
index 0000000..f77d584
--- /dev/null
+++ b/locks/textures/bg_shared_locked_furnace.jpg
Binary files differ
diff --git a/locks/textures/bg_shared_locked_sign.jpg b/locks/textures/bg_shared_locked_sign.jpg
new file mode 100644
index 0000000..866a622
--- /dev/null
+++ b/locks/textures/bg_shared_locked_sign.jpg
Binary files differ
diff --git a/locks/textures/licence.txt b/locks/textures/licence.txt
new file mode 100644
index 0000000..2591083
--- /dev/null
+++ b/locks/textures/licence.txt
@@ -0,0 +1,88 @@
+Licence for the following grafiks:
+lock
+key
+keychain
+
+author: addi
+
+This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
+http://creativecommons.org/licenses/by-sa/3.0/
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+You are free:
+
+ to Share — to copy, distribute and transmit the work
+ to Remix — to adapt the work
+
+
+Under the following conditions:
+
+ Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
+
+ Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.
+
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
+
+1. Definitions
+
+ "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
+ "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License.
+ "Creative Commons Compatible License" means a license that is listed at http://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License.
+ "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
+ "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.
+ "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
+ "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
+ "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
+ "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
+ "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
+ "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
+
+ to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
+ to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
+ to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
+ to Distribute and Publicly Perform Adaptations.
+
+ For the avoidance of doubt:
+ Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
+ Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and,
+ Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
+
+ You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested.
+ You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
+ If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
+ Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
+ Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
+
+8. Miscellaneous
+
+ Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
+ Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
+ If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+ No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
+ This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
+ The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
diff --git a/locks/textures/locks_key16.png b/locks/textures/locks_key16.png
new file mode 100644
index 0000000..ed4d1f8
--- /dev/null
+++ b/locks/textures/locks_key16.png
Binary files differ
diff --git a/locks/textures/locks_key32.png b/locks/textures/locks_key32.png
new file mode 100644
index 0000000..07d6edd
--- /dev/null
+++ b/locks/textures/locks_key32.png
Binary files differ
diff --git a/locks/textures/locks_keychain16.png b/locks/textures/locks_keychain16.png
new file mode 100644
index 0000000..0b5f5d6
--- /dev/null
+++ b/locks/textures/locks_keychain16.png
Binary files differ
diff --git a/locks/textures/locks_keychain32.png b/locks/textures/locks_keychain32.png
new file mode 100644
index 0000000..39439e2
--- /dev/null
+++ b/locks/textures/locks_keychain32.png
Binary files differ
diff --git a/locks/textures/locks_lock16.png b/locks/textures/locks_lock16.png
new file mode 100644
index 0000000..6c841d6
--- /dev/null
+++ b/locks/textures/locks_lock16.png
Binary files differ
diff --git a/locks/textures/locks_lock32.png b/locks/textures/locks_lock32.png
new file mode 100644
index 0000000..139b332
--- /dev/null
+++ b/locks/textures/locks_lock32.png
Binary files differ
diff --git a/locks/textures/locks_xdoors2_bottom_1.png b/locks/textures/locks_xdoors2_bottom_1.png
new file mode 100644
index 0000000..0c6609e
--- /dev/null
+++ b/locks/textures/locks_xdoors2_bottom_1.png
Binary files differ
diff --git a/locks/textures/locks_xdoors2_bottom_2.png b/locks/textures/locks_xdoors2_bottom_2.png
new file mode 100644
index 0000000..b20cdf4
--- /dev/null
+++ b/locks/textures/locks_xdoors2_bottom_2.png
Binary files differ
diff --git a/locks/textures/locks_xdoors2_door.png b/locks/textures/locks_xdoors2_door.png
new file mode 100644
index 0000000..cc3d0d3
--- /dev/null
+++ b/locks/textures/locks_xdoors2_door.png
Binary files differ
diff --git a/locks/textures/xdoors2_bottom.png b/locks/textures/xdoors2_bottom.png
new file mode 100644
index 0000000..15ce4bd
--- /dev/null
+++ b/locks/textures/xdoors2_bottom.png
Binary files differ
diff --git a/locks/textures/xdoors2_side.png b/locks/textures/xdoors2_side.png
new file mode 100644
index 0000000..4c8937d
--- /dev/null
+++ b/locks/textures/xdoors2_side.png
Binary files differ
diff --git a/locks/textures/xdoors2_top.png b/locks/textures/xdoors2_top.png
new file mode 100644
index 0000000..2009fb9
--- /dev/null
+++ b/locks/textures/xdoors2_top.png
Binary files differ
diff --git a/locks/textures/xdoors2_top_1.png b/locks/textures/xdoors2_top_1.png
new file mode 100644
index 0000000..49b3c22
--- /dev/null
+++ b/locks/textures/xdoors2_top_1.png
Binary files differ
diff --git a/locks/textures/xdoors2_top_2.png b/locks/textures/xdoors2_top_2.png
new file mode 100644
index 0000000..c30539e
--- /dev/null
+++ b/locks/textures/xdoors2_top_2.png
Binary files differ
diff --git a/locks/textures/xdoors2locked_bottom_1.png b/locks/textures/xdoors2locked_bottom_1.png
new file mode 100644
index 0000000..db458a5
--- /dev/null
+++ b/locks/textures/xdoors2locked_bottom_1.png
Binary files differ
diff --git a/locks/textures/xdoors2locked_bottom_2.png b/locks/textures/xdoors2locked_bottom_2.png
new file mode 100644
index 0000000..5f7221b
--- /dev/null
+++ b/locks/textures/xdoors2locked_bottom_2.png
Binary files differ
diff --git a/locks/textures/xdoors2locked_door.png b/locks/textures/xdoors2locked_door.png
new file mode 100644
index 0000000..6247067
--- /dev/null
+++ b/locks/textures/xdoors2locked_door.png
Binary files differ