local utils = ... if minetest.get_translator and minetest.get_translator ("lwscratch") then utils.S = minetest.get_translator ("lwscratch") elseif minetest.global_exists ("intllib") then if intllib.make_gettext_pair then utils.S = intllib.make_gettext_pair () else utils.S = intllib.Getter () end else utils.S = function (s) return s end end utils.modpath = minetest.get_modpath ("lwscratch") utils.worldpath = minetest.get_worldpath () utils.robots_list = { } function utils.add_robot_to_list (id, pos) local robot = utils.robots_list[id] if not robot then utils.robots_list[id] = { } robot = utils.robots_list[id] end robot.pos = { x = pos.x, y = pos.y, z = pos.z } end function utils.remove_robot_from_list (id) utils.robots_list[id] = nil end function utils.get_robot_pos (id) local robot = utils.robots_list[id] if robot then return robot.pos end return nil end function utils.stop_robot_by_id (id) local robot = utils.robots_list[id] if robot then utils.robot_stop (robot.pos) return true end return false end function utils.can_interact_with_node (pos, player) if not player or not player:is_player () then return false end if minetest.check_player_privs (player, "protection_bypass") then return true end local meta = minetest.get_meta (pos) if meta then local owner = meta:get_string ("owner") local name = player:get_player_name () if not owner or owner == "" or owner == name then return true end end return false end function utils.new_inventory () local commands = "" for i = 1, utils.commands_inv_size do commands = commands..string.format ("[%d] = '', ", i) end local program = "" for i = 1, utils.program_inv_size do program = program..string.format ("[%d] = '', ", i) end local inv = "{ ".. "value = { [1] = '' }, ".. "program = { "..program.."}, ".. "commands = { "..commands.."}, ".. "storage = { [1] = '', [2] = '', [3] = '', [4] = '', [5] = '', [6] = '', [7] = '', [8] = '', ".. " [9] = '', [10] = '', [11] = '', [12] = '', [13] = '', [14] = '', [15] = '', [16] = '', ".. " [17] = '', [18] = '', [19] = '', [20] = '', [21] = '', [22] = '', [23] = '', [24] = '', ".. " [25] = '', [26] = '', [27] = '', [28] = '', [29] = '', [30] = '', [31] = '', [32] = '' } ".. "}" return inv end function utils.get_program (inv) local program = { } program.cur_line = 0 program.cur_cell = 0 program.loops = { } for l = 1, 50 do program[l] = { } for c = 1, 10 do local stack = inv:get_stack ("program", ((l - 1) * 10) + c) program[l][c] = { } local cmd = program[l][c] if stack then cmd.command = stack:get_name () if utils.is_value_item (stack:get_name ()) or utils.is_action_value_item (stack:get_name ()) or utils.is_condition_value_item (stack:get_name ()) then local meta = stack:get_meta () if meta then cmd.value = meta:get_string ("value") else minetest.log ("error", "lwscratch - unable to get number value.") end end end end end return program end function utils.prep_inventory (inv, program) local ops = { "lwscratch:cmd_act_move_front", "lwscratch:cmd_act_move_back", "lwscratch:cmd_act_move_down", "lwscratch:cmd_act_move_up", "lwscratch:cmd_act_turn_left", "lwscratch:cmd_act_turn_right", "", "", "lwscratch:cmd_act_dig_front", "lwscratch:cmd_act_dig_front_down", "lwscratch:cmd_act_dig_front_up", "lwscratch:cmd_act_dig_back", "lwscratch:cmd_act_dig_back_down", "lwscratch:cmd_act_dig_back_up", "lwscratch:cmd_act_dig_down", "lwscratch:cmd_act_dig_up", "lwscratch:cmd_act_place_front", "lwscratch:cmd_act_place_front_down", "lwscratch:cmd_act_place_front_up", "lwscratch:cmd_act_place_back", "lwscratch:cmd_act_place_back_down", "lwscratch:cmd_act_place_back_up", "lwscratch:cmd_act_place_down", "lwscratch:cmd_act_place_up", "lwscratch:cmd_act_pull", "lwscratch:cmd_act_put", "lwscratch:cmd_act_drop", "lwscratch:cmd_act_trash", "lwscratch:cmd_act_craft", "", "", "", "lwscratch:cmd_act_value_assign", "lwscratch:cmd_act_value_plus", "lwscratch:cmd_act_value_minus", "lwscratch:cmd_act_value_multiply", "lwscratch:cmd_act_value_divide", "", "", "", "lwscratch:cmd_act_stop", "lwscratch:cmd_act_wait", "", "", "", "", "", "", "lwscratch:cmd_value_number", "lwscratch:cmd_value_text", "lwscratch:cmd_value_value", "", "", "", "", "", "lwscratch:cmd_name_front", "lwscratch:cmd_name_front_down", "lwscratch:cmd_name_front_up", "lwscratch:cmd_name_back", "lwscratch:cmd_name_back_down", "lwscratch:cmd_name_back_up", "lwscratch:cmd_name_down", "lwscratch:cmd_name_up", "lwscratch:cmd_stat_if", "lwscratch:cmd_stat_loop", "lwscratch:cmd_op_not", "lwscratch:cmd_op_and", "lwscratch:cmd_op_or", "", "", "", "lwscratch:cmd_cond_counter_equal", "lwscratch:cmd_cond_counter_greater", "lwscratch:cmd_cond_counter_less", "lwscratch:cmd_cond_counter_even", "lwscratch:cmd_cond_counter_odd", "", "", "", "lwscratch:cmd_cond_value_equal", "lwscratch:cmd_cond_value_greater", "lwscratch:cmd_cond_value_less", "lwscratch:cmd_cond_value_even", "lwscratch:cmd_cond_value_odd", "", "", "", "lwscratch:cmd_cond_contains", "lwscratch:cmd_cond_fits", "", "", "", "", "", "", "lwscratch:cmd_cond_detect_front", "lwscratch:cmd_cond_detect_front_down", "lwscratch:cmd_cond_detect_front_up", "lwscratch:cmd_cond_detect_back", "lwscratch:cmd_cond_detect_back_down", "lwscratch:cmd_cond_detect_back_up", "lwscratch:cmd_cond_detect_down", "lwscratch:cmd_cond_detect_up", "lwscratch:cmd_line_insert", "lwscratch:cmd_line_remove", "", "", "", "", "", "", } for i = 1, #ops do inv:set_stack ("commands", i, ItemStack (ops[i])) end if program then for l = 1, #program do local line = program[l] for c = 1, #line do if line[c] and line[c].command then local stack = ItemStack (line[c].command) if stack then if utils.is_value_item (stack:get_name ()) or utils.is_action_value_item (stack:get_name ()) or utils.is_condition_value_item (stack:get_name ()) then local meta = stack:get_meta () if meta then meta:set_string ("value", tostring (line[c].value or "")) meta:set_string ("description", tostring (line[c].value or "")) else minetest.log ("error", "lwscratch - unable to set number value.") end end inv:set_stack ("program", ((l - 1) * 10) + c, stack) else minetest.log ("error", "lwscratch - unable to set program command.") end end end end end end function utils.is_command_item (name) return name:sub (1, 14) == "lwscratch:cmd_" end function utils.is_inventory_item (name) return name:len () > 0 and name:sub (1, 14) ~= "lwscratch:cmd_" end function utils.is_inventory_item_or_blank (name) return name:sub (1, 14) ~= "lwscratch:cmd_" end function utils.is_condition_item (name) return name:sub (1, 19) == "lwscratch:cmd_cond_" end function utils.is_operator_item (name) return name:sub (1, 17) == "lwscratch:cmd_op_" end function utils.is_action_item (name) return name:sub (1, 18) == "lwscratch:cmd_act_" end function utils.is_statement_item (name) return name:sub (1, 19) == "lwscratch:cmd_stat_" end function utils.is_value_item (name) return name:sub (1, 20) == "lwscratch:cmd_value_" end function utils.is_number_item (name) return name == "lwscratch:cmd_value_number" end function utils.is_text_item (name) return name == "lwscratch:cmd_value_text" end function utils.is_variable_item (name) return name == "lwscratch:cmd_value_value" end function utils.is_action_value_item (name) return name:sub (1, 24) == "lwscratch:cmd_act_value_" end function utils.is_condition_value_item (name) return name:sub (1, 25) == "lwscratch:cmd_cond_value_" end function utils.is_name_item (name) return name:sub (1, 19) == "lwscratch:cmd_name_" end function utils.set_owner_formspec (id) return "formspec_version[3]".. "size[8.0,3.0,false]".. "no_prepend[]".. "bgcolor[#769BE6]".. "style[public;bgcolor=green;textcolor=white]".. "style[private_"..tostring (id)..";bgcolor=red;textcolor=white]".. "button_exit[1.0,1.0;2.5,1.0;set_public;Public]".. "button_exit[4.5,1.0;2.5,1.0;private_"..tostring (id)..";Private]" end function utils.robot_stop_formspec (id) return "formspec_version[3]".. "size[4.5,3.0,false]".. "no_prepend[]".. "bgcolor[#769BE6]".. "style_type[button_exit;bgcolor=red;textcolor=white]".. "button_exit[1.0,1.0;2.5,1.0;stop_"..tostring (id)..";Stop]" end function utils.robot_stop (pos) local meta = minetest.get_meta (pos) if meta and meta:get_int ("lwscratch_id") > 0 then minetest.get_node_timer (pos):stop () meta:set_int ("running", 0) meta:set_string ("program", "") local node = minetest.get_node_or_nil (pos) if node then node.name = "lwscratch:robot" minetest.swap_node (pos, node) end end end function utils.robot_run (pos) local meta = minetest.get_meta (pos) if meta then if meta:get_int ("running") == 1 then return false end local inv = meta:get_inventory () if not inv then return false end local program = utils.program:new (utils.get_program (inv), pos) -- check program for errors local result, msg = program:check () if not result then meta:set_string ("error", string.format ("%d, %d: %s", program:line (), program:cell (), msg)) return false else meta:set_string ("error", "") end -- store program and set to running, start node timer program:serialize () meta:set_int ("running", 1) local node = minetest.get_node_or_nil (pos) if node then node.name = "lwscratch:robot_on" minetest.swap_node (pos, node) end minetest.get_node_timer (pos):start (utils.settings.running_tick) end return true end utils.place_substitute = dofile (utils.modpath.."/place_substitute.lua") utils.crafting_mods = dofile (utils.modpath.."/crafting_mods.lua") function utils.get_place_substitute (item) local subst = utils.place_substitute[item] if subst then return subst end return item end function utils.get_crafting_mods (item) return utils.crafting_mods[item] end function utils.get_robot_formspec (pos) local persists = "image_button[21.05,3.0;0.7,0.7;persist_button_off.png;persists;;false;false;persist_button_off.png]" local power = "image_button[20.7,1.0;1.4,1.4;power_button_off.png;power;;false;false;power_button_off.png]" local error_msg = "" local meta = minetest.get_meta (pos) if meta then if meta:get_int ("persists") == 1 then persists = "image_button[21.05,3.0;0.7,0.7;persist_button_on.png;persists;;false;false;persist_button_on.png]" end if meta:get_int ("running") == 1 then power = "image_button[20.7,1.0;1.4,1.4;power_button_on.png;power;;false;false;power_button_on.png]" end local msg = meta:get_string ("error") if msg:len () > 0 then error_msg = "style_type[label;textcolor=red]".. "label[1.0,17.4;"..minetest.formspec_escape (msg).."]".. "style_type[label;textcolor=white]" end end local spec = "formspec_version[3]".. "size[22.8,18.0,false]".. "no_prepend[]".. "bgcolor[#769BE6]".. "field[1.0,1.0;2.5,0.8;name;Robot;${name}]".. "button[3.5,1.0;1.0,0.8;setname;Set]".. "button[4.6,1.0;1.4,0.8;clear_program;Clear]".. "style_type[list;noclip=false;size=1.0,1.0;spacing=0.0,0.0]".. -- value "list[context;value;6.1,0.9;1,1;]\n".. "field[7.2,1.0;3.3,0.8;number_value;Value;]".. "button[10.5,1.0;1.0,0.8;set_value;Set]".. -- program "scrollbaroptions[min=0;max=350;smallstep=30;largestep=70;thumbsize=105;arrows=default]".. "scrollbar[11.0,2.0;0.5,15.0;vertical;program_scroll;0-350]".. "scroll_container[1.0,2.0;10.0,15.0;program_scroll;vertical;0.1]".. "list[context;program;0.0,0.0;10,50;]\n".. "scroll_container_end[]".. -- commands "scrollbaroptions[min=0;max=90;smallstep=10;largestep=10;thumbsize=25;arrows=default]".. "scrollbar[20.0,1.0;0.5,5.0;vertical;commands_scroll;0-90]".. "scroll_container[12.0,1.0;8.0,5.0;commands_scroll;vertical;0.1]".. "list[context;commands;0.0,0.0;8,14;]\n".. "scroll_container_end[]".. power.. persists.. error_msg.. -- inventories "style_type[list;noclip=false;size=1.0,1.0;spacing=0.25,0.25]".. "list[context;storage;12.0,6.7;8,4;]".. "list[current_player;main;12.0,12.2;8,4;]".. "listring[]".. "listcolors[#545454;#6E6E6E;#6281BF]" return spec end --