command UI now lets multiple cycles be requested.

This commit is contained in:
FaceDeer 2019-09-08 00:20:54 -06:00
parent fe5979a1ab
commit 873236667d
2 changed files with 200 additions and 95 deletions

@ -10,6 +10,8 @@ local listname_to_title =
["fuel"] = S("Fuel"),
}
---------------------------------------------------------------------------------------------------------------------
-- Sequencer commands
-- Yes, this indexing scheme is complicated. It's necessary in order to make sequences
-- language-agnostic, and saves a bit of storage space in the process by shortening and
@ -64,77 +66,6 @@ digtron.default_sequence = function()
return {cmd="seq", cnt=1, cur=1, seq={{cmd="dmb", cnt=1, cur=1}}}
end
-------------------------------------------------------------------------------------------------------------------
-- Sequence tab formspec
-- Recursively builds a formspec representation. Dropdowns and buttons are indexed with : delimiters, eg:
--:1
--:2
--:2:1
--:2:2
--:2:2:1
--:3
local create_sequence_list
create_sequence_list = function(sequence_in, list_out, root_index, x, y)
if sequence_in == nil then
minetest.log("error", "[Digtron] create_sequence_list was given a nil sequence_in parameter")
return y
end
root_index = root_index or ""
x = x or 0
y = y or 0
for i, val in ipairs(sequence_in) do
local index = root_index .. ":" .. i
if val.cur == 0 then
table.insert(list_out, "box[" .. x+2.6 .. "," .. y .. ";0.7,0.5;#FF000088]")
end
table.insert(list_out, "dropdown[".. x ..","..y..";1.75,0.5;sequencer_com"..index..";"..sequencer_dropdown_list..";"
.. sequencer_dropdown_order_reverse[val.cmd].."]field["
.. x+1.8 ..",".. y ..";0.75,0.5;sequencer_cnt"..index..";;"..val.cnt.."]"
.. "field_close_on_enter[sequencer_cnt"..index..";false]"
.. "label[".. x+2.65 .."," .. y+0.25 .. ";" .. S("@1 left", val.cur) .. "]"
.. "button[".. x+3.3 .. ","..y ..";0.75,0.5;sequencer_del"..index..";"..S("Delete").."]")
if val.cmd == "seq" then
table.insert(list_out, "button[".. x+4.1 ..","..y ..";0.75,0.5;sequencer_ins"..index..";"..S("Insert").."]")
y = y + 0.6
-- Recurse into sub-sequence
y = create_sequence_list(val.seq, list_out, index, x+0.25, y)
else
y = y + 0.6
end
end
return y
end
local sequence_tab = function(digtron_id)
local sequence = digtron.get_sequence(digtron_id)
local list_out = {"size[5.75,6.75]"
.. position_and_anchor
.. "real_coordinates[true]"
.. "container[0.2,0.2]"
.. "field[0,0.1;0.7,0.5;cycles;"..S("Cycles")..";" .. sequence.cnt .."]"
.. "field_close_on_enter[cycles;false]"
}
if sequence.cur == 0 then
table.insert(list_out, "box[0.75,0.1;0.7,0.5;#FF000088]")
end
table.insert(list_out,
"label[0.8,0.35;" .. S("@1 left", sequence.cur) .."]"
.. "button[1.5,0.1;1,0.5;execute;"..S("Execute").."]" -- TODO pause
.. "button[2.5,0.1;1,0.5;reset;"..S("Reset").."]"
.. "container_end[]"
.. "container[0.2,1]"
)
local y = create_sequence_list(sequence.seq, list_out)
table.insert(list_out,
"button[0,".. y ..";1,0.5;sequencer_insert_end;"..S("New\nCommand").."]"
.. "container_end[]"
)
return table.concat(list_out)
end
-----------------------------------------------------------------------------------------
--- Maniupulating sequences
@ -153,7 +84,7 @@ local find_next_item_to_execute = function(sequence)
break
end
end
if not found then return nil end -- TODO whoops! Didn't reset a sequence or something
if not found then return nil end -- Sequence is finished
end
end
end
@ -255,6 +186,172 @@ clean_subsequences = function(sequence)
end
end
-----------------------------------------------------------------------------
-- Executing
local cycling_digtrons = {}
local start_command = function(digtron_id, command, count, player_name)
cycling_digtrons[digtron_id] = {
command = command,
count = count,
last_action = minetest.get_gametime(),
player_name = player_name,
}
end
local cancel_command = function(digtron_id)
cycling_digtrons[digtron_id] = nil
end
local is_cycling = function(digtron_id)
return cycling_digtrons[digtron_id] ~= nil
end
local command_functions = {
mup = function(digtron_id, pos, facedir, player_name)
return digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_up(facedir)), player_name) end,
mdn = function(digtron_id, pos, facedir, player_name)
return digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_up(facedir), -1)), player_name) end,
mlt = function(digtron_id, pos, facedir, player_name)
return digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_right(facedir), -1)), player_name) end,
mrt = function(digtron_id, pos, facedir, player_name)
return digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_right(facedir)), player_name) end,
mfw = function(digtron_id, pos, facedir, player_name)
return digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_dir(facedir)), player_name) end,
mbk = function(digtron_id, pos, facedir, player_name)
return digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_dir(facedir), -1)), player_name) end,
rlt = function(digtron_id, pos, facedir, player_name)
return digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_up(facedir), -1), player_name) end,
rrt = function(digtron_id, pos, facedir, player_name)
return digtron.rotate(digtron_id, digtron.facedir_to_up(facedir), player_name) end,
rup = function(digtron_id, pos, facedir, player_name)
return digtron.rotate(digtron_id, digtron.facedir_to_right(facedir), player_name) end,
rdn = function(digtron_id, pos, facedir, player_name)
return digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_right(facedir), -1), player_name) end,
rcl = function(digtron_id, pos, facedir, player_name)
return digtron.rotate(digtron_id, digtron.facedir_to_dir(facedir), player_name) end,
rcc = function(digtron_id, pos, facedir, player_name)
return digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_dir(facedir), -1), player_name) end,
dmb = function(digtron_id, pos, facedir, player_name)
return digtron.execute_dig_move_build_cycle(digtron_id, player_name) end,
dmd = function(digtron_id, pos, facedir, player_name)
return digtron.execute_dig_move_build_cycle(digtron_id, player_name, true) end,
seq = function(digtron_id, pos, facedir, player_name)
minetest.chat_send_all("Seq!") -- TODO
return true
end
}
local execute_command = function(digtron_id, command, player_name)
local pos = digtron.get_pos(digtron_id)
local node = minetest.get_node(pos)
if node.name ~= "digtron:controller" then
minetest.log("error", "[Digtron] execute_command was given the command " .. command .. " for " .. digtron_id
.. " by " .. player_name .. " but the node at " .. minetest.pos_to_string(pos) .. " was a " .. node.name)
return
end
local facedir = node.param2
local func = command_functions[command]
if func then
return func(digtron_id, pos, facedir, player_name)
else
minetest.log("error", "[Digtron] " .. digtron_id .. " was given command " .. command .. " but "
.. " that command was not recognized by execute_command.")
return false
end
end
local done_cycling = {}
minetest.register_globalstep(function(dtime)
local gametime = minetest.get_gametime()
for digtron_id, data in pairs(cycling_digtrons) do
if data.last_action < gametime then
local success = execute_command(digtron_id, data.command, data.player_name)
local new_count = data.count - 1
if new_count < 1 or not success then
table.insert(done_cycling, digtron_id)
else
data.count = new_count
data.last_action = gametime
end
end
end
while next(done_cycling) ~= nil do
cycling_digtrons[table.remove(done_cycling)] = nil
end
end)
-------------------------------------------------------------------------------------------------------------------
-- Sequence tab formspec
-- Recursively builds a formspec representation. Dropdowns and buttons are indexed with : delimiters, eg:
--:1
--:2
--:2:1
--:2:2
--:2:2:1
--:3
local create_sequence_list
create_sequence_list = function(sequence_in, list_out, root_index, x, y)
if sequence_in == nil then
minetest.log("error", "[Digtron] create_sequence_list was given a nil sequence_in parameter")
return y
end
root_index = root_index or ""
x = x or 0
y = y or 0
for i, val in ipairs(sequence_in) do
local index = root_index .. ":" .. i
if val.cur == 0 then
table.insert(list_out, "box[" .. x+2.6 .. "," .. y .. ";0.7,0.5;#FF000088]")
end
table.insert(list_out, "dropdown[".. x ..","..y..";1.75,0.5;sequencer_com"..index..";"..sequencer_dropdown_list..";"
.. sequencer_dropdown_order_reverse[val.cmd].."]field["
.. x+1.8 ..",".. y ..";0.75,0.5;sequencer_cnt"..index..";;"..val.cnt.."]"
.. "field_close_on_enter[sequencer_cnt"..index..";false]"
.. "label[".. x+2.65 .."," .. y+0.25 .. ";" .. S("@1 left", val.cur) .. "]"
.. "button[".. x+3.3 .. ","..y ..";0.75,0.5;sequencer_del"..index..";"..S("Delete").."]")
if val.cmd == "seq" then
table.insert(list_out, "button[".. x+4.1 ..","..y ..";0.75,0.5;sequencer_ins"..index..";"..S("Insert").."]")
y = y + 0.6
-- Recurse into sub-sequence
y = create_sequence_list(val.seq, list_out, index, x+0.25, y)
else
y = y + 0.6
end
end
return y
end
local sequence_tab = function(digtron_id)
local sequence = digtron.get_sequence(digtron_id)
local list_out = {"size[5.75,6.75]"
.. position_and_anchor
.. "real_coordinates[true]"
.. "container[0.2,0.2]"
.. "field[0,0.1;0.7,0.5;cycles;"..S("Cycles")..";" .. sequence.cnt .."]"
.. "field_close_on_enter[cycles;false]"
}
if sequence.cur == 0 then
table.insert(list_out, "box[0.75,0.1;0.7,0.5;#FF000088]")
end
table.insert(list_out,
"label[0.8,0.35;" .. S("@1 left", sequence.cur) .."]"
.. "button[1.5,0.1;1,0.5;execute;"..S("Execute").."]" -- TODO pause
.. "button[2.5,0.1;1,0.5;reset;"..S("Reset").."]"
.. "container_end[]"
.. "container[0.2,1]"
)
local y = create_sequence_list(sequence.seq, list_out)
table.insert(list_out,
"button[0,".. y ..";1,0.5;sequencer_insert_end;"..S("New\nCommand").."]"
.. "container_end[]"
)
return table.concat(list_out)
end
-- Handles returned fields for the sequence tab
local update_sequence = function(digtron_id, fields)
local sequence = digtron.get_sequence(digtron_id)
@ -341,8 +438,9 @@ end
-------------------------------------------------------------------------------------------------------
-- Controls tab
local temp_cycles_cache = {} -- TODO
local controls_tab = function(digtron_id)
local sequence = digtron.get_sequence(digtron_id)
return "size[4.2,5]"
.. position_and_anchor
.. "container[0,0]"
@ -350,9 +448,9 @@ local controls_tab = function(digtron_id)
.. "field[1.2,0.3;1.75,1;digtron_name;"..S("Digtron name")..";"
.. minetest.formspec_escape(digtron.get_name(digtron_id)).."]"
.. "field_close_on_enter[digtron_name;false]"
.. "field[2.9,0.3;0.7,1;cycles;"..S("Cycles")..";" .. sequence.cnt .."]"
.. "label[3.2,0.3;" .. S("@1 left", sequence.cur) .."]"
.. "button[3.5,0;1,1;execute;"..S("Execute").."]"
.. "field[2.9,0.3;0.7,1;cycles;"..S("Cycles")..";".. (temp_cycles_cache[digtron_id] or 1) .."]"
.. "field_close_on_enter[cycles;false]"
.. "button[3.3,0;1,1;execute;"..S("Execute").."]"
.. "container_end[]"
.. "container[0,1]"
@ -376,10 +474,9 @@ local controls_tab = function(digtron_id)
.. "button[0.1,1.1;1,1;rot_left;"..S("Yaw Left").."]"
.. "button[2.1,1.1;1,1;rot_right;"..S("Yaw Right").."]"
.. "container_end[]"
end
local update_controls = function(digtron_id, player_name, formname, facedir, fields)
local update_controls = function(digtron_id, pos, player_name, formname, facedir, fields)
local refresh = false
if fields.disassemble then
@ -387,36 +484,39 @@ local update_controls = function(digtron_id, player_name, formname, facedir, fie
minetest.close_formspec(player_name, formname)
end
local cycles = math.max(math.floor(tonumber(fields.cycles) or 1), 1)
temp_cycles_cache[digtron_id] = cycles
-- Translation
if fields.move_forward then
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_dir(facedir)), player_name)
start_command(digtron_id, "mfw", cycles, player_name)
elseif fields.move_back then
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_dir(facedir), -1)), player_name)
start_command(digtron_id, "mbk", cycles, player_name)
elseif fields.move_up then
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_up(facedir)), player_name)
start_command(digtron_id, "mup", cycles, player_name)
elseif fields.move_down then
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_up(facedir), -1)), player_name)
start_command(digtron_id, "mdn", cycles, player_name)
elseif fields.move_left then
digtron.move(digtron_id, vector.add(pos, vector.multiply(digtron.facedir_to_right(facedir), -1)), player_name)
start_command(digtron_id, "mlt", cycles, player_name)
elseif fields.move_right then
digtron.move(digtron_id, vector.add(pos, digtron.facedir_to_right(facedir)), player_name)
start_command(digtron_id, "mrt", cycles, player_name)
-- Rotation
elseif fields.rot_counterclockwise then
digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_dir(facedir), -1), player_name)
start_command(digtron_id, "rcc", cycles, player_name)
elseif fields.rot_clockwise then
digtron.rotate(digtron_id, digtron.facedir_to_dir(facedir), player_name)
start_command(digtron_id, "rcl", cycles, player_name)
elseif fields.rot_up then
digtron.rotate(digtron_id, digtron.facedir_to_right(facedir), player_name)
start_command(digtron_id, "rup", cycles, player_name)
elseif fields.rot_down then
digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_right(facedir), -1), player_name)
start_command(digtron_id, "rdn", cycles, player_name)
elseif fields.rot_left then
digtron.rotate(digtron_id, vector.multiply(digtron.facedir_to_up(facedir), -1), player_name)
start_command(digtron_id, "rlt", cycles, player_name)
elseif fields.rot_right then
digtron.rotate(digtron_id, digtron.facedir_to_up(facedir), player_name)
start_command(digtron_id, "rrt", cycles, player_name)
end
if fields.execute then
digtron.execute_dig_move_build_cycle(digtron_id, player_name)
start_command(digtron_id, "dmb", cycles, player_name)
refresh = true
end
@ -551,7 +651,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if current_tab == 1 then
-- Controls
refresh = update_controls(digtron_id, player_name, formname, node.param2, fields)
refresh = update_controls(digtron_id, pos, player_name, formname, node.param2, fields)
elseif current_tab == 2 then
--Sequencer

