From 58b1be93ca387ee72b1876a48c1591e6c7755a22 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Tue, 12 Oct 2021 19:57:13 +0200 Subject: [PATCH] Add draft version of ta4 sequencer and other minor improvements --- basis/command.lua | 3 + basis/counting.lua | 42 ++++++ init.lua | 2 + logic/movecontroller.lua | 26 ++-- logic/repeater.lua | 2 + logic/sequencer.lua | 4 + logic/sequencer2.lua | 291 +++++++++++++++++++++++++++++++++++++++ ta3_power/akkubox.lua | 1 + tools/repairkit.lua | 8 +- tools/submenu.lua | 16 ++- 10 files changed, 374 insertions(+), 21 deletions(-) create mode 100644 basis/counting.lua create mode 100644 logic/sequencer2.lua diff --git a/basis/command.lua b/basis/command.lua index 00dc142..f09fe94 100644 --- a/basis/command.lua +++ b/basis/command.lua @@ -27,6 +27,7 @@ local string_split = string.split local NodeDef = techage.NodeDef local Tube = techage.Tube local is_cart_available = minecart.is_nodecart_available +local techage_counting_hit = techage.counting_hit ------------------------------------------------------------------- -- Database @@ -332,6 +333,7 @@ function techage.send_multi(src, numbers, topic, payload) if ninfo and ninfo.name and ninfo.pos then local ndef = NodeDef[ninfo.name] if ndef and ndef.on_recv_message then + techage_counting_hit() ndef.on_recv_message(ninfo.pos, src, topic, payload) end end @@ -344,6 +346,7 @@ function techage.send_single(src, number, topic, payload) if ninfo and ninfo.name and ninfo.pos then local ndef = NodeDef[ninfo.name] if ndef and ndef.on_recv_message then + techage_counting_hit() return ndef.on_recv_message(ninfo.pos, src, topic, payload) end end diff --git a/basis/counting.lua b/basis/counting.lua new file mode 100644 index 0000000..7f64173 --- /dev/null +++ b/basis/counting.lua @@ -0,0 +1,42 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + Count techage commands player related + +]]-- + +local PlayerName +local PlayerPoints = {} + +function techage.counting_start(player_name) + PlayerName = player_name + PlayerPoints[PlayerName] = PlayerPoints[PlayerName] or 0 +end + +function techage.counting_stop() + PlayerName = nil +end + +function techage.counting_hit() + if PlayerName then + PlayerPoints[PlayerName] = PlayerPoints[PlayerName] + 1 + end +end + +local function output() + for name, val in pairs(PlayerPoints) do + minetest.log("action", "[techage] " .. name .. " hat " .. val .. " Punkte") + end + PlayerPoints = {} + minetest.after(60, output) +end + +minetest.after(60, output) + diff --git a/init.lua b/init.lua index acc880b..9ef177a 100644 --- a/init.lua +++ b/init.lua @@ -73,6 +73,7 @@ end -- Basis features local MP = minetest.get_modpath("techage") dofile(MP.."/basis/lib.lua") -- helper functions +dofile(MP.."/basis/counting.lua") -- command counting dofile(MP.."/basis/fake_player.lua") -- dummy player object dofile(MP.."/basis/node_store.lua") dofile(MP.."/basis/gravel_lib.lua") -- ore probability @@ -263,6 +264,7 @@ dofile(MP.."/logic/repeater.lua") dofile(MP.."/logic/programmer.lua") dofile(MP.."/logic/signallamp.lua") dofile(MP.."/logic/sequencer.lua") +dofile(MP.."/logic/sequencer2.lua") dofile(MP.."/logic/timer.lua") dofile(MP.."/logic/lua_logic.lua") -- old dofile(MP.."/logic/logic_block.lua") -- new diff --git a/logic/movecontroller.lua b/logic/movecontroller.lua index 2ecf9ce..0d7b2c2 100644 --- a/logic/movecontroller.lua +++ b/logic/movecontroller.lua @@ -93,7 +93,7 @@ local function attach_single_object(parent, obj, dir, height) local res = obj:get_attach() if not res and prop and prop.collisionbox then dir = table.copy(dir) - dir.y = dir.y - 1 + height - prop.collisionbox[2] + dir.y = dir.y - 1.5 + height - prop.collisionbox[2] dir = vector.multiply(dir, 29) obj:set_attach(parent, "", dir, rot, true) obj:set_properties({visual_size = {x = 2.9, y = 2.9}}) @@ -467,8 +467,8 @@ local WRENCH_MENU = { type = "float", name = "height", label = S("Move block height"), - tooltip = S("Value in the range of -0.5 to 0.5"), - default = "0.5", + tooltip = S("Value in the range of 0.0 to 1.0"), + default = "1.0", }, } @@ -509,8 +509,8 @@ local function move_nodes(pos, lpos1, lpos2, handover) local meta = M(pos) local owner = meta:get_string("owner") local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED - local height = meta:contains("height") and meta:get_float("height") or 0.5 - height = techage.in_range(height, -1, 1) + local height = meta:contains("height") and meta:get_float("height") or 1 + height = techage.in_range(height, 0, 1) if #lpos1 == #lpos2 then for idx = 1, #lpos1 do @@ -738,14 +738,14 @@ techage.register_node({"techage:ta4_movecontroller"}, { end, }) -minetest.register_craft({ - output = "techage:ta4_movecontroller", - recipe = { - {"techage:aluminum", "group:wood","techage:aluminum"}, - {"default:mese_crystal_fragment", "techage:ta4_wlanchip", "default:mese_crystal_fragment"}, - {"group:wood", "basic_materials:gear_steel", "group:wood"}, - }, -}) +--minetest.register_craft({ +-- output = "techage:ta4_movecontroller", +-- recipe = { +-- {"techage:aluminum", "group:wood","techage:aluminum"}, +-- {"default:mese_crystal_fragment", "techage:ta4_wlanchip", "default:mese_crystal_fragment"}, +-- {"group:wood", "basic_materials:gear_steel", "group:wood"}, +-- }, +--}) minetest.register_on_joinplayer(function(player) unlock_player(player) diff --git a/logic/repeater.lua b/logic/repeater.lua index 2617490..8de4e50 100644 --- a/logic/repeater.lua +++ b/logic/repeater.lua @@ -103,7 +103,9 @@ techage.register_node({"techage:ta3_repeater"}, { return false else local numbers = M(pos):get_string("numbers") or "" + techage.counting_start(M(pos):get_string("owner")) techage.send_multi(src, numbers, topic, payload) + techage.counting_stop() end end, on_node_load = function(pos) diff --git a/logic/sequencer.lua b/logic/sequencer.lua index 1ad89bc..141d3a2 100644 --- a/logic/sequencer.lua +++ b/logic/sequencer.lua @@ -106,6 +106,7 @@ local function check_rules(pos, elapsed) nvm.running = nvm.running or false nvm.index = nvm.index or 1 nvm.endless = nvm.endless or false + techage.counting_start(M(pos):get_string("owner")) while true do -- process all rules as long as offs == 0 local rule = nvm.rules[nvm.index] local offs = tonumber(nvm.rules[nvm.index].offs or 1) @@ -119,12 +120,15 @@ local function check_rules(pos, elapsed) if offs > 0 then -- we can't restart the timer within the function om_timer minetest.after(0, restart_timer, pos, offs) + techage.counting_stop() return false end else + techage.counting_stop() return stop_the_sequencer(pos) end end + techage.counting_stop() return false end diff --git a/logic/sequencer2.lua b/logic/sequencer2.lua new file mode 100644 index 0000000..2d8ab58 --- /dev/null +++ b/logic/sequencer2.lua @@ -0,0 +1,291 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2017-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Sequencer + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local logic = techage.logic + +local function strsplit(text) + text = text:gsub("\r\n", "\n") + text = text:gsub("\r", "\n") + return string.split(text, "\n", true) +end + +local function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +local function command(s) + local num, cmd, pld = unpack(string.split(s, " ", false, 2)) + if not num or not cmd then + print("error: Invalid command") + return + end + print(num, cmd, pld) + return {number = num, cmnd = cmd, payload = pld} +end + +local function add_error(text, line_num) + local tbl = {} + for idx, line in ipairs(strsplit(text)) do + if idx == line_num and not string.find(line, '--<<== error') then + tbl[#tbl+1] = line.." --<<== error" + else + tbl[#tbl+1] = line + end + end + return table.concat(tbl, "\n") +end + +local function exception(tRes, line, s) + if tRes then + tRes.line = line + tRes.error = s + end +end + +local function compile(s, tRes) + local tCode = {} + local old_idx = 0 + local start_idx + + print("Compile") + for i, line in ipairs(strsplit(s)) do + line = trim(line) + line = string.split(line, "--", true, 1)[1] or "" + if line ~= "" then + local idx, cmnd1, cmnd2 = unpack(string.split(line, " ", false, 2)) + idx = tonumber(string.match(idx, "^%[(%d+)%]$")) + print(idx, old_idx) + if not idx then + return exception(tRes, i, "Syntax error!") + end + if idx <= old_idx then + return exception(tRes, i, "Order error!") + end + start_idx = start_idx or idx + if old_idx ~= 0 and not tCode[old_idx].next_idx then + tCode[old_idx].next_idx = idx + end + if cmnd1 == "send" then + tCode[idx] = command(cmnd2) + elseif cmnd1 == "goto" then + tCode[idx] = {next_idx = tonumber(cmnd2) or 1} + elseif cmnd1 == nil then + tCode[idx] = {} + end + old_idx = idx + end + end + -- return { + -- start_idx = 1, + -- tCode = { + -- = {number = , cmnd = , payload = , next_idx = }, + -- ... + -- }, + -- } + print(dump(tCode)) + return {start_idx=start_idx, tCode=tCode} +end + +local function check_syntax(meta) + local tRes = {} + local res = compile(meta:get_string("text"), tRes) + if not res then + meta:set_string("err_msg", tRes.error) + meta:set_string("text", add_error(meta:get_string("text"), tRes.line)) + return false + else + meta:set_string("err_msg", "") + return true + end +end + +local function formspec(nvm, meta) + local text = meta:get_string("text") + text = minetest.formspec_escape(text) + local bttn = nvm.running and ("stop;" .. S("Stop")) or ("start;" .. S("Start")) + local style = nvm.running and "style_type[textarea;font=mono;textcolor=#888888;border=false]" or + "style_type[textarea;font=mono;textcolor=#FFFFFF;border=false]" + local textarea = nvm.running and "textarea[0.3,0.2;10,8.3;;;"..text.."]" or + "textarea[0.3,0.2;10,8.3;text;;"..text.."]" + + return "size[10,8]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + style .. + "tabheader[0,0;tab;edit,help;1;;true]" .. + "label[0.1,-0.2;" .. S("Commands") .. ":]" .. + textarea .. + "background[0.1,0.3;9.8,7.0;techage_form_mask.png]" .. + "label[0.1,7.5;" .. meta:get_string("err_msg") .. "]" .. + "button_exit[3.4,7.5;2.2,1;cancel;" .. S("Cancel") .. "]" .. + "button[5.6,7.5;2.2,1;save;" .. S("Save") .. "]" .. + "button[7.8,7.5;2.2,1;" .. bttn .. "]" +end + +local function formspec_help(meta) + local text = "" --minetest.formspec_escape("hepl") + return "size[10,8]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "style_type[textarea;font=mono;textcolor=#FFFFFF]".. + "tabheader[0,0;tab;edit,help;2;;true]".. + "label[0,-0.2;Functions:]".. + --"dropdown[0.3,0.2;10,8.3;functions;"..items..";"..pos.."]".. + "textarea[0.3,1.3;10,8;help;Help:;"..text.."]" +end + +local function restart_timer(pos, time) + local timer = minetest.get_node_timer(pos) + if timer:is_started() then + timer:stop() + end + timer:start(time / 10) +end + +local function node_timer(pos, elapsed) + print("node_timer") + local nvm = techage.get_nvm(pos) + if nvm.running then + local mem = techage.get_mem(pos) + mem.code = mem.code or compile(M(pos):get_string("text")) + if mem.code then + mem.idx = mem.idx or mem.code.start_idx + local code = mem.code.tCode[mem.idx] + if code and code.cmnd then + print(code.number, code.cmnd, code.payload, code.next_idx) + end + if code and code.next_idx then + local offs = code.next_idx - mem.idx + minetest.after(0, restart_timer, pos, math.max(offs, 1)) + mem.idx = code.next_idx + end + end + end + return false +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + --print(dump(fields)) + local meta = M(pos) + local nvm = techage.get_nvm(pos) + local mem = techage.get_mem(pos) + nvm.running = nvm.running or false + + if fields.help then + meta:set_string("formspec", formspec_help(nvm, meta)) + return + elseif fields.edit then + meta:set_string("formspec", formspec(nvm, meta)) + return + end + + if fields.save then + nvm.running = false + meta:set_string("text", fields.text or "") + mem.code = nil + mem.idx = nil + elseif fields.start then + if check_syntax(meta) then + nvm.running = true + meta:set_string("text", fields.text or "") + mem.code = nil + mem.idx = nil + minetest.get_node_timer(pos):start(0.5) + end + elseif fields.stop then + nvm.running = false + minetest.get_node_timer(pos):stop() + end + meta:set_string("formspec", formspec(nvm, meta)) +end + +minetest.register_node("techage:ta4_sequencer", { + description = S("TA4 Sequencer"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta4.png^techage_frame_ta4_top.png", + "techage_filling_ta4.png^techage_frame_ta4_top.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_sequencer.png", + }, + + after_place_node = function(pos, placer) + local meta = M(pos) + local nvm = techage.get_nvm(pos) + logic.after_place_node(pos, placer, "techage:ta4_sequencer", S("TA4 Sequencer")) + logic.infotext(meta, S("TA4 Sequencer"), S("stopped")) + nvm.running = false + meta:set_string("formspec", formspec(nvm, meta)) + end, + + on_receive_fields = on_receive_fields, + + after_dig_node = function(pos, oldnode, oldmetadata) + techage.remove_node(pos, oldnode, oldmetadata) + techage.del_mem(pos) + end, + + on_timer = node_timer, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_craft({ + output = "techage:ta4_sequencer", + recipe = { + {"group:wood", "group:wood", ""}, + {"default:mese_crystal", "techage:wlanchip", ""}, + {"group:wood", "group:wood", ""}, + }, +}) + +techage.register_node({"techage:ta4_sequencer"}, { + on_recv_message = function(pos, src, topic, payload) + if topic == "on" then + start_the_sequencer(pos) + elseif topic == "off" then + -- do not stop immediately + local nvm = techage.get_nvm(pos) + if not nvm.running then + nvm.endless = not (nvm.endless or false) + else + nvm.endless = false + end + elseif topic == "pause" then + stop_the_sequencer(pos) + else + return "unsupported" + end + end, + on_node_load = function(pos) + local nvm = techage.get_nvm(pos) + if nvm.running then + minetest.get_node_timer(pos):start(1) + end + end, +}) + diff --git a/ta3_power/akkubox.lua b/ta3_power/akkubox.lua index debf025..0b3bb40 100644 --- a/ta3_power/akkubox.lua +++ b/ta3_power/akkubox.lua @@ -130,6 +130,7 @@ end local function after_dig_node(pos, oldnode, oldmetadata, digger) local outdir = tonumber(oldmetadata.fields.outdir or 0) Cable:after_dig_node(pos, {outdir}) + techage.remove_node(pos, oldnode, oldmetadata) techage.del_mem(pos) end diff --git a/tools/repairkit.lua b/tools/repairkit.lua index 4b1a593..3245d6f 100644 --- a/tools/repairkit.lua +++ b/tools/repairkit.lua @@ -159,10 +159,10 @@ local function settings_menu(pos, playername) end minetest.register_on_player_receive_fields(function(player, formname, fields) - if formname ~= "techage:ta_formspec" then - return false - end - + if formname ~= "techage:ta_formspec" then + return false + end + local playername = player:get_player_name() local pos = context[playername] if pos then diff --git a/tools/submenu.lua b/tools/submenu.lua index b443c06..6abbc34 100644 --- a/tools/submenu.lua +++ b/tools/submenu.lua @@ -144,7 +144,9 @@ local function evaluate_data(pos, meta, form_def, fields, player_name) for idx,elem in ipairs(form_def) do if elem.type == "number" then if fields[elem.name] then - if fields[elem.name]:find("^[%d ]+$") then + if fields[elem.name] == "" then + meta:set_string(elem.name, "") + elseif fields[elem.name]:find("^[%d ]+$") then local val = tonumber(fields[elem.name]) if value_check(elem, val) then meta:set_int(elem.name, val) @@ -158,14 +160,18 @@ local function evaluate_data(pos, meta, form_def, fields, player_name) end elseif elem.type == "numbers" then if fields[elem.name] then - if fields[elem.name]:find("^[%d ]+$") and value_check(elem, fields[elem.name]) then + if fields[elem.name] == "" then + meta:set_string(elem.name, "") + elseif fields[elem.name]:find("^[%d ]+$") and value_check(elem, fields[elem.name]) then meta:set_string(elem.name, fields[elem.name]) else res = false end end elseif elem.type == "float" then - if fields[elem.name] then + if fields[elem.name] == ""then + meta:set_string(elem.name, "") + elseif fields[elem.name] then local val = tonumber(fields[elem.name]) if val and value_check(elem, val) then meta:set_string(elem.name, val) @@ -174,7 +180,9 @@ local function evaluate_data(pos, meta, form_def, fields, player_name) end end elseif elem.type == "ascii" then - if fields[elem.name] then + if fields[elem.name] == ""then + meta:set_string(elem.name, "") + elseif fields[elem.name] then if value_check(elem, fields[elem.name]) then meta:set_string(elem.name, fields[elem.name]) else