aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--init.lua253
1 files changed, 231 insertions, 22 deletions
diff --git a/init.lua b/init.lua
index 016d709..82b627f 100644
--- a/init.lua
+++ b/init.lua
@@ -1,8 +1,81 @@
--- TODO: only one per player
--- TODO: names ought to be ids
+--[[
+ The apartment mod allows players to rent a place with locked objects in
+ - the ownership of the locked objects is transfered to the player who
+ rented the apartment.
+
+ Copyright (C) 2014 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.0
+ Autor: Sokomine
+ Date: 12.02.14
+--]]
+
+-- Changelog:
+-- 14.02.14 Improved formspecs, messages and descriptions of rented and vacant items.
+-- Players with the apartment_unrent priv can now throw other players out of apartments.
+-- Apartment names have to be uniq.
+-- Each player can only rent one apartment at a time.
+-- Added /aphome command
+
+minetest.register_privilege("apartment_unrent", { description = "allows to throw players out of apartments they have rented", give_to_singleplayer = false});
+
apartment = {}
+-- will contain information about all apartments of the server in the form:
+-- { apartment_descr = { pos={x=0,y=0,z=0}, original_owner='', owner=''}
+apartment.apartments = {};
+
+-- set to false if you do not like your players
+apartment.enable_aphome_command = true;
+
+-- TODO: save and restore ought to be library functions and not implemented in each individual mod!
+-- called whenever an apartment is added or removed
+apartment.save_data = function()
+
+ local data = minetest.serialize( apartment.apartments );
+ local path = minetest.get_worldpath().."/apartment.data";
+
+ local file = io.open( path, "w" );
+ if( file ) then
+ file:write( data );
+ file:close();
+ else
+ print("[Mod apartment] Error: Savefile '"..tostring( path ).."' could not be written.");
+ end
+end
+
+
+apartment.restore_data = function()
+
+ local path = minetest.get_worldpath().."/apartment.data";
+
+ local file = io.open( path, "r" );
+ if( file ) then
+ local data = file:read("*all");
+ apartment.apartments = minetest.deserialize( data );
+ file:close();
+ else
+ print("[Mod apartment] Error: Savefile '"..tostring( path ).."' not found.");
+ end
+end
+
+
+
apartment.get_formspec = function( pos, placer )
@@ -19,20 +92,32 @@ apartment.get_formspec = function( pos, placer )
-- if a name has been set
if( descr and descr ~= '' ) then
+ local size_txt = 'label[0.0,0.2;It extends]'..
+ 'label[1.0,0.2;'..(meta:get_string("size_right"))..' m to the right,]'..
+ 'label[2.6,0.2;'..(meta:get_string("size_left" ))..' m to the left,]'..
+ 'label[4.0,0.2;'..(meta:get_string("size_up" ))..' m up,]'..
+ 'label[4.8,0.2;'..(meta:get_string("size_down" ))..' m down,]'..
+ 'label[0.0,0.5;'..(meta:get_string("size_back" ))..' m in front of you and]'..
+ 'label[2.3,0.5;'..(meta:get_string("size_front"))..' m behind you.]'..
+ 'label[3.9,0.5;It has been built by]'..
+ 'label[0.0,0.8;'..(original_owner or '?')..'.]';
+
if( original_owner ~= owner and owner ~= '' ) then
return 'size[6,3]'..
'label[2.0,-0.3;Apartment \''..minetest.formspec_escape( descr )..'\']'..
- 'label[0.5,1.0;This apartment is rented by]'..
- 'label[3.0,1.0;'..tostring( owner )..'.]'..
- 'button_exit[3,2.0;2,0.5;unrent;Move out]'..
- 'button_exit[1,2.0;1,0.5;abort;OK]';
+ size_txt..
+ 'label[0.5,1.4;This apartment is rented by:]'..
+ 'label[3.5,1.4;'..tostring( owner )..']'..
+ 'button_exit[3,2.5;2,0.5;unrent;Move out]'..
+ 'button_exit[1,2.5;1,0.5;abort;OK]';
end
return 'size[6,3]'..
'label[2.0,-0.3;Apartment \''..minetest.formspec_escape( descr )..'\']'..
- 'label[0.5,1.0;Do you want to rent this]'..
- 'label[3.0,1.0;apartment? It\'s free!]'..
- 'button_exit[3,2.0;2,0.5;rent;Yes, rent it]'..
- 'button_exit[1,2.0;1,0.5;abort;No.]';
+ size_txt..
+ 'label[0.5,1.4;Do you want to rent this]'..
+ 'label[2.8,1.4;apartment? It\'s free!]'..
+ 'button_exit[3,2.5;2,0.5;rent;Yes, rent it]'..
+ 'button_exit[1,2.5;1,0.5;abort;No.]';
end
-- defaults that fit to small appartments - change this if needed!
@@ -111,6 +196,13 @@ apartment.on_receive_fields = function(pos, formname, fields, player)
return;
end
+ -- avoid duplicate names
+ if( apartment.apartments[ fields.descr ] ) then
+ minetest.chat_send_player( pname, 'Error: An apartment by that name exists already (name: '..fields.descr..').'..
+ 'Please choose a diffrent name/id.');
+ return;
+ end
+
meta:set_int( 'size_up', size_up );
meta:set_int( 'size_down', size_down );
meta:set_int( 'size_right', size_right );
@@ -121,6 +213,11 @@ apartment.on_receive_fields = function(pos, formname, fields, player)
meta:set_string( 'descr', fields.descr );
meta:set_string( 'formspec', apartment.get_formspec( pos, player ));
+ apartment.rent( pos, original_owner );
+
+ apartment.apartments[ fields.descr ] = { pos={x=pos.x, y=pos.y, z=pos.z}, original_owner = original_owner, owner='' };
+ apartment.save_data();
+
minetest.chat_send_player( pname, 'Apartment \''..tostring( fields.descr )..'\' is ready for rental.');
return;
@@ -137,11 +234,28 @@ apartment.on_receive_fields = function(pos, formname, fields, player)
return;
-- actually rent the appartment
- elseif( fields.rent and not( apartment.rent( pos, pname ))) then
- minetest.chat_send_player( pname, 'Sorry. There was an internal error. Please try again later.');
- return;
-
elseif( fields.rent ) then
+
+ if( not( apartment.apartments[ descr ] )) then
+ minetest.chat_send_player( pname, 'Error: This apartment is not registered. Please un-rent it and ask the original buildier '..
+ 'to dig and place this panel again.');
+ return;
+ end
+
+ -- make sure only one apartment can be rented at a time
+ for k,v in pairs( apartment.apartments ) do
+ if( v and v.owner and v.owner==pname ) then
+ minetest.chat_send_player( pname, 'Sorry. You can only rent one apartment at a time. You have already '..
+ 'rented apartment '..k..'.');
+ return;
+ end
+ end
+
+ if( not( apartment.rent( pos, pname ))) then
+ minetest.chat_send_player( pname, 'Sorry. There was an internal error. Please try again later.');
+ return;
+ end
+
minetest.chat_send_player( pname, 'You have rented apartment \''..tostring( descr )..'\'. Enjoy your stay!');
meta:set_string( 'formspec', apartment.get_formspec( pos, player ));
return;
@@ -154,6 +268,18 @@ apartment.on_receive_fields = function(pos, formname, fields, player)
minetest.chat_send_player( pname, 'You have ended your rent of apartment \''..tostring( descr )..'\'. It is free for others to rent again.');
meta:set_string( 'formspec', apartment.get_formspec( pos, player ));
return;
+
+ -- someone else tries to throw the current owner out
+ elseif( fields.unrent and owner ~= original_owner and owner ~= pname ) then
+ if( not( minetest.check_player_privs(player_name, {apartment_unrent=true}))) then
+ minetest.chat_send_player( pname, 'You do not have the privilelge to throw other people out of apartments they have rented.');
+ return;
+ end
+ if( not( apartment.rent( pos, original_owner ) )) then
+ minetest.chat_send_player( pname, 'Something wrent wrong when giving back the apartment.');
+ return;
+ end
+ minetest.chat_send_player( pname, 'Player '..owner..' has been thrown out of the apartment. It can now be rented by another player.');
end
end
@@ -181,6 +307,13 @@ apartment.rent = function( pos, pname )
return false;
end
+ local rented_by = 'rented by '..pname;
+ if( pname == original_owner ) then
+ rented_by = '- vacant -';
+ end
+ -- else we might run into trouble if we use it in formspecs
+ descr = minetest.formspec_escape( descr );
+
local x1 = pos.x;
local y1 = pos.y;
local z1 = pos.z;
@@ -230,22 +363,32 @@ apartment.rent = function( pos, pname )
-- change the actual owner
m:set_string( 'owner', pname );
-- set a fitting infotext
- local itext = "Rented by "..pname;
+ local itext = 'Object in Ap. '..descr..' ('..rented_by..')';
n = minetest.get_node( {x=px, y=py, z=pz} );
--minetest.chat_send_player( pname, n.name..' found');
if( n.name == 'default:chest_locked' ) then
- itext = "Locked Chest (rented by "..pname..")";
+ itext = "Locked Chest in Ap. "..descr.." ("..rented_by..")";
+ elseif( n.name == 'apartment:apartment' ) then
+ if( pname==original_owner ) then
+ itext = "Rent apartment "..descr.." here by right-clicking this panel!";
+ else
+ itext = "Apartment rental control panel for apartment "..descr.." ("..rented_by..")";
+ end
elseif( n.name == 'doors:door_steel_b_1' or n.name == 'doors:door_steel_t_1'
or n.name == 'doors:door_steel_b_2' or n.name == 'doors:door_steel_t_2' ) then
- itext = "Apartment "..descr.." (rented by "..pname..")";
+ if( pname==original_owner ) then
+ itext = "Apartment "..descr.." (vacant)";
+ else
+ itext = "Apartment "..descr.." ("..rented_by..")";
+ end
-- doors use another meta text
m:set_string( 'doors_owner', pname );
elseif( n.name == "technic:iron_locked_chest" ) then
- itext = "Iron Locked Chest (rented by "..pname..")";
+ itext = "Iron Locked Chest in Ap. "..descr.." (" ..rented_by..")";
elseif( n.name == "technic:copper_locked_chest" ) then
- itext = "Copper Locked Chest (rented by "..pname..")";
+ itext = "Copper Locked Chest in Ap. "..descr.." ("..rented_by..")";
elseif( n.name == "technic:gold_locked_chest" ) then
- itext = "Gold Locked Chest (rented by "..pname..")";
+ itext = "Gold Locked Chest in Ap. "..descr.." (" ..rented_by..")";
end
m:set_string( "infotext", itext );
end
@@ -253,6 +396,17 @@ apartment.rent = function( pos, pname )
end
end
end
+
+ -- here, we need the original descr again
+ descr = meta:get_string( 'descr' );
+ if( apartment.apartments[ descr ] ) then
+ if( original_owner == pname ) then
+ apartment.apartments[ descr ].owner = '';
+ else
+ apartment.apartments[ descr ].owner = pname;
+ end
+ apartment.save_data();
+ end
return true;
end
@@ -318,12 +472,16 @@ minetest.register_node("apartment:apartment", {
local original_owner = meta:get_string( 'original_owner' );
local pname = player:get_player_name();
- if( original_owner and original_owner ~= pname ) then
+ if( not( original_owner ) or original_owner == '' ) then
+ return true;
+ end
+
+ if( original_owner ~= pname ) then
minetest.chat_send_player( pname, 'Sorry. Only the original owner of this apartment control panel can dig it.');
return false;
end
- if( original_owner and original_owner ~= owner and owner ~= '') then
+ if( original_owner ~= owner ) then
minetest.chat_send_player( pname, 'The apartment is currently rented to '..tostring( owner )..'. Please end that first.');
return false;
end
@@ -331,4 +489,55 @@ minetest.register_node("apartment:apartment", {
return true;
end,
+ after_dig_node = function(pos, oldnode, oldmetadata, digger)
+
+ if( not( oldmetadata ) or oldmetadata=="nil" or not(oldmetadata.fields)) then
+ minetest.chat_send_player( digger:get_player_name(), "Error: Could not find information about the apartment panel that is to be removed.");
+ return;
+ end
+
+ local descr = oldmetadata.fields[ "descr" ];
+ if( apartment.apartments[ descr ] ) then
+
+ -- actually remove the apartment
+ apartment.apartments[ descr ] = nil;
+ apartment.save_data();
+ minetest.chat_send_player( digger:get_player_name(), "Removed apartment "..descr.." successfully.");
+ end
+ end,
+
})
+
+
+if( apartment.enable_aphome_command ) then
+ minetest.register_chatcommand("aphome", {
+ params = "",
+ description = "Teleports you back to the apartment you rented.",
+ privs = {},
+ func = function(name, param)
+
+ if( not( name )) then
+ return;
+ end
+
+ local player = minetest.env:get_player_by_name(name);
+
+ for k,v in pairs( apartment.apartments ) do
+ -- found the apartment the player rented
+ if( v and v.owner and v.owner==name ) then
+ player:moveto( v.pos, false);
+ minetest.chat_send_player(name, "Welcome back to your apartment "..k..".");
+ return;
+ end
+ end
+
+ minetest.chat_send_player(name, "Please rent an apartment first.");
+ end
+ })
+end
+
+
+
+-- upon server start, read the savefile
+apartment.restore_data();
+