@ -736,14 +736,14 @@ local move = function(digtron_id, dest_pos, player_name)
minetest.check_for_falling(removed_pos)
end
end
return true
else
digtron.show_buildable_nodes({}, failed)
minetest.sound_play("digtron_squeal", {gain = 0.5, pos=dest_pos})
return false
end
end
------------------------------------------------------------------------
-- Rotation
@ -800,9 +800,11 @@ local rotate = function(digtron_id, axis, player_name)
minetest.check_for_falling(removed_pos)
end
end
return true
else
digtron.show_buildable_nodes({}, failed)
minetest.sound_play("digtron_squeal", {gain = 0.5, pos=root_pos})
return false
end
end
@ -1155,12 +1157,13 @@ local execute_dig_move_build_cycle = function(digtron_id, player_name, dig_down)
minetest.sound_play("digtron_squeal", {gain = 0.5, pos=old_root_pos})
minetest.chat_send_player(player_name, S("@1 at @2 has encountered an obstacle.",
get_name(digtron_id), minetest.pos_to_string(old_root_pos)))
return false
elseif next(missing_items) ~= nil then
clear_predictive_inventory(digtron_id)
local items = {}
for item, count in ipairs(missing_items) do
local item_def = minetest.registered_items[item]
if item_def == nil then -- Shouldn't be a problem, but don't crash if it does happen somehow
if item_def == nil then -- Shouldn't be possible, but don't crash if it does happen somehow
table.insert(items, count .. " " .. item)
else
table.insert(items, count .. " " .. item_def.description)
@ -1169,6 +1172,7 @@ local execute_dig_move_build_cycle = function(digtron_id, player_name, dig_down)
minetest.chat_send_player(player_name, S("@1 at @2 requires @3 to execute its next build cycle.",
get_name(digtron_id), minetest.pos_to_string(old_root_pos), table.concat(items, ", ")))
minetest.sound_play("digtron_dingding", {gain = 0.5, pos=old_root_pos})
return false
else
digtron.fake_player:update(old_root_pos, player_name)
@ -1210,6 +1214,7 @@ local execute_dig_move_build_cycle = function(digtron_id, player_name, dig_down)
commit_predictive_inventory(digtron_id)
end
return true
end
end