lwscratch/utils.lua
2021-03-24 19:04:13 +10:00

613 lines
12 KiB
Lua

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
--