minetest.register_tool('tasks:configurator', { description = 'Configurator Wrench', inventory_image = 'tasks_wrench.png', on_use = function(itemstack, user, pointed_thing) local pos = minetest.get_pointed_thing_position(pointed_thing) if pos then local name = user:get_player_name() local node = minetest.get_node(pos) if not minetest.is_protected(pos, name) or minetest.check_player_privs(name, {server = true}) then tasks.player_config[name] = pos if minetest.get_item_group(node.name, 'tasks') > 0 then tasks.configure(pos, name) elseif minetest.get_item_group(node.name, 'door') > 0 then doors.lock(pos, name) elseif minetest.get_item_group(node.name, 'stash') > 0 then tasks.stash(pos, name) elseif minetest.get_item_group(node.name, 'sabotage') > 0 then sabotage.on_rightclick(pos, node, user) end end end end, on_drop = lobby.no_drop }) function tasks.configure(pos, name) local meta = minetest.get_meta(pos) local info_working = meta:get_string('info_working') local info_repair = meta:get_string('info_repair') local time_min = meta:get_int('time_min') or 60 local time_max = meta:get_int('time_max') or 120 local xp = meta:get_int('xp') or 5 local level = meta:get_int('level') or 0 if info_working == '' then info_working = meta:get_string('infotext') end minetest.show_formspec(name, 'tasks:configuration', tasks.configuration_formspec(info_working, info_repair, time_min, time_max, xp, level)) end minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if formname == 'tasks:configuration' then if fields.save then if tasks.is_integer(fields.time_min) and tasks.is_integer(fields.time_max) and tasks.is_integer(fields.xp) and tonumber(fields.time_max) >= tonumber(fields.time_min) and tasks.is_integer(fields.level) then local pos = tasks.player_config[name] local meta = minetest.get_meta(pos) local timer = minetest.get_node_timer(pos) meta:set_int('time_min', math.max(fields.time_min,5)) meta:set_int('time_max', math.max(fields.time_max,20)) meta:set_int('xp', math.max(fields.xp,0)) meta:set_int('level', math.min(fields.level, 4)) meta:set_string('info_working', fields.info_working) meta:set_string('info_repair', fields.info_repair) local random_number = math.random(fields.time_min, fields.time_max) timer:start(random_number) else minetest.chat_send_player(name, 'Please check your inputs.') end end end end) function tasks.configuration_formspec(info_working, info_repair, time_min, time_max, xp, level) local formspec = 'formspec_version[3]'.. 'size[12,10]'.. 'background[-2,-2;16,14;tasks_configurator_ui_bg.png]'.. 'textarea[0,0;12,3.5;;;Set the time range a task can become available within. '.. 'A random number within the range will be used. Minimum time must be 5 or more seconds, '.. 'and max time must be 20 or more seconds. Whole numbers only! '.. 'Right-clicking on an unavailable task will restart the timer with a new random number. '.. 'If you always want the task to take the same length of time to become available simply set both values to the same number.\n'.. 'Enter the amount of XP to be granted to a player in a match. Ghosts will add half this value, '.. 'and players solo playing a level will only get 1 XP.\n'.. 'Levels can be 1-4, if the level is below the sabotage level it can be interacted with while the map is sabotaged.\n'.. 'Do note that not all tasks have configurable infotexts even though they display here.]'.. 'field[0,4.5;12,.6;info_working;Infotext to displayed when the task is unavailable;'..info_working..']'.. 'field[0,5.75;12,.6;info_repair;Infotext to displayed when the task is available;'..info_repair..']'.. 'field[0,7;2,.6;time_min;Min time;'..time_min..']'.. 'field[3.25,7;2,.6;time_max;Max time;'..time_max..']'.. 'field[6.75,7;2,.6;xp;XP;'..xp..']'.. 'field[10,7;2,.6;level;Level;'..level..']'.. 'button_exit[8,9;3,1;save;Submit]' return formspec end function tasks.stash(pos, name) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() inv:set_size('stash', 8) local infotext = meta:get_string('infotext') minetest.show_formspec(name, 'tasks:stash', tasks.stash_formspec(pos, infotext)) end function tasks.stash_formspec(pos, infotext) local spos = pos.x ..','.. pos.y ..','.. pos.z local formspec = 'formspec_version[3]'.. 'size[10.25,7.5]'.. 'listcolors[#00000069;#5a5a5a]'.. 'textarea[.5,1.5;9.75,2;;;Place items above to let people find them in this node. If their search is successful they will randomly get one of the items here. Blanks will give nothing.]'.. 'field[1,3.0;5,.5;infotext;Infotext;'..infotext..']'.. 'list[detached:creative_trash;main;9,2.5;1,1;]'.. 'image[9,2.5;1,1;creative_trash_icon.png]'.. 'list[nodemeta:'..spos..';stash;.25,.25;8,1;]'.. 'list[detached:tasks_stash;main;.25,4.0;8,2;]'.. 'listring[]'.. 'button_exit[4,6.5;2.25,.75;save;Submit]' return formspec end minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if formname == 'tasks:stash' then if fields.save then local pos = tasks.player_config[name] local meta = minetest.get_meta(pos) meta:set_string('infotext', fields.infotext) end end end) minetest.create_detached_inventory('tasks_stash', { allow_put = function(inv, listname, index, stack, player2) return 0 end, allow_take = function(inv, listname, index, stack, player2) local name = player2 and player2:get_player_name() or '' if not creative.is_enabled_for(name) then return 0 end return -1 end, on_move = function(inv, from_list, from_index, to_list, to_index, count, player2) end, }) local stashable = {} minetest.register_on_mods_loaded(function() for name, def in pairs(minetest.registered_items) do local group = def.groups or {} if group.stashable then stashable[name] = def end end local list = {} for name, def in pairs(stashable) do list[#list+1] = name end local stash_inv = minetest.get_inventory({type = 'detached', name = 'tasks_stash'}) stash_inv:set_size('main', #list) stash_inv:set_list('main', list) end)