2016-11-08 01:32:58 -08:00
basic_robot.commands = { } ;
2016-11-21 11:08:21 -08:00
-- set up nodes for planting (for example seeds -> plant) : [nodename] = plant_name
basic_robot.plant_table = { [ " farming:seed_barley " ] = " farming:barley_1 " , [ " farming:beans " ] = " farming:beanpole_1 " , -- so it works with farming redo mod
[ " farming:blueberries " ] = " farming:blueberry_1 " , [ " farming:carrot " ] = " farming:carrot_1 " , [ " farming:cocoa_beans " ] = " farming:cocoa_1 " ,
2017-02-10 00:59:36 -08:00
[ " farming:coffee_beans " ] = " farming:coffee_1 " , [ " farming:corn " ] = " farming:corn_1 " ,
2016-11-21 11:08:21 -08:00
[ " farming:seed_cotton " ] = " farming:cotton_1 " , [ " farming:cucumber " ] = " farming:cucumber_1 " , [ " farming:grapes " ] = " farming:grapes_1 " ,
[ " farming:melon_slice " ] = " farming:melon_1 " , [ " farming:potato " ] = " farming:potato_1 " , [ " farming:pumpkin_slice " ] = " farming:pumpkin_1 " ,
[ " farming:raspberries " ] = " farming:raspberry_1 " , [ " farming:rhubarb " ] = " farming:rhubarb_1 " , [ " farming:tomato " ] = " farming:tomato_1 " ,
[ " farming:seed_wheat " ] = " farming:wheat_1 " }
local function tick ( pos ) -- needed for plants to start growing: minetest 0.4.14 farming
minetest.get_node_timer ( pos ) : start ( math.random ( 166 , 286 ) )
end
2016-11-08 01:32:58 -08:00
local pi = math.pi ;
local function pos_in_dir ( obj , dir ) -- position after we move in specified direction
local yaw = obj : getyaw ( ) ;
local pos = obj : getpos ( ) ;
if dir == 1 then
yaw = yaw + pi / 2 ;
elseif dir == 2 then
yaw = yaw - pi / 2 ;
elseif dir == 3 then
elseif dir == 4 then
yaw = yaw + pi ;
2016-11-14 08:20:04 -08:00
elseif dir == 5 then -- up
2016-11-08 01:32:58 -08:00
pos.y = pos.y + 1
2016-11-14 08:20:04 -08:00
elseif dir == 6 then -- down
pos.y = pos.y - 1
elseif dir == 7 then -- forward, down
2016-11-08 01:32:58 -08:00
pos.y = pos.y - 1
end
2016-11-14 08:20:04 -08:00
if dir < 5 or dir == 7 then -- left, right, back
2016-11-08 01:32:58 -08:00
pos.x = pos.x + math.cos ( yaw )
pos.z = pos.z + math.sin ( yaw )
end
2016-11-14 08:20:04 -08:00
2016-11-08 01:32:58 -08:00
return pos
end
2017-07-01 14:00:16 -07:00
local check_operations = function ( name , quit )
if basic_robot.maxoperations ~= 0 then
local data = basic_robot.data [ name ] ;
2017-07-16 14:27:52 -07:00
local operations = data.operations - 1 ;
if operations >= 0 then
data.operations = operations
else
2017-07-01 14:00:16 -07:00
if quit then
2017-07-16 14:27:52 -07:00
error ( " robot out of available operations in one step. " ) ; return false
2017-07-01 14:00:16 -07:00
end
2017-07-16 14:27:52 -07:00
return false
2017-07-01 14:00:16 -07:00
end
end
end
2016-11-10 04:07:56 -08:00
basic_robot.commands . move = function ( name , dir )
local obj = basic_robot.data [ name ] . obj ;
2016-11-08 01:32:58 -08:00
local pos = pos_in_dir ( obj , dir )
2016-11-14 08:20:04 -08:00
-- can move through walkable nodes
if minetest.registered_nodes [ minetest.get_node ( pos ) . name ] . walkable then return end
2016-11-08 01:32:58 -08:00
-- up; no levitation!
if minetest.get_node ( { x = pos.x , y = pos.y - 1 , z = pos.z } ) . name == " air " and
minetest.get_node ( { x = pos.x , y = pos.y - 2 , z = pos.z } ) . name == " air " then
2016-11-14 08:20:04 -08:00
return false
2016-11-08 01:32:58 -08:00
end
2016-11-10 23:50:02 -08:00
2016-11-08 01:32:58 -08:00
obj : moveto ( pos , true )
2016-11-14 08:20:04 -08:00
-- sit and stand up for model - doenst work for overwriten obj export
-- if dir == 5 then-- up
-- obj:set_animation({x=0,y=0})
-- elseif dir == 6 then -- down
-- obj:set_animation({x=81,y=160})
-- end
return true
2016-11-08 01:32:58 -08:00
end
2016-11-10 04:07:56 -08:00
basic_robot.commands . turn = function ( name , angle )
local obj = basic_robot.data [ name ] . obj ;
2017-07-16 14:27:52 -07:00
local yaw ;
-- more precise turns by 1 degree resolution
local mult = math.pi / 180 ;
local yaw = obj : getyaw ( ) ;
yaw = math.floor ( ( yaw + angle ) / mult + 0.5 ) * mult ;
2016-11-08 01:32:58 -08:00
obj : setyaw ( yaw ) ;
end
2017-07-16 14:27:52 -07:00
basic_robot.digcosts = { -- 1 energy = 1 coal
[ " default:stone " ] = 1 / 25 ,
}
2016-11-10 04:07:56 -08:00
basic_robot.commands . dig = function ( name , dir )
2016-11-22 05:28:49 -08:00
2017-02-06 02:03:30 -08:00
local energy = 0 ;
2017-07-16 14:27:52 -07:00
check_operations ( name , true )
2016-11-22 05:28:49 -08:00
2016-11-10 04:07:56 -08:00
local obj = basic_robot.data [ name ] . obj ;
2016-11-08 01:32:58 -08:00
local pos = pos_in_dir ( obj , dir )
2017-01-18 08:13:17 -08:00
2016-11-08 01:32:58 -08:00
local luaent = obj : get_luaentity ( ) ;
2016-12-21 03:11:57 -08:00
if minetest.is_protected ( pos , luaent.owner ) then return false end
2016-11-10 02:36:22 -08:00
local nodename = minetest.get_node ( pos ) . name ;
2016-12-21 03:11:57 -08:00
if nodename == " air " or nodename == " ignore " then return false end
2016-11-10 02:36:22 -08:00
local spos = obj : get_luaentity ( ) . spawnpos ;
local inv = minetest.get_meta ( spos ) : get_inventory ( ) ;
2017-04-27 00:22:17 -07:00
2017-07-16 14:27:52 -07:00
--require energy to dig
if basic_robot.dig_require_energy then
local digcost = basic_robot.digcosts [ nodename ] ;
if digcost then
local data = basic_robot.data [ name ] ;
local energy = ( data.menergy or 0 ) - digcost ;
if energy < 0 then
return false , " need " .. digcost .. " energy "
2017-04-27 00:22:17 -07:00
end
2017-07-16 14:27:52 -07:00
data.menergy = energy ;
2017-04-27 00:22:17 -07:00
end
end
2016-11-10 02:36:22 -08:00
if not inv then return end
2016-11-21 11:08:21 -08:00
--inv:add_item("main",ItemStack( nodename ));
2016-11-10 02:36:22 -08:00
2016-11-21 11:08:21 -08:00
basic_robot.give_drops ( nodename , inv ) ;
minetest.set_node ( pos , { name = " air " } )
2016-12-10 01:50:48 -08:00
2016-11-21 11:08:21 -08:00
--DS: sounds
local sounds = minetest.registered_nodes [ nodename ] . sounds
2016-11-14 08:20:04 -08:00
if sounds then
local sound = sounds.dug
if sound then
2017-01-18 08:13:17 -08:00
minetest.sound_play ( sound , { pos = pos , max_hear_distance = 10 } )
2016-11-14 08:20:04 -08:00
end
end
return true
2016-11-08 01:32:58 -08:00
end
2016-11-14 08:20:04 -08:00
basic_robot.commands . insert_item = function ( name , item , inventory , dir )
local obj = basic_robot.data [ name ] . obj ;
local tpos = pos_in_dir ( obj , dir ) ; -- position of target block
local luaent = obj : get_luaentity ( ) ;
if minetest.is_protected ( tpos , luaent.owner ) then return false end
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local meta = minetest.get_meta ( pos ) ;
local tmeta = minetest.get_meta ( tpos ) ;
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
2017-02-10 00:59:36 -08:00
-- fertilize if soil
if item == " farming:fertilizer " then
local stack = ItemStack ( item ) ;
if minetest.get_node ( tpos ) . name == " farming:soil_wet " and ( meta : get_int ( " admin " ) == 1 or inv : contains_item ( " main " , stack ) ) then
inv : remove_item ( " main " , stack ) ;
local nutrient = tmeta : get_int ( " nutrient " ) ; nutrient = nutrient + 10 ; if nutrient > 20 then nutrient = 20 end
tmeta : set_int ( " nutrient " , nutrient ) ;
minetest.set_node ( { x = tpos.x , y = tpos.y + 1 , z = tpos.z } , { name = " air " } )
return true
end
end
2016-11-14 08:20:04 -08:00
local tinv = minetest.get_meta ( tpos ) : get_inventory ( ) ;
if not inventory then inventory = " main " ; end
--if not inv then return end
local stack = ItemStack ( item ) ;
if ( not inv : contains_item ( " main " , stack ) or not tinv : room_for_item ( inventory , stack ) ) and meta : get_int ( " admin " ) ~= 1 then
return false
end
tinv : add_item ( inventory , stack ) ;
inv : remove_item ( " main " , stack ) ;
return true
end
basic_robot.commands . take_item = function ( name , item , inventory , dir )
local obj = basic_robot.data [ name ] . obj ;
local tpos = pos_in_dir ( obj , dir ) ; -- position of target block
local luaent = obj : get_luaentity ( ) ;
if minetest.is_protected ( tpos , luaent.owner ) then return false end
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
if basic_robot.bad_inventory_blocks [ minetest.get_node ( tpos ) . name ] then return false end -- dont allow take from
local meta = minetest.get_meta ( pos ) ;
local tmeta = minetest.get_meta ( tpos ) ;
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
local tinv = minetest.get_meta ( tpos ) : get_inventory ( ) ;
if not inventory then inventory = " main " ; end
--if not inv then return end
local stack = ItemStack ( item ) ;
2016-11-27 14:24:35 -08:00
local contains = tinv : contains_item ( inventory , stack ) ;
if ( not contains or not inv : room_for_item ( " main " , stack ) ) and meta : get_int ( " admin " ) ~= 1 then
2016-11-14 08:20:04 -08:00
return false
end
inv : add_item ( " main " , stack ) ;
tinv : remove_item ( inventory , stack ) ;
2017-01-19 03:04:12 -08:00
return true
2016-11-14 08:20:04 -08:00
end
2017-02-06 02:03:30 -08:00
-- check_inventory(item, inventory, position)
--if position>0 then it returns name of item at that position
basic_robot.commands . check_inventory = function ( name , itemname , inventory , position , dir )
2016-12-21 03:11:57 -08:00
local obj = basic_robot.data [ name ] . obj ;
local tpos ;
if dir ~= 0 then
tpos = pos_in_dir ( obj , dir ) ; -- position of target block in front
else
tpos = obj : get_luaentity ( ) . spawnpos ;
end
local tinv = minetest.get_meta ( tpos ) : get_inventory ( ) ;
2017-02-06 02:03:30 -08:00
if not position then position = - 1 end
if position > 0 then
return tinv : get_stack ( inventory , position ) : to_string ( )
end
if itemname == " " then
return tinv : is_empty ( inventory )
end
2016-12-21 03:11:57 -08:00
local stack = ItemStack ( itemname ) ;
if not inventory then inventory = " main " ; end
return tinv : contains_item ( inventory , stack ) ;
end
2016-11-14 08:20:04 -08:00
2016-12-10 01:50:48 -08:00
basic_robot.no_teleport_table = {
[ " itemframes:item " ] = true ,
[ " signs:text " ] = true ,
2017-04-02 23:37:00 -07:00
[ " basic_robot:robot " ] = true ,
[ " robot " ] = true ,
2016-12-10 01:50:48 -08:00
}
2017-02-06 02:03:30 -08:00
2016-12-10 01:50:48 -08:00
basic_robot.commands . pickup = function ( r , name )
if r > 8 then return false end
2016-12-21 03:11:57 -08:00
2016-12-10 01:50:48 -08:00
local pos = basic_robot.data [ name ] . obj : getpos ( ) ;
local spos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local meta = minetest.get_meta ( spos ) ;
local inv = minetest.get_meta ( spos ) : get_inventory ( ) ;
2017-02-06 02:03:30 -08:00
local picklist = { } ;
2016-12-10 01:50:48 -08:00
for _ , obj in pairs ( minetest.get_objects_inside_radius ( { x = pos.x , y = pos.y , z = pos.z } , r ) ) do
local lua_entity = obj : get_luaentity ( )
2016-12-21 03:11:57 -08:00
if not obj : is_player ( ) and lua_entity and lua_entity.itemstring then
local detected_obj = lua_entity.itemstring or " "
2016-12-10 01:50:48 -08:00
if not basic_robot.no_teleport_table [ detected_obj ] then -- object on no teleport list
-- put item in chest
local stack = ItemStack ( lua_entity.itemstring )
2017-02-06 02:03:30 -08:00
picklist [ # picklist + 1 ] = detected_obj ;
2016-12-10 01:50:48 -08:00
if inv : room_for_item ( " main " , stack ) then
inv : add_item ( " main " , stack ) ;
end
2017-04-02 23:37:00 -07:00
obj : remove ( ) ;
2016-12-10 01:50:48 -08:00
end
end
end
2017-02-06 02:03:30 -08:00
if not picklist [ 1 ] then return nil end
return picklist
2016-12-10 01:50:48 -08:00
end
2016-11-14 08:20:04 -08:00
2016-11-10 04:07:56 -08:00
basic_robot.commands . read_node = function ( name , dir )
local obj = basic_robot.data [ name ] . obj ;
2016-11-08 01:32:58 -08:00
local pos = pos_in_dir ( obj , dir )
return minetest.get_node ( pos ) . name or " "
end
2017-02-10 00:59:36 -08:00
basic_robot.commands . read_text = function ( name , mode , dir , stringname )
if not mode then mode = 0 end
2016-11-10 23:50:02 -08:00
local obj = basic_robot.data [ name ] . obj ;
local pos = pos_in_dir ( obj , dir )
2017-02-10 00:59:36 -08:00
2016-11-21 11:08:21 -08:00
if stringname == nil then
stringname = " infotext "
end
2017-02-10 00:59:36 -08:00
if mode == 1 then return minetest.get_meta ( pos ) : get_int ( stringname ) else
return minetest.get_meta ( pos ) : get_string ( stringname ) or " " end
2016-11-10 23:50:02 -08:00
end
2016-11-08 01:32:58 -08:00
2016-12-24 03:36:03 -08:00
basic_robot.commands . write_text = function ( name , dir , text )
local obj = basic_robot.data [ name ] . obj ;
local pos = pos_in_dir ( obj , dir )
local luaent = obj : get_luaentity ( ) ;
if minetest.is_protected ( pos , luaent.owner ) then return false end
minetest.get_meta ( pos ) : set_string ( " infotext " , text or " " )
return true
end
2017-04-27 00:22:17 -07:00
basic_robot.commands . place = function ( name , nodename , param2 , dir )
2016-11-10 04:07:56 -08:00
local obj = basic_robot.data [ name ] . obj ;
2016-11-08 01:32:58 -08:00
local pos = pos_in_dir ( obj , dir )
local luaent = obj : get_luaentity ( ) ;
2016-11-14 08:20:04 -08:00
if minetest.is_protected ( pos , luaent.owner ) then return false end
if minetest.get_node ( pos ) . name ~= " air " then return false end
2016-11-10 02:36:22 -08:00
local spos = obj : get_luaentity ( ) . spawnpos ;
2016-11-10 04:07:56 -08:00
local meta = minetest.get_meta ( spos ) ;
local inv = meta : get_inventory ( ) ;
2016-11-14 08:20:04 -08:00
if not inv then return false end
2016-12-10 01:50:48 -08:00
if not inv : contains_item ( " main " , ItemStack ( nodename ) ) and meta : get_int ( " admin " ) ~= 1 then return false end
2016-11-10 02:36:22 -08:00
inv : remove_item ( " main " , ItemStack ( nodename ) ) ;
2016-11-10 04:07:56 -08:00
2016-11-14 08:20:04 -08:00
--DS
2016-12-21 03:11:57 -08:00
local registered_node = minetest.registered_nodes [ nodename ] ;
if registered_node then
local sounds = registered_node.sounds
if sounds then
local sound = sounds.place
if sound then
2017-01-18 08:13:17 -08:00
minetest.sound_play ( sound , { pos = pos , max_hear_distance = 10 } )
2016-12-21 03:11:57 -08:00
end
2016-11-14 08:20:04 -08:00
end
end
2016-12-10 01:50:48 -08:00
local placename = basic_robot.plant_table [ nodename ] ;
2016-11-21 11:08:21 -08:00
if placename then
minetest.set_node ( pos , { name = placename } )
tick ( pos ) ; -- needed for seeds to grow
2017-04-27 00:22:17 -07:00
else -- normal place
if param2 then
minetest.set_node ( pos , { name = nodename , param2 = param2 } )
else
minetest.set_node ( pos , { name = nodename } )
end
2016-11-21 11:08:21 -08:00
end
2016-11-14 08:20:04 -08:00
return true
end
basic_robot.commands . attack = function ( name , target ) -- attack range 4, damage 5
2017-03-04 13:03:01 -08:00
local energy = 0 ;
2017-07-16 14:27:52 -07:00
check_operations ( name , true ) ;
2017-03-04 13:03:01 -08:00
2016-11-14 08:20:04 -08:00
local reach = 4 ;
local damage = 5 ;
local tplayer = minetest.get_player_by_name ( target ) ;
if not tplayer then return false end
local obj = basic_robot.data [ name ] . obj ;
local pos = obj : getpos ( ) ;
local tpos = tplayer : getpos ( ) ;
if math.abs ( pos.x - tpos.x ) > reach or math.abs ( pos.y - tpos.y ) > reach or math.abs ( pos.z - tpos.z ) > reach then
return false
end
tplayer : set_hp ( tplayer : get_hp ( ) - damage )
return true
end
2016-12-21 03:11:57 -08:00
basic_robot.commands . grab = function ( name , target )
local reach = 4 ;
local tplayer = minetest.get_player_by_name ( target ) ;
if not tplayer then return false end
local obj = basic_robot.data [ name ] . obj ;
local pos = obj : getpos ( ) ;
local tpos = tplayer : getpos ( ) ;
if math.abs ( pos.x - tpos.x ) > reach or math.abs ( pos.y - tpos.y ) > reach or math.abs ( pos.z - tpos.z ) > reach then
return false
end
if tplayer : get_attach ( ) then
tplayer : set_detach ( )
2017-01-03 08:03:46 -08:00
return false
2016-12-21 03:11:57 -08:00
else
tplayer : set_attach ( obj , " " , { x = 0 , y = 5 , z = 0 } , { x = 0 , y = 0 , z = 0 } )
end
return true
end
2016-11-14 08:20:04 -08:00
basic_robot.commands . read_book = function ( itemstack ) -- itemstack should contain book
2017-07-16 14:27:52 -07:00
local data = itemstack : get_meta ( ) : to_table ( ) . fields -- 0.4.16
--local data = minetest.deserialize(itemstack:get_metadata()) -- pre 0.4.16
2016-11-14 08:20:04 -08:00
if data then
2017-01-18 08:13:17 -08:00
return data.title , data.text ;
2016-11-14 08:20:04 -08:00
else
return nil
end
end
2016-12-21 03:11:57 -08:00
basic_robot.commands . write_book = function ( name , title , text ) -- returns itemstack containing book
2016-11-14 08:20:04 -08:00
local lpp = 14 ;
local new_stack = ItemStack ( " default:book_written " )
local data = { }
2016-12-21 03:11:57 -08:00
if title == " " or not title then title = " program book " .. minetest.get_gametime ( ) end
data.title = title
data.text = text or " "
2016-11-14 08:20:04 -08:00
data.text_len = # data.text
data.page = 1
data.page_max = math.ceil ( ( # data.text : gsub ( " [^ \n ] " , " " ) + 1 ) / lpp )
data.owner = name
2017-07-16 14:27:52 -07:00
--local data_str = minetest.serialize(data) -- pre 0.4.16
--new_stack:set_metadata(data_str);
new_stack : get_meta ( ) : from_table ( { fields = data } ) -- 0.4.16
2016-11-14 08:20:04 -08:00
return new_stack ;
end
2016-11-21 11:08:21 -08:00
basic_robot.give_drops = function ( nodename , inv ) -- gives apropriate drops when node is dug
local table = minetest.registered_items [ nodename ] ;
local dropname ;
if table ~= nil then --put in chest
if table.drop ~= nil then -- drop handling
if table.drop . items then
--handle drops better, emulation of drop code
local max_items = table.drop . max_items or 0 ;
if max_items == 0 then -- just drop all the items (taking the rarity into consideration)
max_items = # table.drop . items or 0 ;
end
local drop = table.drop ;
local i = 0 ;
for k , v in pairs ( drop.items ) do
if i > max_items then break end ; i = i + 1 ;
local rare = v.rarity or 1 ;
if math.random ( 1 , rare ) == 1 then
dropname = v.items [ math.random ( 1 , # v.items ) ] ; -- pick item randomly from list
inv : add_item ( " main " , dropname ) ;
end
end
else
inv : add_item ( " main " , table.drop ) ;
end
else
inv : add_item ( " main " , nodename ) ;
end
end
end
2017-01-18 08:13:17 -08:00
local render_text = function ( text , linesize )
local count = math.floor ( string.len ( text ) / linesize ) + 1 ;
local width = 18 ; local height = 24 ;
local tex = " " ;
local y = 0 ; local x = 0 ;
for i = 1 , string.len ( text ) do
local cb = string.byte ( text , i ) ;
local c = " " ;
if cb == 10 or cb == 13 then
y = y + 1 ; x = 0
else
c = string.format ( " %03d " , cb ) .. " .png "
tex = tex .. " : " .. ( x * width ) .. " , " .. ( y * height ) .. " = " .. c ;
if x == linesize - 1 then y = y + 1 x = 0 else x = x + 1 end
end
end
local background = " (black_screen.png^[resize: " .. ( linesize * width ) .. " x " .. ( linesize * height ) .. " ) " ;
tex = " ([combine: " .. ( linesize * width ) .. " x " .. ( linesize * height ) .. tex .. " ) " ;
tex = background .. " ^ " .. tex ;
return tex ;
2017-02-06 02:03:30 -08:00
end
2017-01-18 08:13:17 -08:00
basic_robot.commands . display_text = function ( obj , text , linesize , size )
2017-02-06 02:03:30 -08:00
if not linesize or linesize < 1 then linesize = 20 end
if not size or size <= 0 then size = 1 end
2017-01-18 08:13:17 -08:00
if string.len ( text ) > linesize * linesize then text = string.sub ( text , 1 , linesize * linesize ) end
local tex = render_text ( text , linesize ) ;
if string.len ( tex ) < 60000 then
obj : set_properties ( { textures = { " arrow.png " , " basic_machine_side.png " , tex , " basic_machine_side.png " , " basic_machine_side.png " , " basic_machine_side.png " } , visual_size = { x = size , y = size } } )
else
self.label ( " error: string too long " )
end
end
2017-02-06 02:03:30 -08:00
local robot_activate_furnace = minetest.registered_nodes [ " default:furnace " ] . on_metadata_inventory_put ; -- this function will activate furnace
2017-01-18 08:13:17 -08:00
basic_robot.commands . activate = function ( name , mode , dir )
local obj = basic_robot.data [ name ] . obj ;
local tpos = pos_in_dir ( obj , dir ) ; -- position of target block in front
local node = minetest.get_node ( tpos ) ;
2017-02-06 02:03:30 -08:00
if node.name == " default:furnace " or node.name == " default:furnace_active " then
if mode > 0 then robot_activate_furnace ( tpos ) end
2017-04-27 00:22:17 -07:00
return true
2017-02-06 02:03:30 -08:00
end
2017-01-18 08:13:17 -08:00
local table = minetest.registered_nodes [ node.name ] ;
if table and table.mesecons and table.mesecons . effector then
else
2017-04-27 00:22:17 -07:00
return false
2017-01-18 08:13:17 -08:00
end -- error
local effector = table.mesecons . effector ;
2017-07-16 14:27:52 -07:00
if not mode then mode = 1 end
2017-01-18 08:13:17 -08:00
if mode > 0 then
2017-04-27 00:22:17 -07:00
if not effector.action_on then return false end
2017-01-18 08:13:17 -08:00
effector.action_on ( tpos , node , 16 )
elseif mode < 0 then
2017-04-27 00:22:17 -07:00
if not effector.action_off then return false end
2017-01-18 08:13:17 -08:00
effector.action_off ( tpos , node , 16 )
end
2017-04-27 00:22:17 -07:00
return true
2017-01-18 08:13:17 -08:00
end
local register_robot_button = function ( R , G , B , type )
minetest.register_node ( " basic_robot:button " .. R .. G .. B ,
{
description = " robot button " ,
tiles = { " robot_button.png^[colorize:# " .. R .. G .. B .. " :180 " } ,
is_ground_content = false ,
groups = { cracky = 3 } ,
on_punch = function ( pos , node , player )
local name = player : get_player_name ( ) ; if name == nil then return end
local round = math.floor ;
local r = 20 ; local ry = 2 * r ;
local ppos = { x = round ( pos.x / r + 0.5 ) * r , y = round ( pos.y / ry + 0.5 ) * ry + 1 , z = round ( pos.z / r + 0.5 ) * r } ;
local meta = minetest.get_meta ( ppos ) ;
local name = meta : get_string ( " name " ) ;
local data = basic_robot.data [ name ] ;
if data then data.keyboard = { x = pos.x , y = pos.y , z = pos.z , puncher = player : get_player_name ( ) , type = type } end
end
} )
end
2017-03-04 13:03:01 -08:00
local register_robot_button_number = function ( number , type )
minetest.register_node ( " basic_robot:button " .. number ,
{
description = " robot button " ,
tiles = { " robot_button " .. number .. " .png " } ,
is_ground_content = false ,
groups = { cracky = 3 } ,
on_punch = function ( pos , node , player )
local name = player : get_player_name ( ) ; if name == nil then return end
local round = math.floor ;
local r = 20 ; local ry = 2 * r ;
local ppos = { x = round ( pos.x / r + 0.5 ) * r , y = round ( pos.y / ry + 0.5 ) * ry + 1 , z = round ( pos.z / r + 0.5 ) * r } ;
local meta = minetest.get_meta ( ppos ) ;
local name = meta : get_string ( " name " ) ;
local data = basic_robot.data [ name ] ;
if data then data.keyboard = { x = pos.x , y = pos.y , z = pos.z , puncher = player : get_player_name ( ) , type = type } end
end
} )
end
2017-01-18 08:13:17 -08:00
register_robot_button ( " FF " , " FF " , " FF " , 1 ) ;
register_robot_button ( " 80 " , " 80 " , " 80 " , 2 ) ;
register_robot_button ( " FF " , " 80 " , " 80 " , 3 ) ;
register_robot_button ( " 80 " , " FF " , " 80 " , 4 ) ;
register_robot_button ( " 80 " , " 80 " , " FF " , 5 ) ;
register_robot_button ( " FF " , " FF " , " 80 " , 6 ) ;
2017-03-04 13:03:01 -08:00
for i = 0 , 9 do register_robot_button_number ( i , i + 7 ) end
2017-01-18 08:13:17 -08:00
-- interactive button for robot: place robot on top of protector to intercept events
basic_robot.commands . keyboard = {
get = function ( name )
local data = basic_robot.data [ name ] ;
if data.keyboard then
local keyboard = data.keyboard ;
local event = { x = keyboard.x , y = keyboard.y , z = keyboard.z , puncher = keyboard.puncher , type = keyboard.type } ;
data.keyboard = nil ;
return event
else
return nil
end
end ,
2017-07-16 14:27:52 -07:00
set = function ( data , pos , type )
local owner = data.owner ;
2017-07-18 05:15:53 -07:00
local spos = data.spawnpos ;
local dist = math.max ( math.abs ( spos.x - pos.x ) , math.abs ( spos.y - pos.y ) , math.abs ( spos.z - pos.z ) ) ;
if dist > 10 then return false end
2017-07-16 14:27:52 -07:00
if minetest.is_protected ( pos , owner ) then return false end -- with fast protect checks this shouldnt be problem!
2017-01-18 08:13:17 -08:00
local nodename ;
if type == 0 then
nodename = " air "
elseif type == 1 then
nodename = " basic_robot:buttonFFFFFF " ;
elseif type == 2 then
nodename = " basic_robot:button808080 " ;
elseif type == 3 then
nodename = " basic_robot:buttonFF8080 " ;
elseif type == 4 then
nodename = " basic_robot:button80FF80 " ;
elseif type == 5 then
nodename = " basic_robot:button8080FF " ;
elseif type == 6 then
nodename = " basic_robot:buttonFFFF80 " ;
2017-03-04 13:03:01 -08:00
elseif type >= 7 then
nodename = " basic_robot:button " .. ( type - 7 ) ;
2017-01-18 08:13:17 -08:00
end
minetest.swap_node ( pos , { name = nodename } )
return true
end ,
2017-02-10 00:59:36 -08:00
}
basic_robot.commands . craftcache = { } ;
2017-07-01 14:00:16 -07:00
basic_robot.commands . craft = function ( item , mode , name )
2017-02-10 00:59:36 -08:00
if not item then return end
local cache = basic_robot.commands . craftcache [ name ] ;
if not cache then basic_robot.commands . craftcache [ name ] = { } ; cache = basic_robot.commands . craftcache [ name ] end
2017-04-27 00:22:17 -07:00
local itemlist = { } ; local output = " " ;
2017-02-10 00:59:36 -08:00
if cache.item == item then -- read cache
itemlist = cache.itemlist ;
2017-04-27 00:22:17 -07:00
output = cache.output ;
2017-02-10 00:59:36 -08:00
else
2017-04-02 23:37:00 -07:00
2017-02-10 00:59:36 -08:00
local craft = minetest.get_craft_recipe ( item ) ;
if craft and craft.type == " normal " and craft.items then else return end
2017-04-27 00:22:17 -07:00
output = craft.output ;
2017-02-10 00:59:36 -08:00
local items = craft.items ;
for _ , item in pairs ( items ) do
itemlist [ item ] = ( itemlist [ item ] or 0 ) + 1 ;
end
cache.item = item ;
2017-04-02 23:37:00 -07:00
cache.itemlist = itemlist ;
2017-04-27 00:22:17 -07:00
cache.output = output ;
2017-04-02 23:37:00 -07:00
-- loop through robot inventory for those "group" items and see if anything in inventory matches group - then replace
-- group name with that item
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
for item , v in pairs ( itemlist ) do
local k = string.find ( item , " group: " ) ;
if k then
local group = string.sub ( item , k + 6 ) ;
-- do we have that in inventory?
local size = inv : get_size ( " main " ) ;
for i = 1 , size do
local itemname = inv : get_stack ( " main " , i ) : get_name ( ) ;
local groups = minetest.registered_items [ itemname ] . groups or { } ;
if groups [ group ] then cache.itemlist [ item ] = nil ; cache.itemlist [ itemname ] = v break end
end
end
end
2017-02-10 00:59:36 -08:00
end
--minetest.chat_send_all(item)
--minetest.chat_send_all(dump(itemlist))
2017-07-01 14:00:16 -07:00
if mode == 1 then return itemlist end
2017-02-10 00:59:36 -08:00
-- check if all items from itemlist..
-- craft item
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
for item , quantity in pairs ( itemlist ) do
local stack = ItemStack ( item .. " " .. quantity ) ;
if not inv : contains_item ( " main " , stack ) then return false end
end
for item , quantity in pairs ( itemlist ) do
local stack = ItemStack ( item .. " " .. quantity ) ;
inv : remove_item ( " main " , stack ) ;
end
2017-04-27 00:22:17 -07:00
inv : add_item ( " main " , ItemStack ( output ) )
2017-02-10 00:59:36 -08:00
return true
2017-03-04 13:03:01 -08:00
end
--FORMS
basic_robot.commands . show_form = function ( name , playername , form )
minetest.show_formspec ( playername , " robot_form " .. name , form )
end
-- handle robots receiving fields
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
if not string.sub ( formname , 1 , 10 ) == " robot_form " then return end
local name = string.sub ( formname , 11 ) ; -- robot name
if not basic_robot.data [ name ] then return end
basic_robot.data [ name ] . read_form = fields ;
basic_robot.data [ name ] . form_sender = player : get_player_name ( ) or " " ;
2017-04-27 00:22:17 -07:00
end )
-- ROBOT TECHNIC
-- amount parameter in generate_power, smelt,... is determined by upgrade level
-- it specifies how much energy will be generated :
basic_robot.technic = { -- data cache
fuels = { } , --[fuel] = value
2017-07-01 14:00:16 -07:00
smelts = { } , -- [item] = [cooktime, cookeditem, aftercookeditem]
2017-04-27 00:22:17 -07:00
grinder_recipes = { --[in] ={fuel cost, out, quantity of material required for processing}
[ " default:stone " ] = { 2 , " default:sand " , 1 } ,
[ " default:cobble " ] = { 1 , " default:gravel " , 1 } ,
[ " default:gravel " ] = { 0.5 , " default:dirt " , 1 } ,
[ " default:dirt " ] = { 0.5 , " default:clay_lump 4 " , 1 } ,
[ " es:aikerum_crystal " ] = { 16 , " es:aikerum_dust 2 " , 1 } , -- added for es mod
[ " es:ruby_crystal " ] = { 16 , " es:ruby_dust 2 " , 1 } ,
[ " es:emerald_crystal " ] = { 16 , " es:emerald_dust 2 " , 1 } ,
[ " es:purpellium_lump " ] = { 16 , " es:purpellium_dust 2 " , 1 } ,
[ " default:obsidian_shard " ] = { 199 , " default:lava_source " , 1 } ,
[ " gloopblocks:basalt " ] = { 1 , " default:cobble " , 1 } , -- enable coble farms with gloopblocks mod
[ " default:ice " ] = { 1 , " default:snow 4 " , 1 } ,
[ " darkage:silt_lump " ] = { 1 , " darkage:chalk_powder " , 1 } ,
[ " default:diamond " ] = { 16 , " basic_machines:diamond_dust_33 2 " , 1 } ,
[ " default:ice " ] = { 1 , " default:snow " , 1 } ,
[ " moreores:tin_lump " ] = { 4 , " basic_machines:tin_dust_33 2 " , 1 } ,
[ " default:obsidian_shard " ] = { 199 , " default:lava_source " , 1 } ,
[ " default:mese_crystal " ] = { 8 , " basic_machines:mese_dust_33 2 " , 1 } ,
[ " moreores:mithril_ingot " ] = { 16 , " basic_machines:mithril_dust_33 2 " , 1 } ,
[ " moreores:silver_ingot " ] = { 5 , " basic_machines:silver_dust_33 2 " , 1 } ,
[ " moreores:tin_ingot " ] = { 4 , " basic_machines:tin_dust_33 2 " , 1 } ,
[ " moreores:mithril_lump " ] = { 16 , " basic_machines:mithril_dust_33 2 " , 1 } ,
[ " default:steel_ingot " ] = { 4 , " basic_machines:iron_dust_33 2 " , 1 } ,
[ " moreores:silver_lump " ] = { 5 , " basic_machines:silver_dust_33 2 " , 1 } ,
[ " default:gold_ingot " ] = { 6 , " basic_machines:gold_dust_33 2 " , 1 } ,
[ " default:copper_ingot " ] = { 4 , " basic_machines:copper_dust_33 2 " , 1 } ,
[ " default:gold_lump " ] = { 6 , " basic_machines:gold_dust_33 2 " , 1 } ,
[ " default:iron_lump " ] = { 4 , " basic_machines:iron_dust_33 2 " , 1 } ,
[ " default:copper_lump " ] = { 4 , " basic_machines:copper_dust_33 2 " , 1 } ,
} ,
compressor_recipes = { --[in] ={fuel cost, out, quantity of material required for processing}
[ " default:snow " ] = { 1 , " default:ice " } ,
[ " default:coalblock " ] = { 16 , " default:diamond " } ,
} ,
}
local chk_machine_level = function ( inv , level ) -- does machine have upgrade to be classified with at least "level"
2017-07-01 14:00:16 -07:00
if level < 1 then level = 1 end
2017-04-27 00:22:17 -07:00
local upg = { " default:diamondblock " , " default:mese " , " default:goldblock " } ;
for i = 1 , # upg do
if not inv : contains_item ( " main " , ItemStack ( upg [ i ] .. " " .. level ) ) then return false end
end
return true
end
2017-07-01 14:00:16 -07:00
2017-04-27 00:22:17 -07:00
basic_robot.commands . machine = {
-- convert fuel into energy
generate_power = function ( name , input , amount ) -- fuel used, if no fuel then amount specifies how much energy builtin generator should produce
2017-07-01 14:00:16 -07:00
check_operations ( name , true )
2017-04-27 00:22:17 -07:00
if amount and amount > 0 then -- attempt to generate power from builtin generator
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
local level = amount * 40 ; -- to generate 1 unit ( coal lump per second ) we need at least upgrade 40
if not chk_machine_level ( inv , level ) then error ( " generate_power : tried to generate " .. amount .. " energy requires upgrade level at least " .. level .. " (blocks of mese, diamond, gold ) " ) return end
local data = basic_robot.data [ name ] ;
local energy = ( data.menergy or 0 ) + amount ;
data.menergy = energy ;
return energy ;
end
local energy = 0 ; -- can only do one step at a run time
2017-07-01 14:00:16 -07:00
2017-04-27 00:22:17 -07:00
if string.find ( input , " " ) then return nil , " 1: can convert only one item at once " end
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
local stack = ItemStack ( input ) ;
if not inv : contains_item ( " main " , stack ) then return nil , " 2: no input material " end
2017-07-16 14:27:52 -07:00
-- read energy value of input ( coal lump = 1)
2017-04-27 00:22:17 -07:00
local add_energy = basic_robot.technic . fuels [ input ] ;
if not add_energy then -- lookup fuel value
local fueladd , afterfuel = minetest.get_craft_result ( { method = " fuel " , width = 1 , items = { stack } } )
if fueladd.time > 0 then
2017-07-16 14:27:52 -07:00
add_energy = fueladd.time / 40 ; -- fix by kurik
2017-07-01 14:00:16 -07:00
else
return nil , " 3: material can not be used as a fuel "
2017-04-27 00:22:17 -07:00
end
2017-07-16 14:27:52 -07:00
if add_energy > 0 then basic_robot.technic . fuels [ input ] = add_energy end
2017-04-27 00:22:17 -07:00
end
inv : remove_item ( " main " , stack ) ;
--add energy
local data = basic_robot.data [ name ] ; energy = data.menergy or 0 ;
energy = energy + add_energy ; data.menergy = energy
return energy ;
end ,
-- smelting
smelt = function ( name , input , amount ) -- input material, amount of energy used for smelt
local energy = 0 ; -- can only do one step at a run time
2017-07-01 14:00:16 -07:00
check_operations ( name , true )
2017-04-27 00:22:17 -07:00
if string.find ( input , " " ) then return nil , " 0: only one item per smelt " end
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local meta = minetest.get_meta ( pos ) ;
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
--read robot energy
local cost = 1 / 40 ;
local smelttimeboost = 1 ;
local level = 1 ;
if amount and amount > 0 then
level = amount * 10 ; -- 10 level required for 1 of amount
if not chk_machine_level ( inv , level ) then
error ( " 3 smelting: need at least level " .. level .. " upgrade for required power " .. amount ) ;
return
end
cost = cost * ( 1 + amount ) ;
smelttimeboost = smelttimeboost + amount ; -- double speed with amount 1
end
local data = basic_robot.data [ name ]
energy = data.menergy or 0 ; -- machine energy
2017-07-01 14:00:16 -07:00
if energy < cost then return nil , " 1: not enough energy " end
2017-04-27 00:22:17 -07:00
local stack = ItemStack ( input ) ;
if not inv : contains_item ( " main " , stack ) then return nil , " 2: no input materials " end
local src_time = ( data.src_time or 0 ) + smelttimeboost ;
-- get smelting data
2017-07-01 14:00:16 -07:00
local smelts = basic_robot.technic . smelts [ input ] ;
2017-04-27 00:22:17 -07:00
if not smelts then
local cooked , aftercooked ;
cooked , aftercooked = minetest.get_craft_result ( { method = " cooking " , width = 1 , items = { stack } } )
if cooked.time > 0 then
2017-07-01 14:00:16 -07:00
basic_robot.technic . smelts [ input ] = { cooked.time , cooked.item , aftercooked.items [ 1 ] } ;
smelts = basic_robot.technic . smelts [ input ] ;
else
return nil , " 3: material can not be smelted "
2017-04-27 00:22:17 -07:00
end
end
local cooktime = smelts [ 1 ] ; local cookeditem = smelts [ 2 ] ; local aftercookeditem = smelts [ 3 ]
-- is smelting done?
data.menergy = energy - cost ;
if src_time >= cooktime then
inv : remove_item ( " main " , stack ) ;
inv : add_item ( " main " , ItemStack ( aftercookeditem ) ) ;
inv : add_item ( " main " , ItemStack ( cookeditem ) ) ;
data.src_time = 0
return true
else
data.src_time = src_time
return math.floor ( src_time / cooktime * 100 * 100 ) / 100
end
end ,
-- grind
grind = function ( name , input )
--[in] ={fuel cost, out, quantity of material required for processing}
local recipe = basic_robot.technic . grinder_recipes [ input ] ;
if not recipe then return nil , " unknown recipe " end
local cost = recipe [ 1 ] ; local output = recipe [ 2 ] ;
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local meta = minetest.get_meta ( pos ) ;
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
--level requirement
2017-07-01 14:00:16 -07:00
local level = math.floor ( ( cost - 1 ) / 3 ) ;
2017-04-27 00:22:17 -07:00
if not chk_machine_level ( inv , level ) then error ( " 0: tried to grind " .. input .. " requires upgrade level at least " .. level ) return end
local stack = ItemStack ( input ) ;
if not inv : contains_item ( " main " , stack ) then return nil , " 1: missing input material " end
local data = basic_robot.data [ name ] ;
local energy = data.menergy or 0 ;
if energy < cost then return nil , " 2: low energy " .. energy .. " / " .. cost end
data.menergy = energy - cost
inv : remove_item ( " main " , ItemStack ( input ) )
inv : add_item ( " main " , ItemStack ( output ) ) ;
return true
end ,
-- compress
compress = function ( name , input )
--[in] ={fuel cost, out, quantity of material required for processing}
local recipe = basic_robot.technic . compressor_recipes [ input ] ;
if not recipe then return nil , " unknown recipe " end
local cost = recipe [ 1 ] ; local output = recipe [ 2 ] ;
local pos = basic_robot.data [ name ] . spawnpos ; -- position of spawner block
local meta = minetest.get_meta ( pos ) ;
local inv = minetest.get_meta ( pos ) : get_inventory ( ) ;
--level requirement
local level = math.floor ( cost / 2 )
if not chk_machine_level ( inv , level ) then error ( " tried to compress " .. input .. " requires upgrade level at least " .. level ) return end
local stack = ItemStack ( input ) ;
if not inv : contains_item ( " main " , stack ) then return nil , " 1: missing input material " end
local data = basic_robot.data [ name ] ;
local energy = data.menergy or 0 ;
if energy < cost then return nil , " 2: low energy " .. energy .. " / " .. cost end
data.menergy = energy - cost
inv : remove_item ( " main " , ItemStack ( input ) )
inv : add_item ( " main " , ItemStack ( output ) ) ;
return true
end ,
transfer_power = function ( name , amount , target )
local pos = basic_robot.data [ name ] . spawnpos ;
local data = basic_robot.data [ name ] ;
local tdata = basic_robot.data [ target ] ;
if not tdata then return nil , " target inactive " end
local energy = 0 ; -- can only do one step at a run time
2017-07-01 14:00:16 -07:00
check_operations ( name , true ) ;
2017-04-27 00:22:17 -07:00
energy = data.menergy or 0 ;
if amount > energy then return nil , " energy too low " end
if not tdata.menergy then tdata.menergy = 0 end
tdata.menergy = tdata.menergy + amount
2017-07-01 14:00:16 -07:00
data.menergy = energy - amount ;
return true
2017-04-27 00:22:17 -07:00
end ,
2017-07-18 05:15:53 -07:00
}
-- CRPYTOGRAPHY
-- rnd 2017
-- nonlinear block stream cypher encryption with scrambling
local scramble = function ( input , password , sgn ) -- permutes text randomly, nice after touch to stream cypher to prevent block analysis
_G.math . randomseed ( password ) ;
local n = # input ;
local permute = { }
for i = 1 , n do permute [ i ] = i end --input:sub(i, i)
for i = n , 2 , - 1 do
local j = math.random ( i - 1 ) ;
local tmp = permute [ j ] ;
permute [ j ] = permute [ i ] ; permute [ i ] = tmp ;
end
local out = { } ;
if sgn > 0 then -- unscramble
for i = 1 , n do out [ permute [ i ] ] = string.sub ( input , i , i ) end
else -- scramble
for i = 1 , n do out [ i ] = string.sub ( input , permute [ i ] , permute [ i ] ) end
end
return table.concat ( out , " " )
end
local scramble_test = function ( )
local text = " testing scrambling 1 2 3 " ;
local enc = scramble ( text , 10 , 1 ) ; -- scramble
local dec = scramble ( enc , 10 , - 1 ) ; -- descramble
say ( " SCRAMBLED--> " .. enc .. " DESCRAMBLED--> " .. dec )
end
--scramble_test()
local get_hash = function ( s , p ) -- basic modular hash, first convert string into 4*8=32 bit int
if not s then return end
local h = 0 ; local n = string.len ( s ) ; local m = 4 ; -- put 4 characters together
local r = 0 ; local i = 0 ;
while i < n do
i = i + 1 ; r = 256 * r + string.byte ( s , i ) ;
if i % m == 0 then h = h + ( r % p ) r = 0 end
end
if i % m ~= 0 then h = h + ( r % p ) end
return h % p
end
local encrypt_ = function ( input , password , sgn ) -- nonlinear stream cypher with extra block offsets
local n = 16 ; -- range 0-255 (for just chat can use 32 - 132)
local m = 65 ;
local ret = " " ; input = input or " " ;
local block_offset = 0 ;
local rndseed = get_hash ( password , 10 ^ 30 ) ;
_G.math . randomseed ( rndseed ) ;
for i = 1 , string.len ( input ) do
local offset = math.random ( n ) ^ 2 + ( i % n ) ^ 3 ; -- yay, nonlinearity is fun
offset = ( offset ^ 2 ) % n
if i % 8 == 1 then -- every 8 characters new offset using strong hash function incorporation recent offset in nonlinear way
block_offset = get_hash ( _G.minetest . get_password_hash ( " " , i * ( offset + 1 ) .. password .. ( block_offset ^ 2 ) ) , n ) ;
if math.random ( 100 ) > 50 then block_offset = block_offset * math.random ( n ) ^ 2 end -- extra fun, why not
end
offset = offset + block_offset ;
local c = string.byte ( input , i ) - m ;
c = m + ( ( c + offset * sgn ) % n ) ;
ret = ret .. string.char ( c )
end
return ret
end
local ascii2hex = function ( input ) -- compress 256 char set to 16 charset range
local ret = " "
for i = 1 , string.len ( input ) do
local c = string.byte ( input , i ) ; -- c = c2*16+c1
local c1 = c % 16 ;
local c2 = ( c - c1 ) / 16 ;
ret = ret .. ( string.char ( c1 + 65 ) .. string.char ( c2 + 65 ) )
end
return ret ;
end
local hex2ascii = function ( input )
local ret = " "
if string.len ( input ) % 2 == 1 then input = input .. " A " end -- padding
for i = 1 , string.len ( input ) , 2 do
local c1 = string.byte ( input , i ) - 65 ; -- c = c2*16+c1
local c2 = string.byte ( input , i + 1 ) - 65 ;
ret = ret .. string.char ( c2 * 16 + c1 )
end
return ret ;
end
-- scheme: encrypt: (stream cypher) encrypt+scramble, decrypt: unscramble+decrypt
local encrypt = function ( input , password )
local ret = encrypt_ ( ascii2hex ( input ) , password , 1 ) ;
local scrambleseed = get_hash ( _G.minetest . get_password_hash ( " " , password ) , 10 ^ 30 ) ; -- strong hash from password, 10^30 possible permutes
return scramble ( ret , scrambleseed , 1 ) ;
end
local decrypt = function ( input , password )
local scrambleseed = get_hash ( _G.minetest . get_password_hash ( " " , password ) , 10 ^ 30 ) ;
input = scramble ( input , scrambleseed , - 1 ) ; -- descramble
return hex2ascii ( encrypt_ ( input , password , - 1 ) )
end
-- just test
local encrypt_test = function ( )
local text = " testing encryption 1 2 3 " ; local password = " hello encryptions " ;
local enc = encrypt ( text , password ) ; local dec = decrypt ( enc , password ) ;
say ( " INPUT: " .. text .. " ENC: " .. enc .. " DEC: " .. dec )
end
basic_robot.commands . crypto = { encrypt = encrypt , decrypt = decrypt , scramble = scramble , basic_hash = get_hash }