mirror of
				https://github.com/sys4-fr/server-nalc.git
				synced 2025-10-31 04:25:32 +01:00 
			
		
		
		
	initial commit
subgame + mods
This commit is contained in:
		
							
								
								
									
										3
									
								
								mods/markers/README.md
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								mods/markers/README.md
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,3 @@ | ||||
|  | ||||
| This is work in progress. | ||||
|  | ||||
							
								
								
									
										833
									
								
								mods/markers/areas.lua
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										833
									
								
								mods/markers/areas.lua
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,833 @@ | ||||
|  | ||||
| -- TODO: offer teleport button? | ||||
|  | ||||
| -- taken from mobf | ||||
| local COLOR_RED   = "#FF0000"; | ||||
| local COLOR_GREEN = "#00FF00"; | ||||
| local COLOR_WHITE = "#FFFFFF"; | ||||
|  | ||||
|  | ||||
| -- we need to store which list we present to which player | ||||
| markers.menu_data_by_player = {} | ||||
|  | ||||
|  | ||||
| markers.get_area_by_pos = function(pos) | ||||
|  | ||||
|    local found_areas = {}; | ||||
|    for id, area in pairs(areas.areas) do | ||||
|       if( pos.x >= area.pos1.x and pos.x <= area.pos2.x and | ||||
|           pos.y >= area.pos1.y and pos.y <= area.pos2.y and | ||||
|           pos.z >= area.pos1.z and pos.z <= area.pos2.z )then | ||||
|  | ||||
|          area[ 'id' ] = id; | ||||
|          table.insert(found_areas, area ); | ||||
|       end | ||||
|    end | ||||
|    return found_areas; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| -- mode: can be pos, player, all, subarea, main_areas | ||||
| -- mode_data: content depends on mode | ||||
| -- selected: display information about the area the player single-clicked on | ||||
| markers.get_area_list_formspec = function( player, mode, pos, mode_data, selected ) | ||||
|  | ||||
|  | ||||
|    local id_list = {}; | ||||
|    local title   = '???'; | ||||
|    local tlabel  = ''; | ||||
|  | ||||
|    -- expects a position in mode_data | ||||
|    if(     mode=='pos' ) then | ||||
|       -- title would be too long for a label | ||||
|       title  = 'All areas which contain position..'; | ||||
|       tlabel = '<'..minetest.pos_to_string( mode_data )..'>:'; | ||||
|  | ||||
|       for id, area in pairs(areas.areas) do | ||||
|  | ||||
|          if( mode_data.x >= area.pos1.x and mode_data.x <= area.pos2.x and | ||||
|              mode_data.y >= area.pos1.y and mode_data.y <= area.pos2.y and | ||||
|              mode_data.z >= area.pos1.z and mode_data.z <= area.pos2.z )then | ||||
|  | ||||
|             table.insert( id_list, id ); | ||||
|          end | ||||
|       end | ||||
|  | ||||
|    -- expects a playername in mode_data | ||||
|    elseif( mode=='player' ) then | ||||
|  | ||||
|       title  = 'All areas owned by player..'; | ||||
|       tlabel = '<'..tostring( mode_data )..'>:'; | ||||
|  | ||||
|       for id, area in pairs(areas.areas) do | ||||
|  | ||||
|          if( area.owner == mode_data ) then | ||||
|             table.insert( id_list, id ); | ||||
|          end | ||||
|       end | ||||
|  | ||||
|    -- expects an area_id in mode_data | ||||
|    elseif( mode=='subareas' ) then | ||||
|  | ||||
|       title  = 'All subareas of area..'; | ||||
|       tlabel = '<'..tostring( areas.areas[ mode_data ].name )..'> ['..tostring( mode_data )..']:'; | ||||
|  | ||||
|       for id, area in pairs(areas.areas) do | ||||
|  | ||||
|          if( area.parent and area.parent == mode_data ) then | ||||
|             table.insert( id_list, id ); | ||||
|          end | ||||
|       end | ||||
|  | ||||
|    -- show only areas that do not have parents | ||||
|    elseif( mode=='main_areas' ) then | ||||
|       title  = 'All main areas:'; | ||||
|       tlabel = '*all main areas*'; | ||||
|       for id, area in pairs(areas.areas) do | ||||
|  | ||||
|          if( not( area.parent )) then | ||||
|             table.insert( id_list, id ); | ||||
|          end | ||||
|       end | ||||
|   | ||||
|  | ||||
|    elseif( mode=='all' ) then | ||||
|       title  = 'All areas:';  | ||||
|       tlabel = '*all areas*'; | ||||
|  | ||||
|       for id, area in pairs(areas.areas) do | ||||
|          table.insert( id_list, id ); | ||||
|       end | ||||
|    end | ||||
|     | ||||
|  | ||||
|    local formspec = 'size[10,9]'; | ||||
|  | ||||
|    title  = minetest.formspec_escape( title ); | ||||
|    tlabel = minetest.formspec_escape( tlabel ); | ||||
|  | ||||
|    formspec = formspec.. | ||||
| 	"label[0.5,0;"..title.."]".. | ||||
| 	"label[4.7,0;"..tlabel.."]".. | ||||
| 	"label[0.5,8.5;Doubleclick to select area.]".. | ||||
| 	"label[4.7,8.5;Areas found: "..tostring( #id_list )..".]".. | ||||
| 	"textlist[0.5,0.5;7,8;markers_area_list_selection;";  | ||||
|  | ||||
|    local liste = ''; | ||||
|    for i,v in ipairs( id_list ) do | ||||
|       if( liste ~= '' ) then | ||||
|          liste = liste..','; | ||||
|       end | ||||
|       liste = liste..minetest.formspec_escape( areas:toString( v ) ); | ||||
|           | ||||
|    end | ||||
|  | ||||
|    -- highlight selected entry | ||||
|    if( selected ) then | ||||
|       formspec = formspec..liste..';'..selected..';false]'; | ||||
|    else | ||||
|       formspec = formspec..liste..';]'; | ||||
|    end | ||||
|     | ||||
|    local pname = player:get_player_name(); | ||||
|    if( not( markers.menu_data_by_player[ pname ] )) then | ||||
|       markers.menu_data_by_player[ pname ] = {}; | ||||
|    end | ||||
|  | ||||
|    -- display information about the location of the area the player clicked on | ||||
|    if( selected  | ||||
|       and id_list[ selected ] | ||||
|       and areas.areas[ id_list[ selected ]] ) then | ||||
|  | ||||
|       local this_area = areas.areas[ id_list[ selected ]]; | ||||
|  | ||||
|       local subareas = {}; | ||||
|       for i,v in pairs( areas.areas ) do | ||||
|          if( v.parent and v.parent == id_list[ selected ]) then | ||||
|             table.insert( subareas, i ); | ||||
|          end | ||||
|       end | ||||
|  | ||||
|       formspec = formspec.. | ||||
|                markers.show_compass_marker( 8.5, 3.0, false, pos, this_area.pos1, this_area.pos2 ); | ||||
|  | ||||
|  | ||||
|       if( this_area.parent) then | ||||
|          formspec = formspec.. | ||||
|                'button[8.0,0.5;2,0.5;show_parent;'..  | ||||
| 			minetest.formspec_escape( areas.areas[ this_area.parent ].name )..']'; | ||||
|       end | ||||
|  | ||||
|       if( #subareas > 0 ) then | ||||
|          formspec = formspec.. | ||||
|                'button[8.0,1.0;2,0.5;list_subareas;'.. | ||||
|                         minetest.formspec_escape( 'List subareas ('..tostring( #subareas )..')')..']'; | ||||
|       end | ||||
|   | ||||
|  | ||||
|       if( mode=='player' ) then | ||||
|          formspec = formspec.. | ||||
|                'label[8.0,1.5;'.. | ||||
| 			minetest.formspec_escape( this_area.owner..'\'s areas')..']'; | ||||
|       else | ||||
|          formspec = formspec.. | ||||
|                'button[8.0,1.5;2,0.5;list_player_areas;'.. | ||||
| 			minetest.formspec_escape( this_area.owner..'\'s areas')..']'; | ||||
|       end | ||||
|  | ||||
|    end | ||||
|  | ||||
|    formspec = formspec.. | ||||
|                'button[8.0,8.5;2,0.5;list_main_areas;List all main areas]'; | ||||
|  | ||||
|    -- we need to remember especially the id_list - else it would be impossible to know what the | ||||
|    -- player selected | ||||
|    markers.menu_data_by_player[ pname ] = { | ||||
| 	  typ       = 'area_list', | ||||
|           mode      = mode, | ||||
|           pos       = pos, | ||||
|           mode_data = mode_data, | ||||
|           list      = id_list, | ||||
|  | ||||
| 	  selected  = id_list[ selected ], | ||||
| 	}; | ||||
|           | ||||
| 	   | ||||
|    return formspec; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| -- shows a formspec with information about a particular area | ||||
| -- pos is the position of the marker stone or place where the player clicked | ||||
| --  with the land title register; it is used for relative display of coordinates | ||||
| markers.get_area_desc_formspec = function( id, player, pos ) | ||||
|  | ||||
|    if( not( areas.areas ) or not( id ) or not( areas.areas[ id ] )) then | ||||
|       return 'field[info;Error:;Area not found.]'; | ||||
|    end | ||||
|    local this_area = areas.areas[ id ]; | ||||
|  | ||||
|    local pname     = player:get_player_name(); | ||||
|  | ||||
|    -- show some buttons only if area is owned by the player | ||||
|    local is_owner  = false; | ||||
|  | ||||
|    if( this_area.owner == pname ) then | ||||
|       is_owner     = true; | ||||
|    end | ||||
|  | ||||
|    local formspec  = 'size[10,9]'.. | ||||
| 	'label[2.5,0.0;Area information and management]'.. | ||||
| 	'button_exit[4.7,7.0;1,0.5;abort;OK]'; | ||||
|  | ||||
|    -- general information about the area | ||||
|    formspec = formspec.. | ||||
| 	'label[0.5,1.0;This is area number ]'.. | ||||
|         'label[4.7,1.0;'..tostring( id )..']'.. | ||||
|  | ||||
| 	'label[0.5,1.5;The area is called ]'.. | ||||
|         'label[4.7,1.5;'..minetest.formspec_escape( this_area.name or '-not set-')..']'.. | ||||
|  | ||||
| 	'label[0.5,2.0;It is owned by ]'.. | ||||
|         'label[4.7,2.0;'..minetest.formspec_escape( this_area.owner)..']'; | ||||
|  | ||||
|  | ||||
|    -- these functions are only available to the owner of the area | ||||
|    if( is_owner ) then | ||||
|       formspec = formspec.. | ||||
|         'button_exit[8.0,0.0;2,0.5;change_owner;Change owner]'.. | ||||
|         'button_exit[8.0,1.0;2,0.5;delete;Delete]'.. | ||||
|         'button_exit[8.0,1.5;2,0.5;rename;Rename]'.. | ||||
|         'button_exit[8.0,2.0;2,0.5;list_player_areas;My areas]'; | ||||
|  | ||||
|    -- subareas of own areas can be deleted (but not renamed) | ||||
|    elseif( not( is_owner ) | ||||
|       and this_area.parent | ||||
|       and areas.areas[ this_area.parent ] | ||||
|       and areas.areas[ this_area.parent ].owner == pname ) then | ||||
|   | ||||
|       formspec = formspec.. | ||||
|         'button_exit[8.0,1.0;2,0.5;delete;Delete subarea]'.. | ||||
|         'button_exit[8.0,2.0;2,0.5;list_player_areas;Player\'s areas]'; | ||||
|  | ||||
|    else | ||||
|       formspec = formspec.. | ||||
|         'button_exit[8.0,2.0;2,0.5;list_player_areas;Player\'s areas]'; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    -- players with the areas priv get an extra menu | ||||
|    if( minetest.check_player_privs(pname, {areas=true})) then | ||||
|       formspec = formspec.. | ||||
|               'label[8.0,6.0;Admin commands:]'.. | ||||
|         'button_exit[8.0,6.5;2,0.5;change_owner;Change owner]'.. | ||||
|         'button_exit[8.0,7.0;2,0.5;delete;Delete]'.. | ||||
|         'button_exit[8.0,7.5;2,0.5;rename;Rename]'; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    -- show subowners and areas with the same coordinates | ||||
|    formspec = formspec.. | ||||
| 	'label[0.5,2.5;Further owners of the entire area:]'; | ||||
|    local further_owners = {}; | ||||
|    for i, area in pairs(areas.areas) do | ||||
|       if( i ~= id and | ||||
|           this_area.pos1.x == area.pos1.x and this_area.pos2.x == area.pos2.x and | ||||
|           this_area.pos1.y == area.pos1.y and this_area.pos2.y == area.pos2.y and | ||||
|           this_area.pos1.z == area.pos1.z and this_area.pos2.z == area.pos2.z )then | ||||
|  | ||||
|          table.insert( further_owners, area.owner ); | ||||
|       end | ||||
|    end | ||||
|    if( #further_owners > 0 ) then | ||||
|  | ||||
|       formspec = formspec.. | ||||
|         'label[4.7,2.5;'..minetest.formspec_escape( table.concat( further_owners, ', '))..'.]'; | ||||
|  | ||||
|       -- deleting subowners is done by deleting their areas | ||||
|       if( is_owner ) then | ||||
|          formspec = formspec.. | ||||
| 	        'button_exit[8.0,2.5;2,0.5;add_owner;Add]'; | ||||
|       end | ||||
|    else | ||||
|       formspec = formspec.. | ||||
|         'label[4.7,2.5;-none-]'; | ||||
|   | ||||
|       if( is_owner ) then | ||||
|          formspec = formspec.. | ||||
| 		'button_exit[8.0,2.5;2,0.5;add_owner;Add]'; | ||||
|       end | ||||
|    end   | ||||
|  | ||||
|  | ||||
|    -- is the area a subarea? | ||||
|    if( this_area.parent ) then | ||||
|       formspec = formspec.. | ||||
| 	'label[0.5,3.0;This area is a sub-area of area]'.. | ||||
| 	'label[4.7,3.0;'..minetest.formspec_escape( areas.areas[ this_area.parent ].name..' ['..this_area.parent..']' )..']'.. | ||||
|         'button_exit[8.0,3.0;2,0.5;show_parent;Show main area]'; | ||||
|    end | ||||
|   | ||||
|  | ||||
|    -- does the area have subareas, i.e. is it a parent area for others? | ||||
|    local sub_areas = {}; | ||||
|    for i, area in pairs(areas.areas) do | ||||
|       if( i ~= id and | ||||
|           area.parent == id ) then | ||||
|  | ||||
|          table.insert( sub_areas, i ); | ||||
|       end | ||||
|    end | ||||
|    if( #sub_areas > 0 ) then | ||||
|  | ||||
|       formspec = formspec.. | ||||
| 	'label[0.5,4.0;Number of defined subareas:]'.. | ||||
|         'label[4.7,4.0;'..tostring( #sub_areas )..']'.. | ||||
|         'button_exit[8.0,4.0;2,0.5;list_subareas;List subareas]'; | ||||
|    else | ||||
|       formspec = formspec.. | ||||
| 	'label[0.5,4.0;There are no subareas defined.]'; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    -- give information about the size of the area | ||||
|    local length_x = (math.abs( this_area.pos2.x - this_area.pos1.x )+1); | ||||
|    local length_y = (math.abs( this_area.pos2.y - this_area.pos1.y )+1); | ||||
|    local length_z = (math.abs( this_area.pos2.z - this_area.pos1.z )+1); | ||||
|  | ||||
|    formspec = formspec.. | ||||
|                'label[0.5,4.5;The area extends from]'.. | ||||
|                'label[4.7,4.5;'..minetest.pos_to_string( this_area.pos1 )..' to '..minetest.pos_to_string( this_area.pos2 )..'.]'.. | ||||
|                'label[4.7,4.75;It spans '..tostring( length_x ).. | ||||
|                                    ' x '..tostring( length_z ).. | ||||
|                                    ' = '..tostring( length_x * length_z ).. | ||||
|                                    ' m^2. Height: '..tostring( length_y )..' m.]'; | ||||
|  | ||||
|  | ||||
|    formspec = formspec.. | ||||
|                markers.show_compass_marker( 2.0, 7.0, true, pos, this_area.pos1, this_area.pos2 ); | ||||
|  | ||||
| -- TODO: buy / sell button | ||||
|  | ||||
|    local pname = player:get_player_name(); | ||||
|    if( not( markers.menu_data_by_player[ pname ] )) then | ||||
|       markers.menu_data_by_player[ pname ] = {}; | ||||
|    end | ||||
|  | ||||
|    -- we need to remember especially the id_list - else it would be impossible to know what the | ||||
|    -- player selected | ||||
|    markers.menu_data_by_player[ pname ] = | ||||
| 	{ typ       = 'show_area', | ||||
|           mode      = nil,  | ||||
|           pos       = pos, | ||||
|           mode_data = nil, | ||||
|           list      = nil, | ||||
|  | ||||
| 	  selected  = id, | ||||
| 	}; | ||||
|           | ||||
|    return formspec; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| -- shows where the area (defined by pos1/pos2) is located relative to the given position pos | ||||
| -- row_offset/col_offset are offsets for the formspec | ||||
| markers.show_compass_marker = function( col_offset, row_offset, with_text, pos, pos1, pos2 ) | ||||
|  | ||||
|    local formspec = ''; | ||||
| -- TODO: show up/down information somehow | ||||
| -- TODO: what if checked with a land claim register? | ||||
|  | ||||
|    -- if possible, show how far the area streches into each direction relative to pos | ||||
|    if(     pos.x >= pos1.x and pos.x <= pos2.x  | ||||
|        and pos.y >= pos1.y and pos.y <= pos2.y  | ||||
|        and pos.z >= pos1.z and pos.z <= pos2.z ) then | ||||
|   | ||||
|       if( with_text ) then | ||||
|          formspec = formspec.. | ||||
| 		'label[0.5,5.5;Dimensions of the area in relation to..]'.. | ||||
| -- TODO: check if there is a marker; else write 'position you clicked on' | ||||
| 		'label[4.7,5.5;the marker at '..minetest.pos_to_string( pos )..':]'.. | ||||
| 		'button_exit[8.0,5.5;2,0.5;list_areas_at;Local areas]'; | ||||
|       end | ||||
|       formspec = formspec.. | ||||
| 		'image['..col_offset..','..row_offset..';1,1;markers_stone.png]'.. | ||||
| 		'label['..(col_offset-0.8)..','..(row_offset+0.05)..';'..tostring( pos.x - pos1.x         )..' m W]'.. | ||||
| 		'label['..(col_offset+1.0)..','..(row_offset+0.05)..';'..tostring(         pos2.x - pos.x )..' m E]'.. | ||||
| 		'label['..(col_offset+0.1)..','..(row_offset+0.80)..';'..tostring( pos.z - pos1.z         )..' m S]'.. | ||||
| 		'label['..(col_offset+0.1)..','..(row_offset-0.80)..';'..tostring(         pos2.z - pos.z )..' m N]'; | ||||
|  | ||||
|    -- else show how far the area is away | ||||
|    else | ||||
|  | ||||
|       local starts_north = ''; | ||||
|       local starts_south = ''; | ||||
|       local starts_east  = ''; | ||||
|       local starts_west  = ''; | ||||
|       if( pos.z > pos2.z ) then | ||||
|          starts_north = ''; | ||||
|          starts_south = tostring( pos.z - pos2.z         )..' m S'; | ||||
|       else | ||||
|          starts_north = tostring(         pos1.z - pos.z )..' m N'; | ||||
|          starts_south = ''; | ||||
|       end | ||||
|       if( pos.x > pos2.x ) then | ||||
|          starts_east  = ''; | ||||
|          starts_west  = tostring( pos.x - pos2.x         )..' m W'; | ||||
|       else | ||||
|          starts_east  = tostring(         pos1.x - pos.x )..' m E'; | ||||
|          starts_west  = ''; | ||||
|       end | ||||
|  | ||||
|  | ||||
|       if( with_text ) then | ||||
|          formspec = formspec.. | ||||
| 		'label[0.5,5.5;Position of the area in relation to..]'.. | ||||
| -- TODO: check if there is a marker; else write 'position you clicked on' | ||||
| 		'label[4.7,5.5;the marker at '..minetest.pos_to_string( pos )..':]'.. | ||||
| 		'button_exit[8.0,5.5;2,0.5;list_areas_at;Local areas]'; | ||||
|       end | ||||
|       formspec = formspec.. | ||||
| 		'image['..col_offset..','..row_offset..';1,1;compass_side_top.png]'.. | ||||
| 		'label['..(col_offset-0.8)..','..(row_offset+0.05)..';'..starts_west..']'.. | ||||
| 		'label['..(col_offset+1.0)..','..(row_offset+0.05)..';'..starts_east..']'.. | ||||
| 		'label['..(col_offset+0.1)..','..(row_offset-0.80)..';'..starts_north..']'.. | ||||
| 		'label['..(col_offset+0.1)..','..(row_offset+0.80)..';'..starts_south..']'; | ||||
|    end | ||||
|   | ||||
|    return formspec; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| -- formspec input needs to be handled diffrently | ||||
| markers.form_input_handler_areas = function( player, formname, fields) | ||||
|  | ||||
|    local pname = player:get_player_name(); | ||||
|  | ||||
|    if( formname ~= "markers:info" | ||||
|       or not( player ) | ||||
|       or not(  markers.menu_data_by_player[ pname ] )) then | ||||
|     | ||||
|       return false; | ||||
|    end | ||||
|    | ||||
|    local menu_data = markers.menu_data_by_player[ pname ]; | ||||
|    local formspec = ''; | ||||
|  | ||||
|  | ||||
|    -- rename an area | ||||
|    if( fields.rename  | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] | ||||
|           and areas.areas[ menu_data.selected ].owner == pname ) then | ||||
|     | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|       if( not( area.name )) then | ||||
|          area.name = '-enter area name-'; | ||||
|       end | ||||
|       formspec = 'field[rename_new_name;Enter new name for area:;'..minetest.formspec_escape( area.name )..']'; | ||||
|  | ||||
|    elseif( fields.rename_new_name  | ||||
|           and menu_data.selected | ||||
|           and  areas.areas[ menu_data.selected ] | ||||
|           and ((areas.areas[ menu_data.selected ].owner == pname )  | ||||
|             or minetest.check_player_privs(pname, {areas=true}))) then | ||||
|     | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|  | ||||
|       -- actually rename the area | ||||
|       areas.areas[ menu_data.selected ].name = fields.rename_new_name; | ||||
|       areas:save(); | ||||
|  | ||||
|       minetest.chat_send_player( pname, 'Area successfully renamed.'); | ||||
|       -- shwo the renamed area | ||||
|       formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|   | ||||
|  | ||||
|     | ||||
|    -- change owner the area | ||||
|    elseif( fields.change_owner | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] ) then | ||||
|     | ||||
|       -- there are no checks here - those happen when the area is transferred | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|       formspec = 'field[change_owner_name;Give area \"'..minetest.formspec_escape( area.name )..'\" to player:;-enter name of NEW OWNER-]'; | ||||
|  | ||||
|    elseif( fields.change_owner_name | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] ) then | ||||
|  | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|  | ||||
|       -- only own areas can be transfered to another player (or if the areas priv is there) | ||||
|       if( area.owner ~= pname  | ||||
|         and not( minetest.check_player_privs(pname, {areas=true}))) then | ||||
|   | ||||
|          minetest.chat_send_player( pname, 'Permission denied. You do not own the area.'); | ||||
|  | ||||
|       elseif( not( areas:player_exists( fields.change_owner_name ))) then | ||||
|  | ||||
|          minetest.chat_send_player( pname, 'That player does not exist.'); | ||||
|  | ||||
|       else | ||||
|          -- actually change the owner | ||||
|          areas.areas[ menu_data.selected ].owner = fields.change_owner_name; | ||||
|          areas:save() | ||||
|  | ||||
|          minetest.chat_send_player( pname, 'Your area '..tostring( area.name )..' has been transfered to '..tostring( fields.change_owner_name )..'.'); | ||||
|  | ||||
|          minetest.chat_send_player( fields.change_owner_name, pname..'" has given you control over an area.') | ||||
|       end | ||||
|  | ||||
|       formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|  | ||||
|  | ||||
|    -- add an owner to the entire area | ||||
|    elseif( fields.add_owner | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] | ||||
|           and areas.areas[ menu_data.selected ].owner == pname ) then | ||||
|     | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|       formspec = 'field[add_owner_name;Grant access to area \"'..minetest.formspec_escape( area.name )..'\" to player:;-enter player name-]'; | ||||
|  | ||||
|    elseif( fields.add_owner_name  | ||||
|               -- the player has to own the area already; we need a diffrent name here | ||||
|           and fields.add_owner_name ~= pname | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] | ||||
|           and areas.areas[ menu_data.selected ].owner == pname ) then | ||||
|  | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|  | ||||
|       -- does the player exist? | ||||
|       if( not( areas:player_exists( fields.add_owner_name ))) then | ||||
|          minetest.chat_send_player( pname, 'That player does not exist.'); | ||||
|          -- show the formspec | ||||
|          formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|  | ||||
|       else | ||||
|          -- log the creation of the new area | ||||
|          minetest.log("action", pname.." runs /add_owner through the markers-mod. Owner = "..fields.add_owner_name.. | ||||
|                                 " AreaName = "..area.name.." ParentID = "..menu_data.selected.. | ||||
|                                 " StartPos = "..area.pos1.x..","..area.pos1.y..","..area.pos1.z.. | ||||
|                                 " EndPos = "  ..area.pos2.x..","..area.pos2.y..","..area.pos2.z) | ||||
|  | ||||
|          -- take the name from the old/parent area | ||||
|          local new_id = areas:add( fields.add_owner_name, area.name, area.pos1, area.pos2, menu_data.selected ); | ||||
|          areas:save() | ||||
|  | ||||
|  | ||||
|          minetest.chat_send_player( fields.add_owner_name, | ||||
|                                 "You have been granted control over area #".. | ||||
|                                 new_id..". Type /list_areas to show your areas.") | ||||
|  | ||||
|          minetest.chat_send_player( pname, 'The player may now build and dig in your area.'); | ||||
|          -- shwo the new area | ||||
|          markers.menu_data_by_player[ pname ].selected = new_id; | ||||
|          formspec = markers.get_area_desc_formspec( new_id, player, menu_data.pos ); | ||||
|       end | ||||
|  | ||||
|  | ||||
|  | ||||
|    -- delete area | ||||
|    elseif( fields.delete  | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] ) then | ||||
|  | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|  | ||||
|       -- a player can only delete own areas or subareas of own areas | ||||
|       if( area.owner ~= pname  | ||||
|         and not(     area.parent  | ||||
|                  and areas.areas[ area.parent ]  | ||||
|                  and areas.areas[ area.parent ].owner | ||||
|                  and areas.areas[ area.parent ].owner == pname ) | ||||
|         and not( minetest.check_player_privs(pname, {areas=true}))) then | ||||
|   | ||||
|          minetest.chat_send_player( pname, 'Permission denied. You own neither the area itshelf nor its parent area.'); | ||||
|          -- shwo the area where the renaming failed | ||||
|          formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|  | ||||
|       else | ||||
|  | ||||
|          formspec = 'field[rename_new_name;Enter new name for area:;'..minetest.formspec_escape( area.name )..']'; | ||||
|          formspec = 'field[delete_confirm;'..minetest.formspec_escape( 'Really delete area \"'..area.name.. | ||||
|                             '\" (owned by '..area.owner..')? Confirm with YES:')..';-type yes in capitals to confirm-]'; | ||||
|  | ||||
|       end | ||||
|  | ||||
|    elseif( fields.delete_confirm  | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] ) then | ||||
|     | ||||
|       local area = areas.areas[ menu_data.selected ]; | ||||
|       local old_owner = area.owner; | ||||
|  | ||||
|       local subareas = {}; | ||||
|       for i,v in pairs( areas.areas ) do | ||||
|          if( v.parent and v.parent == menu_data.selected ) then | ||||
|             table.insert( subareas, i ); | ||||
|          end | ||||
|       end | ||||
|  | ||||
|       -- a player can only delete own areas or subareas of own areas | ||||
|       if( area.owner ~= pname  | ||||
|         and not(     area.parent  | ||||
|                  and areas.areas[ area.parent ]  | ||||
|                  and areas.areas[ area.parent ].owner | ||||
|                  and areas.areas[ area.parent ].owner == pname ) | ||||
|         and not( minetest.check_player_privs(pname, {areas=true}))) then | ||||
|   | ||||
|          minetest.chat_send_player( pname, 'Permission denied. You own neither the area itshelf nor its parent area.'); | ||||
|          -- shwo the renamed area | ||||
|          formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|  | ||||
|       -- avoid accidents | ||||
|       elseif( fields.delete_confirm ~= 'YES' ) then | ||||
|          minetest.chat_send_player( pname, 'Delition of area \"'..tostring( area.name )..'\" (owned by '..old_owner..') aborted.'); | ||||
|          formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|  | ||||
|       -- only areas without subareas can be deleted | ||||
|       elseif( #subareas > 0 ) then  | ||||
|          minetest.chat_send_player( pname, 'The area has '..tostring( #subareas )..' subarea(s). Please delete those first!'); | ||||
|          formspec = markers.get_area_desc_formspec( menu_data.selected, player, menu_data.pos ); | ||||
|  | ||||
|       else | ||||
|  | ||||
|          minetest.chat_send_player( pname, 'Area \"'..tostring( area.name )..'\" (owned by '..old_owner..') deleted.'); | ||||
|          -- really delete | ||||
|          areas:remove( menu_data.selected, false ); -- no recursive delete | ||||
|          areas:save(); | ||||
|          -- show the list of areas owned by the previous owner | ||||
|          formspec = markers.get_area_list_formspec( player, 'player',   menu_data.pos, old_owner, nil ); | ||||
|       end | ||||
|  | ||||
|     | ||||
|  | ||||
|    elseif( fields.show_parent  | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] | ||||
|           and areas.areas[ menu_data.selected ].parent ) then | ||||
|  | ||||
|       formspec = markers.get_area_desc_formspec( areas.areas[ menu_data.selected ].parent, player, menu_data.pos ); | ||||
|  | ||||
|  | ||||
|    elseif( fields.list_player_areas | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] ) then | ||||
|  | ||||
|       formspec = markers.get_area_list_formspec( player, 'player',   menu_data.pos, areas.areas[ menu_data.selected ].owner, nil ); | ||||
|  | ||||
|  | ||||
|    elseif( fields.list_subareas | ||||
|           and menu_data.selected | ||||
|           and areas.areas[ menu_data.selected ] ) then | ||||
|  | ||||
|       formspec = markers.get_area_list_formspec( player, 'subareas', menu_data.pos, menu_data.selected, nil ); | ||||
|  | ||||
|  | ||||
|    elseif( fields.list_main_areas ) then | ||||
|  | ||||
|       formspec = markers.get_area_list_formspec( player, 'main_areas', menu_data.pos, nil, nil ); | ||||
|            | ||||
|    elseif( fields.list_areas_at | ||||
|           and menu_data.pos ) then | ||||
|  | ||||
|       formspec = markers.get_area_list_formspec( player, 'pos',      menu_data.pos, menu_data.pos, nil ); | ||||
|  | ||||
|  | ||||
|    elseif( fields.markers_area_list_selection | ||||
|           and menu_data.typ | ||||
|           and menu_data.typ == 'area_list' | ||||
|           and menu_data.list | ||||
|           and #menu_data.list > 0 ) then | ||||
|  | ||||
|  | ||||
|       local field_data = fields.markers_area_list_selection:split( ':' ); | ||||
|       if( not( field_data ) or #field_data < 2 ) then | ||||
|          field_data = { '', '' }; | ||||
|       end | ||||
|  | ||||
|       local selected = tonumber( field_data[ 2 ] ); | ||||
|       if( field_data[1]=='DCL' ) then | ||||
|  | ||||
|          -- on doubleclick, show detailed area information | ||||
|          formspec = markers.get_area_desc_formspec( tonumber( menu_data.list[ selected ] ), player, menu_data.pos ); | ||||
|       else | ||||
|  | ||||
|          -- on single click, just show the position of that particular area | ||||
|          formspec = markers.get_area_list_formspec( player, menu_data.mode, menu_data.pos, menu_data.mode_data, selected ); | ||||
|       end | ||||
|  | ||||
|    else | ||||
|       return false; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    minetest.show_formspec( pname, "markers:info", formspec ) | ||||
|    return true; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| -- search the area at the given position pos that might be of most intrest to the player | ||||
| markers.show_marker_stone_formspec = function( player, pos ) | ||||
|  | ||||
|    local pname       = player:get_player_name(); | ||||
|  | ||||
|    -- this table stores the list the player may have selected from; at the beginning, there is no list  | ||||
|    if( not( markers.menu_data_by_player[ pname ]  )) then | ||||
|       markers.menu_data_by_player[ pname ] = { | ||||
| 	  typ       = 'area_list', | ||||
|           mode      = 'main_areas', | ||||
|           pos       = pos, | ||||
|           mode_data = pos, | ||||
|           list      = {}, | ||||
|  | ||||
| 	  selected  = nil, | ||||
|       }; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    local formspec        = ''; | ||||
|  | ||||
|    local found_areas     = {}; | ||||
|    local min_area_size   = 100000000000; | ||||
|  | ||||
|    for id, area in pairs(areas.areas) do | ||||
|       if( pos.x >= area.pos1.x and pos.x <= area.pos2.x and | ||||
|           pos.y >= area.pos1.y and pos.y <= area.pos2.y and | ||||
|           pos.z >= area.pos1.z and pos.z <= area.pos2.z )then | ||||
|  | ||||
|          -- ignore y (height) value because some areas may go from bottom to top | ||||
|          local area_size = math.abs( area.pos2.x - area.pos1.x ) | ||||
|                          * math.abs( area.pos2.z - area.pos1.z ); | ||||
|  | ||||
|          -- collect subareas that have the same size | ||||
|          if( area_size == min_area_size ) then | ||||
|             table.insert(found_areas, id ); | ||||
|          -- we have found a smaller area - that is more intresting here | ||||
|          elseif( area_size <= min_area_size ) then | ||||
|             found_areas = {}; | ||||
|             min_area_size = area_size; | ||||
|             table.insert(found_areas, id ); | ||||
|          end | ||||
|       end | ||||
|    end | ||||
|  | ||||
|    -- no areas found; display error message and selection menu | ||||
|    if(     #found_areas < 1 ) then | ||||
|  | ||||
|       formspec = 'size[4,3]'.. | ||||
|  		'label[0.5,0.5;This position is not protected.]'.. | ||||
| 		     'button[1.0,1.5;2,0.5;list_main_areas;List all main areas]'.. | ||||
| 		'button_exit[3.0,1.5;1,0.5;abort;OK]'; | ||||
|   | ||||
|    -- found exactly one areaa - display it | ||||
|    elseif( #found_areas == 1 ) then | ||||
|  | ||||
|       formspec = markers.get_area_desc_formspec( found_areas[ 1 ], player, pos ); | ||||
|  | ||||
|    -- found more than one area; we have saved only those with the smallest size | ||||
|    else | ||||
|  | ||||
|       local own_area    = 0; | ||||
|       local parent_area = 0; | ||||
|       local upper_area  = 0; | ||||
|       for i,v in ipairs( found_areas ) do | ||||
|  | ||||
|          local area = areas.areas[ v ]; | ||||
|  | ||||
|          -- owned by player? | ||||
|          if(          area.owner == pname ) then | ||||
|             own_area    = v; | ||||
|  | ||||
|          -- parentless area? | ||||
|          elseif( not( area.parent )) then | ||||
|             parent_area = v; | ||||
|  | ||||
|          -- the parent has diffrent coordinates? | ||||
|          elseif(      areas.areas[ area.parent ].pos1.x ~= area.pos1.x | ||||
|                    or areas.areas[ area.parent ].pos1.y ~= area.pos1.y | ||||
|                    or areas.areas[ area.parent ].pos1.z ~= area.pos1.z | ||||
|                    or areas.areas[ area.parent ].pos2.x ~= area.pos2.x | ||||
|                    or areas.areas[ area.parent ].pos2.y ~= area.pos2.y | ||||
|                    or areas.areas[ area.parent ].pos2.z ~= area.pos2.z ) then | ||||
|             upper_area = v; | ||||
|          end | ||||
|       end | ||||
|  | ||||
|       -- the area owned by the player is most intresting | ||||
|       if(     own_area    > 0 ) then | ||||
|  | ||||
|          formspec = markers.get_area_desc_formspec( own_area,    player, pos ); | ||||
|  | ||||
|       -- if the player owns none of these areas, show the topmost (parentless) area | ||||
|       elseif( parent_area > 0 ) then | ||||
|  | ||||
|          formspec = markers.get_area_desc_formspec( parent_area, player, pos ); | ||||
|  | ||||
|       -- an area which has a parent with diffrent coordinates from its child may (or may not) be the | ||||
|       -- parent of all these subareas we've found here; there is no guarantee, but it's a best guess. | ||||
|       -- If it is not good enough, then the player can still search for himshelf. | ||||
|       elseif( upper_area  > 0 ) then | ||||
|  | ||||
|          formspec = markers.get_area_desc_formspec( upper_area,  player, pos ); | ||||
|  | ||||
|       -- our superficial analysis of the structure of the areas failed; it is up to the player to | ||||
|       -- find out which of the candidates he is intrested in; we list them all | ||||
|       else | ||||
|  | ||||
|         formspec = markers.get_area_list_formspec( player, 'pos', pos, pos, nil ); | ||||
|       end | ||||
|    end | ||||
|  | ||||
|    minetest.show_formspec( player:get_player_name(), "markers:info", formspec ); | ||||
| end | ||||
							
								
								
									
										1
									
								
								mods/markers/depends.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								mods/markers/depends.txt
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1 @@ | ||||
| areas | ||||
							
								
								
									
										612
									
								
								mods/markers/init.lua
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										612
									
								
								mods/markers/init.lua
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,612 @@ | ||||
|  | ||||
| -- markers are useful for measuring distances and for marking areas | ||||
| -- markers are protected from digging by other players for one day | ||||
| -- (the protection for the *marker* auto-expires then, and it can be digged) | ||||
|  | ||||
| markers = {} | ||||
|  | ||||
| -- stores up to 4 marker positions for each player | ||||
| markers.positions = {} | ||||
|  | ||||
| -- store the positions of that many markers for each player (until server restart) | ||||
| markers.MAX_MARKERS  = 10; | ||||
|   | ||||
| -- the protection against digging of the marker by other players expires after this time | ||||
| markers.EXPIRE_AFTER = 60*60*24; | ||||
|  | ||||
| -- self-protected areas can not get higher than 100 blocks | ||||
| markers.MAX_HEIGHT   = 100; | ||||
|  | ||||
| -- only areas up to this size (in square meters) can be protected | ||||
| markers.MAX_SIZE     = 1024; -- 32m * 32m = 1024 m^2 | ||||
|  | ||||
|  | ||||
| dofile(minetest.get_modpath("markers").."/areas.lua"); | ||||
|  | ||||
| dofile(minetest.get_modpath("markers").."/marker_stone.lua"); | ||||
|  | ||||
| dofile(minetest.get_modpath("markers").."/land_title_register.lua"); | ||||
|  | ||||
|  | ||||
| -- returns the first area found | ||||
| markers.get_area_by_pos1_pos2 = function(pos1, pos2) | ||||
|    for id, area in pairs(areas.areas) do | ||||
|  | ||||
|       if( ((area.pos1.x == pos1.x and area.pos1.z == pos1.z ) | ||||
|         or (area.pos1.x == pos1.x and area.pos1.z == pos2.z ) | ||||
|         or (area.pos1.x == pos2.x and area.pos1.z == pos1.z ) | ||||
|         or (area.pos1.x == pos2.x and area.pos1.z == pos2.z )) | ||||
|  | ||||
|        and((area.pos2.x == pos1.x and area.pos2.z == pos1.z ) | ||||
|         or (area.pos2.x == pos1.x and area.pos2.z == pos2.z ) | ||||
|         or (area.pos2.x == pos2.x and area.pos2.z == pos1.z ) | ||||
|         or (area.pos2.x == pos2.x and area.pos2.z == pos2.z ))) then | ||||
|  | ||||
|           -- at least pos1 needs to have a hight value that fits in | ||||
|           if(  (area.pos1.y <= pos1.y and area.pos2.y >= pos1.y) | ||||
|             or (area.pos1.y >= pos1.y and area.pos2.y <= pos1.y)) then | ||||
|  | ||||
|              local found = area; | ||||
|              found[ 'id' ] = id; | ||||
|              return found; | ||||
|  | ||||
|           end | ||||
|       end | ||||
|    end | ||||
|    return nil; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| -- this function is supposed to return a text string describing the price of the land between po1 and pos2 | ||||
| -- You can return somethiing like "for free" or "the promise to build anything good" as well as any | ||||
| -- real prices in credits or materials - it's really just a text here. | ||||
| -- Make sure you do not charge the player more than what you ask here. | ||||
| markers.calculate_area_price_text = function( pos1, pos2, playername ) | ||||
|  | ||||
|    local price = ( math.abs( pos1.x - pos2.x )+1 ) | ||||
|                * ( math.abs( pos1.z - pos2.z )+1 ); | ||||
|  | ||||
| --               * math.ceil( ( math.abs( pos1.y - pos2.y )+1 )/10); | ||||
|  | ||||
|    return tostring( price )..' credits'; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| markers.marker_placed = function( pos, placer, itemstack ) | ||||
|   | ||||
|    if( not( pos ) or not( placer )) then | ||||
|       return; | ||||
|    end | ||||
|   | ||||
|    local meta = minetest.env:get_meta( pos ); | ||||
|    local name = placer:get_player_name(); | ||||
|  | ||||
|    meta:set_string( 'infotext', 'Marker at '..minetest.pos_to_string( pos ).. | ||||
| 				' (placed by '..tostring( name )..'). '.. | ||||
| 				'Right-click to update.'); | ||||
|    meta:set_string( 'owner',    name ); | ||||
|    -- this allows protection of this particular marker to expire | ||||
|    meta:set_string( 'time',     tostring( os.time()) ); | ||||
|  | ||||
|    local txt = ''; | ||||
|  | ||||
|    if( not( markers.positions[ name ] ) or #markers.positions[name]<1) then | ||||
|       markers.positions[ name ] = {}; | ||||
|       markers.positions[ name ][ 1 ] = pos; | ||||
|   | ||||
|       minetest.chat_send_player( name, | ||||
| 		'First marker set to position '.. | ||||
| 		minetest.pos_to_string( markers.positions[ name ][ 1 ] ).. | ||||
| 		'. Please place a second marker to measure distance. '.. | ||||
| 		'Place four markers in a square to define an area.'); | ||||
|    else | ||||
|       table.insert( markers.positions[ name ], pos ); | ||||
|  | ||||
|       local n = #markers.positions[ name ]; | ||||
|  | ||||
|       local dx = markers.positions[ name ][ n ].x - markers.positions[ name ][ n-1 ].x; | ||||
|       local dy = markers.positions[ name ][ n ].y - markers.positions[ name ][ n-1 ].y; | ||||
|       local dz = markers.positions[ name ][ n ].z - markers.positions[ name ][ n-1 ].z; | ||||
|  | ||||
|       local dir_name = "unknown"; | ||||
|       local d = 0; | ||||
|       if(     dx == 0 and dz > 0 )             then dir_name = "north"; d = math.abs(dz); | ||||
|       elseif( dx == 0 and dz < 0 )             then dir_name = "south"; d = math.abs(dz); | ||||
|       elseif( dz == 0 and dx > 0 )             then dir_name = "east";  d = math.abs(dx); | ||||
|       elseif( dz == 0 and dx < 0 )             then dir_name = "west";  d = math.abs(dx); | ||||
|       elseif( dx == 0 and dz == 0 and dy > 0 ) then dir_name = "above"; d = math.abs(dy); | ||||
|       elseif( dx == 0 and dz == 0 and dy < 0 ) then dir_name = "below"; d = math.abs(dy); | ||||
|       else | ||||
|  | ||||
|          local area   =        (math.abs( dx )+1) | ||||
|                              * (math.abs( dz )+1); | ||||
|          local volume = area * (math.abs( dy )+1); | ||||
|  | ||||
|          minetest.chat_send_player( name, 'This marker is at '.. | ||||
|                minetest.pos_to_string( markers.positions[ name ][ n ] )..', while the last one is at '.. | ||||
|                minetest.pos_to_string( markers.positions[ name ][ n-1 ] )..'. Distance (x/y/z): '.. | ||||
|                tostring(math.abs(dx))..'/'.. | ||||
|                tostring(math.abs(dy))..'/'.. | ||||
|                tostring(math.abs(dz)).. | ||||
|               '. Area: '..tostring( area )..' m^2. Volume: '..tostring( volume )..' m^3.'); | ||||
|       end | ||||
|       | ||||
|       -- this marker is aligned to the last one | ||||
|       if( d > 0 ) then | ||||
|          minetest.chat_send_player( name, 'Marker placed at '..minetest.pos_to_string( pos ).. | ||||
| 				'. Relative to the marker you placed before, this one is '.. | ||||
|  				tostring( d )..' m '..dir_name..'.'); | ||||
|       end | ||||
|  | ||||
|       -- do the last 4 markers placed form an area? | ||||
|       if( #markers.positions[ name ] > 3 ) then | ||||
|          local count_x_coord = {}; | ||||
|          local count_z_coord = {}; | ||||
|          local anz_x_coord   = 0; | ||||
|          local anz_z_coord   = 0; | ||||
|          local check_failed  = 0; | ||||
|          for i=0,3 do | ||||
|  | ||||
|             local v = markers.positions[ name ][ n-i ].x; | ||||
|  | ||||
|             if( not( count_x_coord[ v ] )) then | ||||
|                count_x_coord[       v ] = 1; | ||||
|                anz_x_coord = anz_x_coord + 1; | ||||
|             elseif(  count_x_coord[ v ] == 2 ) then                | ||||
|                check_failed = 1; | ||||
|             else | ||||
|                count_x_coord[       v ] = count_x_coord[ v ] + 1; | ||||
|             end | ||||
|  | ||||
|             v = markers.positions[ name ][ n-i ].z; | ||||
|             if( not( count_z_coord[ v ] )) then | ||||
|                count_z_coord[       v ] = 1; | ||||
|                anz_z_coord = anz_z_coord + 1; | ||||
|             elseif(  count_z_coord[ v ] == 2 ) then                | ||||
|                check_failed = 1; | ||||
|             else | ||||
|                count_z_coord[       v ] = count_z_coord[ v ] + 1; | ||||
|             end | ||||
|          end | ||||
|  | ||||
|          if(     anz_x_coord == 2  | ||||
|             and  anz_z_coord == 2 | ||||
|             and check_failed == 0 ) then | ||||
|                 | ||||
|             minetest.chat_send_player( name, 'The last four markers you placed form a rectangle. '.. | ||||
|                    'Right-click on this marker here in order to protect the area.'); | ||||
|          end | ||||
|       end | ||||
|  | ||||
|       -- make sure the list does not grow too large | ||||
|       if( n > markers.MAX_MARKERS ) then | ||||
|          table.remove( markers.positions[ name ], 1 ); | ||||
|       end | ||||
|    end | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| markers.marker_can_dig = function(pos,player)  | ||||
|  | ||||
|    if( not( pos ) or not( player )) then | ||||
|       return true; | ||||
|    end | ||||
|  | ||||
|    local meta  = minetest.env:get_meta( pos ); | ||||
|    local owner = meta:get_string( 'owner' ); | ||||
|    local time  = meta:get_string( 'time' );  | ||||
|  | ||||
|    -- can the marker be removed? | ||||
|    if( not( owner )  | ||||
|        or owner=='' | ||||
|        or not( time )  | ||||
|        or time=='' | ||||
|        or (os.time() - tonumber( time )) > markers.EXPIRE_AFTER ) then | ||||
|  | ||||
|       return true; | ||||
|  | ||||
|    -- marker whose data got lost anyway | ||||
|    elseif( not( markers.positions[ owner ] ) | ||||
|             or #markers.positions[ owner ] < 1 ) then | ||||
|     | ||||
|      return true; | ||||
|  | ||||
|    -- marker owned by someone else and still in use | ||||
|    elseif( owner ~= player:get_player_name()) then | ||||
|  | ||||
|       minetest.chat_send_player( player:get_player_name(), | ||||
| 		'Sorry, this marker belongs to '..tostring( owner ).. | ||||
| 		'. If you still want to remove it, try again in '.. | ||||
| 		( tostring( markers.EXPIRE_AFTER + tonumber( time ) - os.time()))..' seconds.'); | ||||
|       return false; | ||||
|  | ||||
|    end | ||||
|    | ||||
|    return true; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| markers.marker_after_dig_node = function(pos, oldnode, oldmetadata, digger) | ||||
|  | ||||
|    if( not(oldmetadata ) or not(oldmetadata['fields'])) then | ||||
|       return; | ||||
|    end | ||||
|  | ||||
|    local owner = oldmetadata['fields']['owner']; | ||||
|    if( not( owner )  | ||||
|        or owner=='' | ||||
|        or not( markers.positions[ owner ] ) | ||||
|        or     #markers.positions[ owner ] < 1 ) then | ||||
|  | ||||
|       return; | ||||
|    end | ||||
|  | ||||
|    -- remove the markers position from our table of stored positions | ||||
|    local found = 0; | ||||
|    for i,v in ipairs( markers.positions[ owner ] ) do | ||||
|       if(   v.x == pos.x  | ||||
|         and v.y == pos.y | ||||
|         and v.z == pos.z ) then | ||||
|          found = i; | ||||
|       end | ||||
|    end | ||||
|    if( found ~= 0 ) then | ||||
|       table.remove( markers.positions[ owner ], found ); | ||||
|    end | ||||
|    return true; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| markers.get_marker_formspec = function(player, pos, error_msg) | ||||
|    local formspec = ""; | ||||
|  | ||||
|    local meta  = minetest.env:get_meta( pos ); | ||||
|    local owner = meta:get_string( 'owner' ); | ||||
|  | ||||
|    local name  = player:get_player_name(); | ||||
|  | ||||
|    local formspec_info = "size[6,4]".. | ||||
|              "button_exit[2,2.5;1,0.5;abort;OK]".. | ||||
|              "textarea[1,1;4,2;info;Information;"; | ||||
|    if( owner ~= nil and owner ~= '' and owner ~= name ) then | ||||
|       return formspec_info.."This marker\ncan only be used by\n"..tostring( owner )..", who\nplaced the markers.]"; | ||||
|    end | ||||
|  | ||||
|    if( not( markers.positions[ name ]) or #markers.positions[name]<1) then | ||||
|       return formspec_info.."Information about the positions\nof your other markers\ngot lost.\nPlease dig and place\nyour markers again!]"; | ||||
|    end | ||||
|  | ||||
|    local n = #markers.positions[ name ]; | ||||
|  | ||||
|    if(    markers.positions[ name ][ n ].x ~= pos.x | ||||
|       or  markers.positions[ name ][ n ].y ~= pos.y | ||||
|       or  markers.positions[ name ][ n ].z ~= pos.z ) then | ||||
|  | ||||
|       return formspec_info.."Please use the marker\nyou placed last\n".. | ||||
|                  "for accessing this menu.\nYou can find said marker at\n".. | ||||
|                  minetest.pos_to_string( markers.positions[ name ][ n ] )..'.]'; | ||||
|    end | ||||
|  | ||||
|    if( n < 4 ) then | ||||
|       return formspec_info.."Please place 4 markers\n - one in each corner\n of your area - first.]"; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    local coords_raw = meta:get_string( 'coords' ); | ||||
|    local coords      = {}; | ||||
|    if( coords_raw ~= nil and coords_raw ~= '' ) then | ||||
|       coords = minetest.deserialize( coords_raw ); | ||||
|    end | ||||
|     | ||||
|  | ||||
|    local opposite = n; | ||||
|    -- the last 4 markers placed ought to form the area | ||||
|    if( true or #coords ~= 2 ) then -- TODO | ||||
|    | ||||
|  | ||||
|       for i=1,3 do | ||||
|  | ||||
|          -- if both coordinates are diffrent, then this may be the opposite marker | ||||
|          if(   ( markers.positions[ name ][ n-i ].x ~=   | ||||
|                  markers.positions[ name ][ n   ].x ) | ||||
|            and ( markers.positions[ name ][ n-i ].z ~=   | ||||
|                  markers.positions[ name ][ n   ].z )) then  | ||||
|  | ||||
|              opposite = n-i; | ||||
|              coords = { markers.positions[ name ][ n   ], | ||||
|                         markers.positions[ name ][ n-i ] }; | ||||
|          end | ||||
|       end | ||||
|  | ||||
|       -- check if they fit | ||||
|       for i=1,3 do | ||||
|  | ||||
|          if(not( ((n-i) == opposite ) | ||||
|              or not(markers.positions[ name ][ n-i ] ) | ||||
|              or  ( markers.positions[ name ][ n-i ].x == coords[ 1 ].x | ||||
|                and markers.positions[ name ][ n-i ].z == coords[ 2 ].z ) | ||||
|              or  ( markers.positions[ name ][ n-i ].x == coords[ 2 ].x | ||||
|                and markers.positions[ name ][ n-i ].z == coords[ 1 ].z ))) then | ||||
|  | ||||
|             return formspec_info.."Error: The last 4 markers\nyou placed do not form\na rectangle.]"; | ||||
|          end | ||||
|  | ||||
|       end | ||||
|  | ||||
|       -- save data      | ||||
|       meta:set_string( 'coords', minetest.serialize( coords ) ); | ||||
|    end | ||||
|  | ||||
|    -- the coordinates are set; we may present an input form now | ||||
|  | ||||
|     -- has the area already been defined? | ||||
|     local area = markers.get_area_by_pos1_pos2( coords[1], coords[2] ); | ||||
|  | ||||
|  | ||||
|     local size = (math.abs( coords[1].x - coords[2].x )+1)  | ||||
|                * (math.abs( coords[1].z - coords[2].z )+1); | ||||
|  | ||||
|     -- check if area is too large | ||||
|     if( markers.MAX_SIZE < size ) then | ||||
|        return formspec_info.."Error: You can only protect\nareas of up to "..tostring( markers.MAX_SIZE ).."m^2.\n".. | ||||
|                              "Your marked area is "..tostring( size ).." m^2 large.]"; | ||||
|     end | ||||
|  | ||||
|     local formspec = 'size[10,7]'.. | ||||
|                'label[0.5,1;The area you marked extends from]'.. | ||||
|                'label[4.7,1;'..minetest.pos_to_string( coords[ 1 ] )..' to '..minetest.pos_to_string( coords[ 2 ] )..'.]'.. | ||||
|                'label[4.7,1.5;It spans '..tostring( math.abs( coords[1].x - coords[2].x )+1 ).. | ||||
|                                ' x '..tostring( math.abs( coords[1].z - coords[2].z )+1 ).. | ||||
|                                ' = '..tostring( size )..' m^2.]'; | ||||
|  | ||||
|     -- display the error message (if there is any) | ||||
|     if( error_msg ~= nil ) then | ||||
|        formspec = formspec.. | ||||
|                     'label[0.5,0.0;Error: ]'.. | ||||
|                     'textarea[5.0,0;4,1.5;info;;'..error_msg..']'; | ||||
|     end | ||||
|        | ||||
|     if( area and area['id'] ) then | ||||
|        formspec =   formspec.. | ||||
|                     'label[0.5,2.0;This is area number ]'.. | ||||
|                     'label[4.7,2.0;'..tostring( area['id'] )..'.]'.. | ||||
|                     'label[0.5,2.5;It is owned by ]'.. | ||||
|                     'label[4.7,2.5;'..tostring( area['owner'] )..'.]'.. | ||||
|                     'label[0.5,3.0;The area is called ]'.. | ||||
|                     'label[4.7,3.0;'..tostring( area['name'] )..'.]'.. | ||||
|                     "button_exit[2,6.0;2,0.5;abort;OK]"; | ||||
|     else | ||||
|        formspec =   formspec.. | ||||
|                     'label[0.5,2.0;Buying this area will cost you ]'.. | ||||
|                     'label[4.7,2.0;'..markers.calculate_area_price_text( coords[1], coords[2], name )..'.]'.. | ||||
|  | ||||
|                     'label[0.5,3.0;Your area ought to go..]'.. | ||||
|                     'label[0.5,3.5;this many blocks up:]'.. | ||||
|                     'field[5.0,4.0;1,0.5;add_height;;40]'.. | ||||
|                     'label[6.0,3.5;(relative to this marker)]'.. | ||||
|  | ||||
|                     'label[0.5,4.0;and this many blocks down:]'.. | ||||
|                     'field[5.0,4.5;1,0.5;add_depth;;10]'.. | ||||
|                     'label[6.0,4.0;(relative to this marker)]'.. | ||||
|  | ||||
|                     'label[0.5,4.5;The area shall be named]'.. | ||||
|                     'field[5.0,5.0;6,0.5;set_area_name;;please enter a name]'.. | ||||
|       | ||||
|                     "button_exit[2,6.0;2,0.5;abort;Abort]".. | ||||
|                     -- code the position in the "Buy area" field | ||||
|                     "button_exit[6,6.0;2,0.5;"..minetest.pos_to_string(pos)..";Buy area]"; | ||||
|     end | ||||
|  | ||||
|    return formspec; | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| -- protect/buy an area | ||||
| markers.marker_on_receive_fields = function(pos, formname, fields, sender) | ||||
|  | ||||
|    if( not( pos )) then | ||||
|       minetest.chat_send_player( name, 'Sorry, could not find the marker you where using to access this formspec.' ); | ||||
|       return; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    local meta  = minetest.env:get_meta( pos ); | ||||
|  | ||||
|    local name  = sender:get_player_name(); | ||||
|  | ||||
|    local coords_string = meta:get_string( 'coords' ); | ||||
|    if( not( coords_string ) or coords_string == '' ) then | ||||
|       minetest.chat_send_player( name, 'Could not find marked area. Please dig and place your markers again!'); | ||||
|       return; | ||||
|    end | ||||
|    local coords = minetest.deserialize( coords_string ); | ||||
|  | ||||
|  | ||||
|    -- do not protect areas twice | ||||
|    local area = markers.get_area_by_pos1_pos2( coords[1], coords[2] ); | ||||
|    if( area ) then | ||||
|  | ||||
|       minetest.chat_send_player( name, 'This area is already protected.'); | ||||
|       return; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    -- check input | ||||
|    local add_height = tonumber( fields['add_height'] ); | ||||
|    local add_depth  = tonumber( fields['add_depth']  ); | ||||
|  | ||||
|    local error_msg = ''; | ||||
|    if(     not( add_height ) or add_height < 0 or add_height > markers.MAX_HEIGHT ) then | ||||
|       minetest.chat_send_player( name, 'Please enter a number between 0 and '..tostring( markers.MAX_HEIGHT ).. | ||||
| 		' in the field where the height of your area is requested. Your area will stretch that many blocks '.. | ||||
| 		'up into the sky from the position of this marker onward.'); | ||||
|       error_msg = 'The height value\nhas to be larger than 0\nand smaller than '..tostring( markers.MAX_HEIGHT ); | ||||
|       | ||||
|    elseif( not( add_depth  ) or add_depth  < 0 or add_depth  > markers.MAX_HEIGHT ) then | ||||
|       minetest.chat_send_player( name, 'Please enter a number between 0 and '..tostring( markers.MAX_HEIGHT ).. | ||||
| 		' in the field where the depth of your area is requested. Your area will stretch that many blocks '.. | ||||
| 		'into the ground from the position of this marker onward.'); | ||||
|       error_msg = 'The depth value\nhas to be larger than 0\nand smaller than '..tostring( markers.MAX_HEIGHT ); | ||||
|  | ||||
|    elseif( add_height + add_depth > markers.MAX_HEIGHT ) then | ||||
|       minetest.chat_send_player( name,  'Sorry, your area exceeds the height limit. Height and depth added have to '.. | ||||
| 		'be smaller than '..tostring( markers.MAX_HEIGHT )..'.'); | ||||
|       error_msg = 'height + depth has to\nbe smaller than '..tostring( markers.MAX_HEIGHT )..'.' | ||||
|  | ||||
|    elseif( not( fields[ 'set_area_name' ] ) or fields['set_area_name'] == 'please enter a name' ) then | ||||
|       minetest.chat_send_player( name, 'Please provide a name for your area, i.e. \"'.. | ||||
| 		tostring( name )..'s first house\" The name ought to describe what you intend to build here.'); | ||||
|       error_msg = 'Please provide a\nname for your area!'; | ||||
|  | ||||
|    else | ||||
|       error_msg = nil; | ||||
|    end | ||||
|   | ||||
|  | ||||
|    if( error_msg ~= nil ) then | ||||
|       minetest.show_formspec( name, "markers:mark", markers.get_marker_formspec(sender, pos, error_msg)); | ||||
|       return; | ||||
|    end | ||||
|  | ||||
|  | ||||
|    -- those coords lack the height component | ||||
|    local pos1 = coords[1]; | ||||
|    local pos2 = coords[2]; | ||||
|    -- apply height values from the formspeck | ||||
|    pos1.y = pos.y + add_height; | ||||
|    pos2.y = pos.y - add_depth; | ||||
|  | ||||
|    pos1, pos2 = areas:sortPos( pos1, pos2 ); | ||||
|  | ||||
|    --minetest.chat_send_player('singleplayer','INPUT: '..minetest.serialize( pos1  )..' pos2: '..minetest.serialize( pos2 )); | ||||
|    minetest.log("action", "[markers] /protect invoked, owner="..name.. | ||||
|                                 " areaname="..fields['set_area_name'].. | ||||
|                                 " startpos="..minetest.pos_to_string(pos1).. | ||||
|                                 " endpos="  ..minetest.pos_to_string(pos2)); | ||||
|  | ||||
|    local canAdd, errMsg = areas:canPlayerAddArea(pos1, pos2, name) | ||||
|    if not canAdd then | ||||
|       minetest.chat_send_player(name, "You can't protect that area: "..errMsg) | ||||
|       minetest.show_formspec( name, "markers:mark", markers.get_marker_formspec(sender, pos, errMsg)); | ||||
|       return | ||||
|    end | ||||
|  | ||||
|    local id = areas:add(name, fields['set_area_name'], pos1, pos2, nil) | ||||
|    areas:save() | ||||
|  | ||||
|    minetest.chat_send_player(name, "Area protected. ID: "..id) | ||||
|  | ||||
|    minetest.show_formspec( name, "markers:mark", markers.get_marker_formspec(sender, pos, nil)); | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
| -- formspec input needs to be handled diffrently | ||||
| markers.form_input_handler = function( player, formname, fields) | ||||
|  | ||||
|    if( formname == "markers:mark" ) then | ||||
|  | ||||
|  | ||||
|       if( not(fields) or fields['abort']) then | ||||
|          return true; | ||||
|       end | ||||
|  | ||||
|       --- decode the position of the marker (which is hidden in the Buy-buttons name | ||||
|       local pos = {}; | ||||
|       for k, v in pairs( fields ) do | ||||
|          if( v == 'Buy area' ) then | ||||
|             pos = minetest.string_to_pos( k ); | ||||
|          end | ||||
|       end | ||||
|       if( pos and pos.x and pos.y and pos.z ) then | ||||
|          markers.marker_on_receive_fields(pos, formname, fields, player); | ||||
|       end | ||||
|       return true; | ||||
|  | ||||
|  | ||||
|    elseif( formname == "markers:info" | ||||
|       and player | ||||
|       and markers.menu_data_by_player[ player:get_player_name() ] ) then | ||||
|  | ||||
|       local res = markers.form_input_handler_areas( player, formname, fields); | ||||
|       if( res ) then | ||||
|          return true; | ||||
|       end | ||||
|    | ||||
|       -- TODO | ||||
| --      minetest.chat_send_player('singleplayer','MARKERS:INFO WITH '..minetest.serialize( fields )); | ||||
|  | ||||
|    else | ||||
|       -- TODO | ||||
| --      minetest.chat_send_player('singleplayer','YOU CALLED '..tostring( formname )..' WITH '..minetest.serialize( fields )); | ||||
|  | ||||
|    end | ||||
|     | ||||
|    return false; | ||||
|  | ||||
| end | ||||
|  | ||||
| minetest.register_on_player_receive_fields( markers.form_input_handler) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| minetest.register_node("markers:mark", { | ||||
| 	description = "Marker", | ||||
| 	tiles = {"markers_mark.png"}, | ||||
| 	drawtype = "nodebox", | ||||
| 	paramtype = "light", | ||||
| 	paramtype2 = "facedir", | ||||
| 	groups = {snappy=2,choppy=2,dig_immediate=3}, | ||||
| 	light_source = 1, | ||||
| 	node_box = { | ||||
| 		type = "fixed", | ||||
| 		fixed = { | ||||
| 			{ -0.1, -0.5, -0.1, 0.1, 1.5, 0.1 }, | ||||
| 			}, | ||||
| 		}, | ||||
|  | ||||
|         after_place_node = function(pos, placer, itemstack) | ||||
|            markers.marker_placed( pos, placer, itemstack ); | ||||
|         end, | ||||
|    | ||||
|         -- the node is digged immediately, so we may as well do all the work in can_dig (any wrong digs are not that critical) | ||||
|         can_dig = function(pos,player)  | ||||
|            return markers.marker_can_dig( pos, player ); | ||||
|         end, | ||||
|  | ||||
|         after_dig_node = function(pos, oldnode, oldmetadata, digger) | ||||
|            return markers.marker_after_dig_node( pos, oldnode, oldmetadata, digger ); | ||||
|         end, | ||||
|  | ||||
| 	on_rightclick = function(pos, node, clicker) | ||||
|  | ||||
|            minetest.show_formspec( clicker:get_player_name(), | ||||
| 				   "markers:mark", | ||||
| 				   markers.get_marker_formspec(clicker, pos, nil) | ||||
| 			); | ||||
| 	end, | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_craft({ | ||||
|    output = "markers:mark 4", | ||||
|    recipe = { { "group:stick" }, | ||||
|               { "default:apple" }, | ||||
|               { "group:stick" }, | ||||
|              } }); | ||||
|  | ||||
							
								
								
									
										74
									
								
								mods/markers/land_title_register.lua
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										74
									
								
								mods/markers/land_title_register.lua
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,74 @@ | ||||
|  | ||||
|  | ||||
| minetest.register_tool( "markers:land_title_register", | ||||
| { | ||||
|     description = "Land title register. Left-click with it to get information about who owns the land you clicked on.", | ||||
|     groups = {},  | ||||
|     inventory_image = "default_book.png", -- TODO | ||||
|     wield_image = "", | ||||
|     wield_scale = {x=1,y=1,z=1}, | ||||
|     stack_max = 1, -- there is no need to have more than one | ||||
|     liquids_pointable = true, -- ground with only water on can be owned as well | ||||
|     -- the tool_capabilities are completely irrelevant here - no need to dig | ||||
|     tool_capabilities = { | ||||
|         full_punch_interval = 1.0, | ||||
|         max_drop_level=0, | ||||
|         groupcaps={ | ||||
|             fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, | ||||
|             snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, | ||||
|             choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0} | ||||
|         } | ||||
|     }, | ||||
|     node_placement_prediction = nil, | ||||
|  | ||||
|     on_place = function(itemstack, placer, pointed_thing) | ||||
|  | ||||
|        if( placer == nil or pointed_thing == nil) then | ||||
|           return itemstack; -- nothing consumed | ||||
|        end | ||||
|        local name = placer:get_player_name(); | ||||
|  | ||||
|        -- the position is what we're actually looking for | ||||
|        local pos  = minetest.get_pointed_thing_position( pointed_thing, 0 ); --under ); | ||||
|         | ||||
|        if( not( pos ) or not( pos.x )) then | ||||
|           minetest.chat_send_player( name, "Position not found."); | ||||
|           return itemstack; | ||||
|        end | ||||
|  | ||||
|        -- this function shows the formspec with the information about the area(s) | ||||
|        markers.show_marker_stone_formspec( placer, pos ); | ||||
|  | ||||
|        return itemstack; -- nothing consumed, nothing changed | ||||
|     end, | ||||
|       | ||||
|  | ||||
|     on_use = function(itemstack, placer, pointed_thing) | ||||
|  | ||||
|        if( placer == nil or pointed_thing == nil) then | ||||
|           return itemstack; -- nothing consumed | ||||
|        end | ||||
|        local name = placer:get_player_name(); | ||||
|  | ||||
|        local pos  = minetest.get_pointed_thing_position( pointed_thing, under ); | ||||
|         | ||||
|        if( not( pos ) or not( pos.x )) then | ||||
|           minetest.chat_send_player( name, "Position not found."); | ||||
|           return itemstack; | ||||
|        end | ||||
|  | ||||
|        -- this function shows the formspec with the information about the area(s) | ||||
|        markers.show_marker_stone_formspec( placer, pos ); | ||||
|  | ||||
|        return itemstack; -- nothing consumed, nothing changed | ||||
|     end, | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_craft({ | ||||
|    output = "markers:land_title_register", | ||||
|    recipe = { { "markers:mark" }, | ||||
|               { "markers:stone" }, | ||||
|               { "default:book"} | ||||
|              } }); | ||||
|  | ||||
							
								
								
									
										24
									
								
								mods/markers/marker_stone.lua
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								mods/markers/marker_stone.lua
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,24 @@ | ||||
|  | ||||
| minetest.register_node("markers:stone", { | ||||
| 	description = "Boundary marker for land administration", | ||||
| 	tiles = {"markers_stone.png", "markers_stone.png", "markers_stone_side.png", | ||||
|                 "markers_stone_side.png", "markers_stone_side.png", "markers_stone_side.png" }, | ||||
| -- no facedir here - we want a fixed north indication! | ||||
| --	paramtype2 = "facedir", | ||||
| 	groups = {cracky=2}, | ||||
| 	legacy_facedir_simple = true, | ||||
| 	is_ground_content = false, | ||||
|  | ||||
| 	on_rightclick = function(pos, node, clicker) | ||||
|  | ||||
|            markers.show_marker_stone_formspec( clicker, pos ); | ||||
| 	end, | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_craft({ | ||||
|    output = "markers:stone", | ||||
|    recipe = { { "markers:mark" }, | ||||
|               { "default:cobble" }, | ||||
|              } }); | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								mods/markers/textures/compass_side_top.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								mods/markers/textures/compass_side_top.png
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 684 B | 
							
								
								
									
										
											BIN
										
									
								
								mods/markers/textures/markers_mark.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								mods/markers/textures/markers_mark.png
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 377 B | 
							
								
								
									
										
											BIN
										
									
								
								mods/markers/textures/markers_stone.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								mods/markers/textures/markers_stone.png
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 793 B | 
							
								
								
									
										
											BIN
										
									
								
								mods/markers/textures/markers_stone_side.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								mods/markers/textures/markers_stone_side.png
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 832 B | 
		Reference in New Issue
	
	Block a user